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, 1 * 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 case TacticalLines.SPT: 2379 case TacticalLines.FRONTAL_ATTACK: 2380 case TacticalLines.TURNING_MOVEMENT: 2381 case TacticalLines.MOVEMENT_TO_CONTACT: 2382 case TacticalLines.AIRAOA: 2383 case TacticalLines.AAAAA: 2384 case TacticalLines.MAIN: 2385 String axisMod = buildAreaGroupDTGString(tg); 2386 if (tg.Pixels.size() == 3) //one segment 2387 { 2388 midPt = lineutility.MidPointDouble(pt0, pt1, 0); 2389 if(!tg.get_Name().isEmpty()) 2390 { 2391 if(!axisMod.isEmpty()) 2392 axisMod += '\n'; 2393 axisMod += tg.get_Name(); 2394 } 2395 AddIntegralAreaModifier(tg, axisMod, area, 0, midPt, midPt, false); 2396 2397 } else if (tg.Pixels.size() == 4) //2 segments 2398 { 2399 midPt = lineutility.MidPointDouble(pt1, pt2, 0); 2400 if(!tg.get_Name().isEmpty()) 2401 { 2402 if(!axisMod.isEmpty()) 2403 axisMod += '\n'; 2404 axisMod += tg.get_Name(); 2405 } 2406 AddIntegralAreaModifier(tg, axisMod, area, 0, midPt, midPt, false); 2407 } else // 3 or more segments 2408 { 2409 midPt = lineutility.MidPointDouble(pt1, pt2, 0); 2410 AddIntegralAreaModifier(tg, axisMod, area, 0, midPt, midPt, false); 2411 midPt = lineutility.MidPointDouble(pt2, pt3, 0); 2412 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, midPt, midPt, false); 2413 } 2414 modifiersGrouped = true; 2415 break; 2416 } 2417 } 2418 2419 //modifiers aren't grouped or the symbol doesn't leverage grouped modifiers 2420 if(!modifiersGrouped) { 2421 switch (linetype) { 2422 case TacticalLines.PL: 2423 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), toEnd, T1LineFactor, pt0, pt1, false); 2424 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), toEnd, T1LineFactor, ptLast, ptNextToLast, false); 2425 break; 2426 case TacticalLines.DECISION_LINE: 2427 if (tg.get_AS() == null || !tg.get_AS().isEmpty()) 2428 tg.set_AS(GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(tg.get_SymbolId()))); 2429 Bitmap bi = getImageModifier(tg); 2430 2431 POINT2 ptDP1 = lineutility.ExtendLine2Double(pt1, pt0, bi.getWidth() / 2, 0); 2432 POINT2 ptDP2 = lineutility.ExtendLine2Double(ptNextToLast, ptLast, bi.getWidth() / 2, 0); 2433 2434 AddIntegralAreaModifier(tg, bi, toEnd, 0, pt0, ptDP1, false); 2435 AddIntegralAreaModifier(tg, bi, toEnd, 0, ptLast, ptDP2, false); 2436 break; 2437 case TacticalLines.BS_LINE: 2438 case TacticalLines.BBS_LINE: 2439 if (tg.get_T1() == null || tg.get_T1().isEmpty()) { 2440 AddIntegralAreaModifier(tg, tg.get_Name(), toEnd, T1LineFactor, pt0, pt1, false); 2441 AddIntegralAreaModifier(tg, tg.get_Name(), toEnd, T1LineFactor, ptLast, ptNextToLast, false); 2442 } else { 2443 if (tg.get_T1().equalsIgnoreCase("1")) { 2444 for (j = 0; j < tg.Pixels.size() - 1; j++) { 2445 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, tg.Pixels.get(j), tg.Pixels.get(j + 1), false); 2446 } 2447 } else if (tg.get_T1().equalsIgnoreCase("2")) { 2448 AddIntegralAreaModifier(tg, tg.get_Name(), toEnd, T1LineFactor, pt0, pt1, false); 2449 AddIntegralAreaModifier(tg, tg.get_Name(), toEnd, T1LineFactor, ptLast, ptNextToLast, false); 2450 } else if (tg.get_T1().equalsIgnoreCase("3")) { 2451 //either end of the polyline 2452 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2453 stringWidth = metrics.stringWidth(tg.get_Name()); 2454 stringWidth /= 2; 2455 pt2 = lineutility.ExtendAlongLineDouble2(pt1, pt0, dist + stringWidth); 2456 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, pt2, pt2, false); 2457 dist = lineutility.CalcDistanceDouble(ptNextToLast, ptLast); 2458 pt2 = lineutility.ExtendAlongLineDouble2(ptNextToLast, ptLast, dist + stringWidth); 2459 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, pt2, pt2, false); 2460 //the intermediate points 2461 for (j = 1; j < tg.Pixels.size() - 1; j++) { 2462 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, tg.Pixels.get(j), tg.Pixels.get(j), false); 2463 } 2464 } else //t1 is set inadvertantly or for other graphics 2465 { 2466 AddIntegralAreaModifier(tg, tg.get_Name(), toEnd, T1LineFactor, pt0, pt1, false); 2467 AddIntegralAreaModifier(tg, tg.get_Name(), toEnd, T1LineFactor, ptLast, ptNextToLast, false); 2468 } 2469 } 2470 break; 2471 case TacticalLines.BS_AREA: 2472 case TacticalLines.BBS_AREA: 2473 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2474 break; 2475 case TacticalLines.FEBA: 2476 AddIntegralAreaModifier(tg, label, toEnd, 0, pt0, pt1, false); 2477 AddIntegralAreaModifier(tg, label, toEnd, 0, ptLast, ptNextToLast, false); 2478 break; 2479 // T before label 2480 case TacticalLines.FSCL: 2481 pt0 = tg.Pixels.get(0); 2482 pt1 = tg.Pixels.get(1); 2483 pt2 = tg.Pixels.get(tg.Pixels.size() - 1); 2484 pt3 = tg.Pixels.get(tg.Pixels.size() - 2); 2485 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2486 dist2 = lineutility.CalcDistanceDouble(pt2, pt3); 2487 stringWidth = (int) ((double) metrics.stringWidth(tg.get_Name() + " " + label)); 2488 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG())); 2489 if (stringWidth2 > stringWidth) { 2490 stringWidth = stringWidth2; 2491 } 2492 2493 if (tg.Pixels.size() == 2) //one segment 2494 { 2495 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2496 AddModifier2(tg, tg.get_Name() + " " + label, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2497 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2498 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2499 if (dist > 3.5 * stringWidth)//was 28stringwidth+5 2500 { 2501 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2502 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2503 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2504 AddModifier2(tg, tg.get_Name() + " " + label, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2505 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2506 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2507 } 2508 } else //more than one semgent 2509 { 2510 double dist3 = lineutility.CalcDistanceDouble(pt0, pt2); 2511 if (dist > stringWidth + 5 || dist >= dist2 || dist3 > stringWidth + 5) { 2512 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2513 AddModifier2(tg, tg.get_Name() + " " + label, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2514 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2515 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2516 } 2517 if (dist2 > stringWidth + 5 || dist2 > dist || dist3 > stringWidth + 5) { 2518 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2519 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2520 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2521 AddModifier2(tg, tg.get_Name() + " " + label, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2522 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2523 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2524 } 2525 } 2526 break; 2527 // T after label 2528 case TacticalLines.ICL: 2529 case TacticalLines.NFL: 2530 case TacticalLines.BCL_REVD: 2531 case TacticalLines.RFL: 2532 case TacticalLines.BCL: 2533 pt0 = tg.Pixels.get(0); 2534 pt1 = tg.Pixels.get(1); 2535 pt2 = tg.Pixels.get(tg.Pixels.size() - 1); 2536 pt3 = tg.Pixels.get(tg.Pixels.size() - 2); 2537 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2538 dist2 = lineutility.CalcDistanceDouble(pt2, pt3); 2539 String TMod = ""; // Don't add parenthesis if T modifier is empty 2540 2541 2542 int version = SymbolID.getVersion(tg.get_SymbolId()); 2543 if (version < SymbolID.Version_2525E) { 2544 TMod = tg.get_Name(); 2545 stringWidth = (int) ((double) metrics.stringWidth(TMod + " " + label)); 2546 } else if (version == SymbolID.Version_2525E || version == SymbolID.Version_2525Ech1) { 2547 if (linetype == TacticalLines.BCL) { 2548 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) 2549 TMod = " (" + tg.get_Name() + ")"; 2550 stringWidth = (int) ((double) metrics.stringWidth(label + TMod)); 2551 } else { 2552 TMod = tg.get_Name(); 2553 stringWidth = (int) ((double) metrics.stringWidth(tg.get_Name() + " " + label)); 2554 } 2555 } else if ((version == SymbolID.Version_APP6Ech2)) { 2556 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) 2557 TMod += " " + tg.get_Name(); 2558 if (tg.get_AS() != null && !tg.get_AS().isEmpty()) 2559 TMod += " (" + tg.get_AS() + ")"; 2560 stringWidth = (int) ((double) metrics.stringWidth(label + TMod)); 2561 2562 } 2563 2564 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG())); 2565 if (stringWidth2 > stringWidth) { 2566 stringWidth = stringWidth2; 2567 } 2568 2569 if (tg.Pixels.size() == 2) //one segment 2570 { 2571 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2572 AddModifier2(tg, label + TSpace + TMod, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2573 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2574 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2575 if (dist > 3.5 * stringWidth)//was 28stringwidth+5 2576 { 2577 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2578 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2579 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2580 AddModifier2(tg, label + TSpace + TMod, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2581 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2582 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2583 } 2584 } else //more than one semgent 2585 { 2586 double dist3 = lineutility.CalcDistanceDouble(pt0, pt2); 2587 if (dist > stringWidth + 5 || dist >= dist2 || dist3 > stringWidth + 5) { 2588 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2589 AddModifier2(tg, label + TSpace + TMod, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2590 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2591 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2592 } 2593 if (dist2 > stringWidth + 5 || dist2 > dist || dist3 > stringWidth + 5) { 2594 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2595 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2596 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2597 AddModifier2(tg, label + TSpace + TMod, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2598 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2599 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2600 } 2601 } 2602 break; 2603 case TacticalLines.DIRATKSPT: 2604 case TacticalLines.DIRATKAIR: 2605 case TacticalLines.DIRATKGND: 2606 midPt = lineutility.MidPointDouble(pt0, pt1, 0); 2607 //midPt=lineutility.MidPointDouble(pt0, midPt, 0); 2608 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, pt0, midPt, false); 2609 addDTG(tg, aboveMiddle, csFactor, 2 * csFactor, pt0, pt1, metrics); 2610 break; 2611 case TacticalLines.SPT: 2612 case TacticalLines.FRONTAL_ATTACK: 2613 case TacticalLines.TURNING_MOVEMENT: 2614 case TacticalLines.MOVEMENT_TO_CONTACT: 2615 case TacticalLines.AIRAOA: 2616 case TacticalLines.AAAAA: 2617 case TacticalLines.MAIN: 2618 if (tg.Pixels.size() == 3) //one segment 2619 { 2620 midPt = lineutility.MidPointDouble(pt0, pt1, 0); 2621 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, aboveMiddle, 0, midPt, midPt, false); 2622 AddIntegralAreaModifier(tg, tg.get_DTG1(), aboveMiddle, csFactor, midPt, midPt, false); 2623 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 2 * csFactor, midPt, midPt, false); 2624 2625 } else if (tg.Pixels.size() == 4) //2 segments 2626 { 2627 midPt = lineutility.MidPointDouble(pt1, pt2, 0); 2628 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, aboveMiddle, 0, midPt, midPt, false); 2629 AddIntegralAreaModifier(tg, tg.get_DTG1(), aboveMiddle, csFactor, midPt, midPt, false); 2630 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 2 * csFactor, midPt, midPt, false); 2631 } else // 3 or more segments 2632 { 2633 midPt = lineutility.MidPointDouble(pt1, pt2, 0); 2634 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, aboveMiddle, -csFactor / 2, midPt, midPt, false); 2635 AddIntegralAreaModifier(tg, tg.get_DTG1(), aboveMiddle, csFactor / 2, midPt, midPt, false); 2636 midPt = lineutility.MidPointDouble(pt2, pt3, 0); 2637 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, -csFactor / 2, midPt, midPt, false); 2638 } 2639 break; 2640 case TacticalLines.LL: 2641 case TacticalLines.LOD: 2642 case TacticalLines.LDLC: 2643 case TacticalLines.PLD: 2644 case TacticalLines.RELEASE: 2645 case TacticalLines.HOL: 2646 case TacticalLines.BHL: 2647 case TacticalLines.FCL: 2648 case TacticalLines.HOLD: 2649 case TacticalLines.BRDGHD: 2650 case TacticalLines.HOLD_GE: 2651 case TacticalLines.BRDGHD_GE: 2652 case TacticalLines.LOA: 2653 case TacticalLines.IFF_OFF: 2654 case TacticalLines.IFF_ON: 2655 AddIntegralAreaModifier(tg, label, aboveEnd, -csFactor, pt0, pt1, false); 2656 AddIntegralAreaModifier(tg, label, aboveEnd, -csFactor, ptLast, ptNextToLast, false); 2657 break; 2658 case TacticalLines.EWL: 2659 AddIntegralAreaModifier(tg, label, aboveEnd, -csFactor, pt0, pt1, false); 2660 AddIntegralAreaModifier(tg, label, aboveEnd, -csFactor, ptLast, ptNextToLast, false); 2661 tg.set_EchelonSymbol(""); 2662 if (clipRect != null) { 2663 AddBoundaryModifiers(tg, g2d, clipRect); 2664 } else { 2665 AddBoundaryModifiers(tg, g2d, clipArray); 2666 } 2667 break; 2668 case TacticalLines.AIRFIELD: 2669 ur = new POINT2(); 2670 ul = new POINT2(); 2671 ll = new POINT2(); 2672 lr = new POINT2(); 2673 Modifier2.GetMBR(tg, ul, ur, lr, ll); 2674 stringWidth = metrics.stringWidth(tg.get_H()); 2675 pt0.x = ur.x + stringWidth / 2 + 1; 2676 //pt0.x=ptUr.x+1; 2677 //pt0.y=(ptUr.y+ptLr.y)/2-metrics.getFont().getSize() 2678 pt0.y = (ur.y + lr.y) / 2 - font.getSize(); 2679 AddIntegralAreaModifier(tg, tg.get_H(), area, csFactor, pt0, pt0, false); 2680 break; 2681 case TacticalLines.LAUNCH_AREA: 2682 case TacticalLines.DEFENDED_AREA_CIRCULAR: 2683 AddIntegralAreaModifier(tg, label + TDash + tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2684 break; 2685 case TacticalLines.JTAA: 2686 case TacticalLines.SAA: 2687 case TacticalLines.SGAA: 2688 addNModifier(tg); 2689 AddIntegralAreaModifier(tg, label + TDash + tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2690 addDTG(tg, area, csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 2691 break; 2692 case TacticalLines.FORT: 2693 case TacticalLines.ZONE: 2694 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2695 break; 2696 case TacticalLines.BDZ: 2697 AddIntegralAreaModifier(tg, label, area, 0, pt0, pt0, false); 2698 break; 2699 case TacticalLines.ASSAULT: 2700 case TacticalLines.ATKPOS: 2701 case TacticalLines.OBJ: 2702 case TacticalLines.NAI: 2703 case TacticalLines.TAI: 2704 case TacticalLines.BASE_CAMP_REVD: 2705 case TacticalLines.GUERILLA_BASE_REVD: 2706 case TacticalLines.ASSY: 2707 case TacticalLines.EA: 2708 case TacticalLines.DZ: 2709 case TacticalLines.EZ: 2710 case TacticalLines.LZ: 2711 case TacticalLines.PZ: 2712 case TacticalLines.AO: 2713 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2714 break; 2715 case TacticalLines.BASE_CAMP: 2716 case TacticalLines.GUERILLA_BASE: 2717 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, -1 * csFactor, ptCenter, ptCenter, false); 2718 AddModifier(tg, tg.get_H(), area, 0, ptCenter, ptCenter); 2719 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 2720 addNModifier(tg); 2721 addModifierBottomSegment(tg, tg.get_EchelonSymbol()); 2722 break; 2723 case TacticalLines.GENERIC_AREA: 2724 AddIntegralAreaModifier(tg, tg.get_H() + " " + tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, false); 2725 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 2726 addNModifier(tg); 2727 break; 2728 case TacticalLines.AIRHEAD: 2729 GetMBR(tg, ul, ur, lr, ll); 2730 AddIntegralAreaModifier(tg, label, aboveMiddle, csFactor, ll, lr, false); 2731 break; 2732 case TacticalLines.AC: 2733 case TacticalLines.LLTR: 2734 case TacticalLines.MRR: 2735 case TacticalLines.SL: 2736 case TacticalLines.TC: 2737 case TacticalLines.SAAFR: 2738 case TacticalLines.SC: 2739 AddIntegralModifier(tg, "Name: " + tg.get_Name(), aboveMiddle, -7 * csFactor, middleSegment, middleSegment + 1, false); 2740 AddIntegralModifier(tg, "Width: " + removeDecimal(tg.get_AM()), aboveMiddle, -6 * csFactor, middleSegment, middleSegment + 1, false); 2741 AddIntegralModifier(tg, "Min Alt: " + tg.get_X(), aboveMiddle, -5 * csFactor, middleSegment, middleSegment + 1, false); 2742 AddIntegralModifier(tg, "Max Alt: " + tg.get_X1(), aboveMiddle, -4 * csFactor, middleSegment, middleSegment + 1, false); 2743 AddIntegralModifier(tg, "DTG Start: " + tg.get_DTG(), aboveMiddle, -3 * csFactor, middleSegment, middleSegment + 1, false); 2744 AddIntegralModifier(tg, "DTG End: " + tg.get_DTG1(), aboveMiddle, -2 * csFactor, middleSegment, middleSegment + 1, false); 2745 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, 0, middleSegment, middleSegment + 1, false); 2746 break; 2747 case TacticalLines.BEARING_J: 2748 case TacticalLines.BEARING_RDF: 2749 case TacticalLines.BEARING: 2750 case TacticalLines.ELECTRO: 2751 case TacticalLines.BEARING_EW: 2752 case TacticalLines.ACOUSTIC: 2753 case TacticalLines.ACOUSTIC_AMB: 2754 case TacticalLines.TORPEDO: 2755 case TacticalLines.OPTICAL: 2756 midPt = lineutility.MidPointDouble(pt0, pt1, 0); 2757 AddIntegralAreaModifier(tg, label, aboveMiddle, 0, midPt, midPt, true); 2758 pt3 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 3, font.getSize() / 2.0); 2759 AddIntegralAreaModifier(tg, tg.get_H(), aboveMiddle, 1, pt3, pt3, true); 2760 break; 2761 case TacticalLines.ACA: 2762 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, -3 * csFactor, ptCenter, ptCenter, false); 2763 AddIntegralAreaModifier(tg, tg.get_T1(), area, -2 * csFactor, ptCenter, ptCenter, false); 2764 AddIntegralAreaModifier(tg, "MIN ALT: " + tg.get_X(), area, -1 * csFactor, ptCenter, ptCenter, false, "H"); 2765 AddIntegralAreaModifier(tg, "MAX ALT: " + tg.get_X1(), area, 0, ptCenter, ptCenter, false, "H1"); 2766 AddIntegralAreaModifier(tg, "GRID " + tg.get_Location(), area, 1 * csFactor, ptCenter, ptCenter, false, "H2"); 2767 AddModifier2(tg, "EFF " + tg.get_DTG() + WDash, area, 2 * csFactor, ptCenter, ptCenter, false, "W"); 2768 AddModifier2(tg, tg.get_DTG1(), area, 3 * csFactor, ptCenter, ptCenter, false, "W1"); 2769 break; 2770 case TacticalLines.MFP: 2771 pt0 = tg.Pixels.get(middleSegment); 2772 pt1 = tg.Pixels.get(middleSegment + 1); 2773 AddIntegralModifier(tg, label, aboveMiddle, 0, middleSegment, middleSegment + 1, true); 2774 AddIntegralModifier(tg, tg.get_DTG() + WDash, aboveEnd, 1 * csFactor, 0, 1, false); 2775 AddIntegralModifier(tg, tg.get_DTG1(), aboveEnd, 2 * csFactor, 0, 1, false); 2776 break; 2777 case TacticalLines.LINTGT: 2778 AddIntegralModifier(tg, ap, aboveMiddle, -0.7 * csFactor, middleSegment, middleSegment + 1, false); 2779 break; 2780 case TacticalLines.LINTGTS: 2781 AddIntegralModifier(tg, ap, aboveMiddle, -0.7 * csFactor, middleSegment, middleSegment + 1, false); 2782 AddIntegralModifier(tg, label, aboveMiddle, 0.7 * csFactor, middleSegment, middleSegment + 1, false); 2783 break; 2784 case TacticalLines.FPF: 2785 AddIntegralModifier(tg, ap, aboveMiddle, -0.7 * csFactor, 0, 1, false); 2786 AddIntegralModifier(tg, label, aboveMiddle, .7 * csFactor, 0, 1, false); 2787 AddIntegralModifier(tg, tg.get_T1(), aboveMiddle, 1.7 * csFactor, 0, 1, false); 2788 AddIntegralModifier(tg, v, aboveMiddle, 2.7 * csFactor, 0, 1, false); 2789 break; 2790 case TacticalLines.AT: 2791 AddIntegralAreaModifier(tg, ap, area, 0, ptCenter, ptCenter, false); 2792 break; 2793 case TacticalLines.RECTANGULAR: 2794 case TacticalLines.CIRCULAR: 2795 AddIntegralAreaModifier(tg, ap, area, 0, pt0, pt0, false); 2796 break; 2797 case TacticalLines.PBS_CIRCLE: 2798 case TacticalLines.PBS_ELLIPSE: 2799 case TacticalLines.PBS_RECTANGLE: 2800 case TacticalLines.BBS_POINT: 2801 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, pt0, pt0, false); 2802 break; 2803 case TacticalLines.RECTANGULAR_TARGET: 2804 stringWidth = metrics.stringWidth(tg.get_Name()); 2805 POINT2 offsetCenterPoint = new POINT2(ptCenter.x + ((double) stringWidth) / 2.0, ptCenter.y); 2806 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1 * csFactor, offsetCenterPoint, offsetCenterPoint, false); 2807 break; 2808 case TacticalLines.SMOKE: 2809 AddIntegralAreaModifier(tg, ap, area, -csFactor, ptCenter, ptCenter, false); 2810 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, false); 2811 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 2812 break; 2813 case TacticalLines.LINE: 2814 AddIntegralModifier(tg, tg.get_Name(), aboveMiddle, csFactor, middleSegment, middleSegment + 1, false); 2815 break; 2816 case TacticalLines.MINED: 2817 if (tg.isHostile()) { 2818 pt1 = lineutility.MidPointDouble(pt0, pt1, 0); 2819 AddIntegralAreaModifier(tg, tg.get_N(), aboveMiddle, 0, pt0, pt1, true); 2820 if (middleSegment != 0) { 2821 pt0 = tg.Pixels.get(middleSegment); 2822 pt1 = tg.Pixels.get(middleSegment + 1); 2823 pt1 = lineutility.MidPointDouble(pt0, pt1, 0); 2824 AddIntegralAreaModifier(tg, tg.get_N(), aboveMiddle, 0, pt0, pt1, true); 2825 } 2826 } 2827 GetMBR(tg, ul, ur, lr, ll); 2828 AddIntegralAreaModifier(tg, tg.get_H(), aboveMiddle, -1.5 * csFactor, ul, ur, false); 2829 AddIntegralAreaModifier(tg, tg.get_DTG(), aboveMiddle, 1.5 * csFactor, ll, lr, false); 2830 addModifierOnLine("M", tg); 2831 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 2832 break; 2833 case TacticalLines.FENCED: 2834 if (tg.isHostile()) { 2835 pt1 = lineutility.MidPointDouble(pt0, pt1, 0); 2836 AddIntegralAreaModifier(tg, tg.get_N(), aboveMiddle, 0, pt0, pt1, true); 2837 if (middleSegment != 0) { 2838 pt0 = tg.Pixels.get(middleSegment); 2839 pt1 = tg.Pixels.get(middleSegment + 1); 2840 pt1 = lineutility.MidPointDouble(pt0, pt1, 0); 2841 AddIntegralAreaModifier(tg, tg.get_N(), aboveMiddle, 0, pt0, pt1, true); 2842 } 2843 } 2844 addModifierOnLine("M", tg); 2845 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 2846 break; 2847 case TacticalLines.ASLTXING: 2848 if (tg.Pixels.get(1).y > tg.Pixels.get(0).y) { 2849 pt0 = tg.Pixels.get(1); 2850 pt1 = tg.Pixels.get(3); 2851 pt2 = tg.Pixels.get(0); 2852 pt3 = tg.Pixels.get(2); 2853 } else { 2854 pt0 = tg.Pixels.get(0); 2855 pt1 = tg.Pixels.get(2); 2856 pt2 = tg.Pixels.get(1); 2857 pt3 = tg.Pixels.get(3); 2858 } 2859 pt2 = lineutility.ExtendAlongLineDouble2(pt0, pt2, -20); 2860 pt3 = lineutility.ExtendAlongLineDouble2(pt1, pt3, -20); 2861 addDTG(tg, aboveMiddle, 0, csFactor, pt2, pt3, metrics); 2862 break; 2863 case TacticalLines.SERIES: 2864 case TacticalLines.DRCL: 2865 addModifierTopSegment(tg, tg.get_Name()); 2866 break; 2867 case TacticalLines.STRIKWARN: 2868 AddIntegralModifier(tg, "1", aboveMiddle, 0, index, index + 1, true); 2869 AddIntegralModifier(tg, "2", aboveMiddle, 0, size / 2, size / 2 + 1, true); 2870 break; 2871 case TacticalLines.SCREEN: 2872 case TacticalLines.COVER: 2873 case TacticalLines.GUARD: 2874 if (tg.Pixels.size() == 4) { 2875 pt1 = new POINT2(tg.Pixels.get(1)); 2876 pt2 = new POINT2(tg.Pixels.get(2)); 2877 AddIntegralAreaModifier(tg, label, area, 0, pt1, pt1, true); 2878 AddIntegralAreaModifier(tg, label, area, 0, pt2, pt2, true); 2879 } else { 2880 stringHeight = (int) (0.5 * (double) font.getSize()); 2881 dAngle0 = Math.atan2(tg.Pixels.get(0).y - tg.Pixels.get(1).y, tg.Pixels.get(0).x - tg.Pixels.get(1).x); 2882 dAngle1 = Math.atan2(tg.Pixels.get(0).y - tg.Pixels.get(2).y, tg.Pixels.get(0).x - tg.Pixels.get(2).x); 2883 pt0 = new POINT2(tg.Pixels.get(0)); 2884 pt0.x -= 30 * Math.cos(dAngle0); 2885 pt0.y -= 30 * Math.sin(dAngle0) + stringHeight; 2886 pt1 = new POINT2(tg.Pixels.get(0)); 2887 pt1.x -= 30 * Math.cos(dAngle1); 2888 pt1.y -= 30 * Math.sin(dAngle1) + stringHeight; 2889 AddIntegralAreaModifier(tg, label, area, 0, pt0, pt0, true); 2890 AddIntegralAreaModifier(tg, label, area, 0, pt1, pt1, true); 2891 } 2892 break; 2893 case TacticalLines.MSR_ONEWAY: 2894 case TacticalLines.ASR_ONEWAY: 2895 case TacticalLines.TRAFFIC_ROUTE_ONEWAY: 2896 case TacticalLines.MSR_TWOWAY: 2897 case TacticalLines.ASR_TWOWAY: 2898 case TacticalLines.MSR_ALT: 2899 case TacticalLines.ASR_ALT: 2900 case TacticalLines.TRAFFIC_ROUTE_ALT: 2901 stringWidth = (int) (1.5 * (double) metrics.stringWidth(label + TSpace + tg.get_Name())); 2902 double arrowOffset = 10 * DPIScaleFactor; 2903 if (linetype == TacticalLines.MSR_TWOWAY || linetype == TacticalLines.ASR_TWOWAY) 2904 arrowOffset = 25 * DPIScaleFactor; 2905 boolean isAlt = linetype == TacticalLines.MSR_ALT || linetype == TacticalLines.ASR_ALT || linetype == TacticalLines.TRAFFIC_ROUTE_ALT; 2906 if (isAlt) { 2907 stringWidth2 = (int) (1.5 * (double) metrics.stringWidth("ALT")); 2908 if (stringWidth2 > stringWidth) { 2909 stringWidth = stringWidth2; 2910 } 2911 } 2912 2913 foundSegment = false; 2914 //acevedo - 11/30/2017 - adding option to render only 2 labels. 2915 if (RendererSettings.getInstance().getTwoLabelOnly() == false) { 2916 for (j = 0; j < tg.Pixels.size() - 1; j++) { 2917 pt0 = tg.Pixels.get(j); 2918 pt1 = tg.Pixels.get(j + 1); 2919 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2920 int arrowSide = arraysupport.SupplyRouteArrowSide(pt0, pt1); 2921 if (dist < stringWidth) { 2922 continue; 2923 } else { 2924 if (arrowSide == 1 || arrowSide == 2) { 2925 // Shift points to account for arrow shift with DPI 2926 pt0 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, arrowSide, arrowOffset); 2927 pt1 = lineutility.ExtendDirectedLine(pt1, pt0, pt1, arrowSide, arrowOffset); 2928 AddModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1.7 * csFactor, pt0, pt1); 2929 if (isAlt) 2930 AddModifier(tg, "ALT", aboveMiddle, 0, pt0, pt1); 2931 } else { 2932 AddModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1); 2933 if (isAlt) { 2934 pt0 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, arrowSide, arrowOffset); 2935 pt1 = lineutility.ExtendDirectedLine(pt1, pt0, pt1, arrowSide, arrowOffset); 2936 AddModifier(tg, "ALT", aboveMiddle, 0, pt0, pt1); 2937 } 2938 } 2939 foundSegment = true; 2940 } 2941 } 2942 if (foundSegment == false) { 2943 pt0 = tg.Pixels.get(middleSegment); 2944 pt1 = tg.Pixels.get(middleSegment + 1); 2945 int arrowSide = arraysupport.SupplyRouteArrowSide(pt0, pt1); 2946 if (arrowSide == 1 || arrowSide == 2) { 2947 // Shift points to account for arrow shift with DPI 2948 pt0 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, arrowSide, arrowOffset); 2949 pt1 = lineutility.ExtendDirectedLine(pt1, pt0, pt1, arrowSide, arrowOffset); 2950 AddModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1.7 * csFactor, pt0, pt1); 2951 if (isAlt) 2952 AddModifier(tg, "ALT", aboveMiddle, 0, pt0, pt1); 2953 } else { 2954 AddModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1); 2955 if (isAlt) { 2956 pt0 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, arrowSide, arrowOffset); 2957 pt1 = lineutility.ExtendDirectedLine(pt1, pt0, pt1, arrowSide, arrowOffset); 2958 AddModifier(tg, "ALT", aboveMiddle, 0, pt0, pt1); 2959 } 2960 } 2961 } 2962 } else { 2963 // 2 labels one to the north and the other to the south of graphic. 2964 northestPtIndex = 0; 2965 northestPt = tg.Pixels.get(northestPtIndex); 2966 southestPtIndex = 0; 2967 southestPt = tg.Pixels.get(southestPtIndex); 2968 2969 for (j = 0; j < tg.Pixels.size() - 1; j++) { 2970 pt0 = tg.Pixels.get(j); 2971 if (pt0.y >= northestPt.y) { 2972 northestPt = pt0; 2973 northestPtIndex = j; 2974 } 2975 if (pt0.y <= southestPt.y) { 2976 southestPt = pt0; 2977 southestPtIndex = j; 2978 } 2979 } 2980 2981 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1.7 * csFactor, northestPtIndex, northestPtIndex + 1, false); 2982 if (isAlt) 2983 AddIntegralModifier(tg, "ALT", aboveMiddle, -0.7 * csFactor, northestPtIndex, northestPtIndex + 1, false); 2984 2985 if (northestPtIndex != southestPtIndex) { 2986 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1.7 * csFactor, southestPtIndex, southestPtIndex + 1, false); 2987 if (isAlt) 2988 AddIntegralModifier(tg, "ALT", aboveMiddle, -0.7 * csFactor, southestPtIndex, southestPtIndex + 1, false); 2989 } 2990 }//else 2991 break; 2992 case TacticalLines.DHA_REVD: 2993 AddIntegralAreaModifier(tg, "DETAINEE", area, -1.5 * csFactor, ptCenter, ptCenter, false); 2994 AddIntegralAreaModifier(tg, "HOLDING", area, -0.5 * csFactor, ptCenter, ptCenter, false); 2995 AddIntegralAreaModifier(tg, "AREA", area, 0.5 * csFactor, ptCenter, ptCenter, false); 2996 AddIntegralAreaModifier(tg, tg.get_Name(), area, 1.5 * csFactor, ptCenter, ptCenter, false); 2997 break; 2998 case TacticalLines.EPW: 2999 AddIntegralAreaModifier(tg, "EPW", area, -1.5 * csFactor, ptCenter, ptCenter, false); 3000 AddIntegralAreaModifier(tg, "HOLDING", area, -0.5 * csFactor, ptCenter, ptCenter, false); 3001 AddIntegralAreaModifier(tg, "AREA", area, 0.5 * csFactor, ptCenter, ptCenter, false); 3002 AddIntegralAreaModifier(tg, tg.get_Name(), area, 1.5 * csFactor, ptCenter, ptCenter, false); 3003 break; 3004 case TacticalLines.UXO: 3005 addModifierOnLine("UXO", tg, true); 3006 break; 3007 case TacticalLines.GENERAL: 3008 addNModifier(tg); 3009 break; 3010 case TacticalLines.DHA: 3011 case TacticalLines.KILL_ZONE: 3012 case TacticalLines.FARP: 3013 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 3014 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 3015 break; 3016 case TacticalLines.BSA: 3017 case TacticalLines.DSA: 3018 case TacticalLines.CSA: 3019 case TacticalLines.RSA: 3020 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, false); 3021 break; 3022 case TacticalLines.RHA: 3023 AddIntegralAreaModifier(tg, "REFUGEE", area, -1.5 * csFactor, ptCenter, ptCenter, false); 3024 AddIntegralAreaModifier(tg, "HOLDING", area, -0.5 * csFactor, ptCenter, ptCenter, false); 3025 AddIntegralAreaModifier(tg, "AREA", area, 0.5 * csFactor, ptCenter, ptCenter, false); 3026 AddIntegralAreaModifier(tg, tg.get_Name(), area, 1.5 * csFactor, ptCenter, ptCenter, false); 3027 break; 3028 case TacticalLines.MSR: 3029 case TacticalLines.ASR: 3030 case TacticalLines.TRAFFIC_ROUTE: 3031 //AddIntegralModifier(tg, label + tg.get_Name(), aboveMiddle, -1*csFactor, middleSegment, middleSegment + 1,false); 3032 foundSegment = false; 3033 //acevedo - 11/30/2017 - adding option to render only 2 labels. 3034 if (RendererSettings.getInstance().getTwoLabelOnly() == false) { 3035 for (j = 0; j < tg.Pixels.size() - 1; j++) { 3036 pt0 = tg.Pixels.get(j); 3037 pt1 = tg.Pixels.get(j + 1); 3038 stringWidth = (int) (1.5 * (double) metrics.stringWidth(label + TSpace + tg.get_Name())); 3039 dist = lineutility.CalcDistanceDouble(pt0, pt1); 3040 if (dist < stringWidth) { 3041 continue; 3042 } else { 3043 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1 * csFactor, j, j + 1, false); 3044 foundSegment = true; 3045 } 3046 } 3047 if (foundSegment == false) { 3048 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1 * csFactor, middleSegment, middleSegment + 1, false); 3049 } 3050 } else { 3051 // 2 labels one to the north and the other to the south of graphic. 3052 for (j = 0; j < tg.Pixels.size(); j++) { 3053 pt0 = tg.Pixels.get(j); 3054 3055 if (northestPt == null) { 3056 northestPt = pt0; 3057 northestPtIndex = j; 3058 } 3059 if (southestPt == null) { 3060 southestPt = pt0; 3061 southestPtIndex = j; 3062 } 3063 if (pt0.y >= northestPt.y) { 3064 northestPt = pt0; 3065 northestPtIndex = j; 3066 } 3067 3068 if (pt0.y <= southestPt.y) { 3069 southestPt = pt0; 3070 southestPtIndex = j; 3071 } 3072 }//for 3073 middleSegment = northestPtIndex; 3074 middleSegment2 = southestPtIndex; 3075 3076 if (middleSegment == tg.Pixels.size() - 1) { 3077 middleSegment -= 1; 3078 } 3079 if (middleSegment2 == tg.Pixels.size() - 1) { 3080 middleSegment2 -= 1; 3081 } 3082 if (middleSegment == middleSegment2) { 3083 middleSegment2 -= 1; 3084 } 3085 3086 // if (middleSegment != middleSegment2) { 3087 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, 0, middleSegment, middleSegment + 1, false); 3088 //} 3089 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, 0, middleSegment2, middleSegment2 + 1, false); 3090 3091 }//else 3092 break; 3093 case TacticalLines.TRIP: 3094 foundSegment = false; 3095 stringWidth = (int) (1.5 * (double) metrics.stringWidth(label)); 3096 for (j = 0; j < tg.Pixels.size() - 1; j++) { 3097 pt0 = tg.Pixels.get(j); 3098 pt1 = tg.Pixels.get(j + 1); 3099 midPt = lineutility.MidPointDouble(pt0, pt1, 0); 3100 dist = lineutility.CalcDistanceDouble(pt0, pt1); 3101 if (dist > stringWidth) { 3102 AddModifier2(tg, label, aboveMiddle, -0.7 * csFactor, midPt, midPt, false); 3103 foundSegment = true; 3104 } 3105 } 3106 if (!foundSegment) { 3107 midPt = lineutility.MidPointDouble(tg.Pixels.get(middleSegment), tg.Pixels.get(middleSegment + 1), 0); 3108 AddModifier2(tg, label, aboveMiddle, -0.7 * csFactor, midPt, midPt, false); 3109 } 3110 break; 3111 case TacticalLines.GAP: 3112 if (tg.Pixels.get(1).y > tg.Pixels.get(0).y) { 3113 pt0 = tg.Pixels.get(1); 3114 pt1 = tg.Pixels.get(3); 3115 pt2 = tg.Pixels.get(0); 3116 pt3 = tg.Pixels.get(2); 3117 } else { 3118 pt0 = tg.Pixels.get(0); 3119 pt1 = tg.Pixels.get(2); 3120 pt2 = tg.Pixels.get(1); 3121 pt3 = tg.Pixels.get(3); 3122 } 3123 pt2 = lineutility.ExtendAlongLineDouble2(pt0, pt2, -20); 3124 pt3 = lineutility.ExtendAlongLineDouble2(pt1, pt3, -20); 3125 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, pt0, pt1, false); 3126 addDTG(tg, aboveMiddle, 0, csFactor, pt2, pt3, metrics); 3127 break; 3128 case TacticalLines.BIO: 3129 case TacticalLines.BIOT: 3130 case TacticalLines.CHEM: 3131 case TacticalLines.CHEMT: 3132 case TacticalLines.NUC: 3133 case TacticalLines.RAD: 3134 case TacticalLines.RADT: 3135 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 3136 break; 3137 case TacticalLines.ANCHORAGE_LINE: 3138 AddIntegralAreaModifier(tg, getImageModifier(tg), aboveMiddle, -0.15 * csFactor, tg.Pixels.get(middleSegment), tg.Pixels.get(middleSegment + 1), false); 3139 break; 3140 case TacticalLines.ANCHORAGE_AREA: 3141 // Add anchor on segment with lowest midpoint 3142 y = pt0.y + pt1.y; 3143 index = 0; 3144 for (j = 1; j < size - 1; j++) { 3145 if (y < tg.Pixels.get(j).y + tg.Pixels.get(j + 1).y) { 3146 index = j; 3147 y = tg.Pixels.get(index).y + tg.Pixels.get(index + 1).y; 3148 } 3149 } 3150 AddIntegralAreaModifier(tg, getImageModifier(tg), aboveMiddle, -0.25 * csFactor, tg.Pixels.get(index), tg.Pixels.get(index + 1), false); 3151 break; 3152 case TacticalLines.MINE_LINE: 3153 AddIntegralAreaModifier(tg, getImageModifier(tg), aboveMiddle, -0.2 * csFactor, tg.Pixels.get(middleSegment), tg.Pixels.get(middleSegment + 1), false); 3154 if (tg.isHostile()) { 3155 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, 0.0, pt0, pt1, false); 3156 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, 0.0, ptLast, ptNextToLast, false); 3157 } 3158 break; 3159 case TacticalLines.DEPICT: 3160 GetMBR(tg, ul, ur, lr, ll); 3161 addNModifier(tg); 3162 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 3163 break; 3164 case TacticalLines.FFA: 3165 case TacticalLines.RFA: 3166 case TacticalLines.NFA: 3167 AddIntegralAreaModifier(tg, label, area, -1 * csFactor, ptCenter, ptCenter, false); 3168 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 3169 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 3170 break; 3171 case TacticalLines.PAA: 3172 addModifierOnLine("PAA", tg); 3173 AddIntegralAreaModifier(tg, tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, false); 3174 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 3175 break; 3176 case TacticalLines.FSA: 3177 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, false); 3178 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 3179 break; 3180 case TacticalLines.ATI: 3181 case TacticalLines.CFFZ: 3182 case TacticalLines.CFZ: 3183 case TacticalLines.TBA: 3184 case TacticalLines.TVAR: 3185 case TacticalLines.ZOR: 3186 case TacticalLines.DA: 3187 case TacticalLines.SENSOR: 3188 case TacticalLines.CENSOR: 3189 case TacticalLines.KILLBOXBLUE: 3190 case TacticalLines.KILLBOXPURPLE: 3191 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 3192 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 3193 3194 //DTG label top left point of BBOX 3195 /*GetMBR(tg, ul, ur, lr, ll); 3196 POINT2 ptLeft = ul; 3197 POINT2 ptRight = ur; 3198 //if (tg.get_Client().equalsIgnoreCase("ge")) { 3199 // ptLeft.x -= font.getSize() / 2; 3200 // ptRight.x -= font.getSize() / 2;} 3201 3202 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, toEnd, 0.5 * csFactor, ptLeft, ptRight, false, "W"); 3203 AddIntegralAreaModifier(tg, tg.get_DTG1(), toEnd, 1.5 * csFactor, ptLeft, ptRight, false, "W1");//*/ 3204 3205 //DTG Labels at highest left-of-center point 3206 //Could be more expensive than the bbox approximation above if there are a lot of points. 3207 POINT2 highest = getHighestPointLeftOfCenter(tg.Pixels,ptCenter); 3208 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, toEnd, 0.5 * csFactor, highest, new POINT2(highest.x + 0.001, highest.y), false, "W"); 3209 AddIntegralAreaModifier(tg, tg.get_DTG1(), toEnd, 1.5 * csFactor, highest, new POINT2(highest.x + 0.001, highest.y), false, "W1"); 3210 break; 3211 case TacticalLines.BATTLE: 3212 case TacticalLines.STRONG: 3213 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 3214 addModifierBottomSegment(tg, tg.get_EchelonSymbol()); 3215 break; 3216 case TacticalLines.PNO: 3217 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, 0, ptCenter, ptCenter, false); 3218 addModifierBottomSegment(tg, tg.get_EchelonSymbol()); 3219 addNModifier(tg); 3220 break; 3221 case TacticalLines.WFZ_REVD: 3222 AddIntegralAreaModifier(tg, label, area, -1.5 * csFactor, ptCenter, ptCenter, true); 3223 AddIntegralAreaModifier(tg, tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, true); 3224 AddIntegralAreaModifier(tg, "TIME FROM: " + tg.get_DTG(), area, 0.5 * csFactor, ptCenter, ptCenter, true, "W"); 3225 AddIntegralAreaModifier(tg, "TIME TO: " + tg.get_DTG1(), area, 1.5 * csFactor, ptCenter, ptCenter, true, "W1"); 3226 break; 3227 case TacticalLines.WFZ: 3228 AddIntegralAreaModifier(tg, label, area, -2.5 * csFactor, ptCenter, ptCenter, true); 3229 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1.5 * csFactor, ptCenter, ptCenter, true); 3230 AddIntegralAreaModifier(tg, "TIME FROM: " + tg.get_DTG(), area, -0.5 * csFactor, ptCenter, ptCenter, true, "W"); 3231 AddIntegralAreaModifier(tg, "TIME TO: " + tg.get_DTG1(), area, 0.5 * csFactor, ptCenter, ptCenter, true, "W1"); 3232 AddIntegralAreaModifier(tg, "MIN ALT: " + tg.get_X(), area, 1.5 * csFactor, ptCenter, ptCenter, false, "H"); 3233 AddIntegralAreaModifier(tg, "MAX ALT: " + tg.get_X1(), area, 2.5, ptCenter, ptCenter, false, "H1"); 3234 break; 3235 case TacticalLines.OBSFAREA: 3236 AddIntegralAreaModifier(tg, label, area, -1.5 * csFactor, ptCenter, ptCenter, false); 3237 AddIntegralAreaModifier(tg, tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, false); 3238 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, area, 0.5 * csFactor, ptCenter, ptCenter, false, "W"); 3239 AddIntegralAreaModifier(tg, tg.get_DTG1(), area, 1.5 * csFactor, ptCenter, ptCenter, false, "W1"); 3240 break; 3241 case TacticalLines.OBSAREA: 3242 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1 * csFactor, ptCenter, ptCenter, true); 3243 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, area, 0, ptCenter, ptCenter, true, "W"); 3244 AddIntegralAreaModifier(tg, tg.get_DTG1(), area, 1 * csFactor, ptCenter, ptCenter, true, "W1"); 3245 break; 3246 case TacticalLines.ROZ: 3247 case TacticalLines.AARROZ: 3248 case TacticalLines.UAROZ: 3249 case TacticalLines.WEZ: 3250 case TacticalLines.FEZ: 3251 case TacticalLines.JEZ: 3252 case TacticalLines.FAADZ: 3253 case TacticalLines.HIDACZ: 3254 case TacticalLines.MEZ: 3255 case TacticalLines.LOMEZ: 3256 case TacticalLines.HIMEZ: 3257 AddIntegralAreaModifier(tg, label, area, -2.5, ptCenter, ptCenter, false, ""); 3258 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1.5, ptCenter, ptCenter, false, "T"); 3259 AddIntegralAreaModifier(tg, "MIN ALT: " + tg.get_X(), area, -0.5, ptCenter, ptCenter, false, "H"); 3260 AddIntegralAreaModifier(tg, "MAX ALT: " + tg.get_X1(), area, 0.5, ptCenter, ptCenter, false, "H1"); 3261 AddIntegralAreaModifier(tg, "TIME FROM: " + tg.get_DTG(), area, 1.5, ptCenter, ptCenter, false, "W"); 3262 AddIntegralAreaModifier(tg, "TIME TO: " + tg.get_DTG1(), area, 2.5, ptCenter, ptCenter, false, "W1"); 3263 break; 3264 case TacticalLines.ENCIRCLE: 3265 if (tg.isHostile()) { 3266 AddIntegralModifier(tg, tg.get_N(), aboveMiddle, 0, 0, 1, true); 3267 AddIntegralModifier(tg, tg.get_N(), aboveMiddle, 0, middleSegment, middleSegment + 1, true); 3268 } 3269 break; 3270 case TacticalLines.LAA: 3271 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 3272 AddIntegralAreaModifier(tg, label, area, -1 * csFactor, ptCenter, ptCenter, false); 3273 break; 3274 case TacticalLines.BOUNDARY: 3275 if (clipRect != null) { 3276 AddBoundaryModifiers(tg, g2d, clipRect); 3277 } else { 3278 AddBoundaryModifiers(tg, g2d, clipArray); 3279 } 3280 break; 3281 case TacticalLines.CFL: 3282 stringWidth = (int) ((double) metrics.stringWidth(label + TSpace + tg.get_Name())); 3283 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG() + WDash + tg.get_DTG1())); 3284 if (stringWidth2 > stringWidth) { 3285 stringWidth = stringWidth2; 3286 } 3287 pt0 = new POINT2(tg.Pixels.get(middleSegment)); 3288 pt1 = new POINT2(tg.Pixels.get(middleSegment + 1)); 3289 getPixelsMiddleSegment(tg, stringWidth, pt0, pt1); 3290 AddModifier2(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3291 addDTG(tg, aboveMiddle, 0.7 * csFactor, 1.7 * csFactor, pt0, pt1, metrics); 3292 break; 3293 case TacticalLines.FLOT: 3294 if (tg.get_H().equals("1")) { 3295 label = "LC"; 3296 } else if (tg.get_H().equals("2")) { 3297 label = ""; 3298 } 3299 AddIntegralAreaModifier(tg, label, toEnd, 0, pt0, pt1, false); 3300 AddIntegralAreaModifier(tg, label, toEnd, 0, ptLast, ptNextToLast, false); 3301 3302 if (tg.isHostile()) { 3303 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, -1 * csFactor, pt0, pt1, false); 3304 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, -1 * csFactor, ptLast, ptNextToLast, false); 3305 } 3306 break; 3307 case TacticalLines.LC: 3308 double shiftFactor = 1d; 3309 if (shiftLines) { 3310 shiftFactor = 0.5d; 3311 } 3312 if (tg.isHostile()) { 3313 if (pt0.x < pt1.x) { 3314 TLineFactor = -shiftFactor;//was -1 3315 } else { 3316 TLineFactor = shiftFactor;//was 1 3317 } 3318 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, TLineFactor, pt0, pt1, false); 3319 if (ptNextToLast.x < ptLast.x) { 3320 TLineFactor = -shiftFactor;//was -1 3321 } else { 3322 TLineFactor = shiftFactor;//was 1 3323 } 3324 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, TLineFactor, ptLast, ptNextToLast, false); 3325 } 3326 AddIntegralAreaModifier(tg, label, toEnd, 0, pt0, pt1, false); 3327 AddIntegralAreaModifier(tg, label, toEnd, 0, ptLast, ptNextToLast, false); 3328 break; 3329 case TacticalLines.CATK: 3330 AddIntegralModifier(tg, label, aboveMiddle, 0, 1, 0, false); 3331 break; 3332 case TacticalLines.CATKBYFIRE: 3333 stringWidth = (int) (1.5 * (double) metrics.stringWidth(label)); 3334 pt2 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3335 AddModifier2(tg, label, aboveMiddle, 0, pt1, pt2, false); 3336 break; 3337 case TacticalLines.IL: 3338 AddIntegralModifier(tg, tg.get_Name(), aboveMiddle, 0, 1, 0, false); 3339 break; 3340 case TacticalLines.RETIRE: 3341 case TacticalLines.PURSUIT: 3342 case TacticalLines.WITHDRAW: 3343 case TacticalLines.DISENGAGE: 3344 case TacticalLines.WDRAWUP: 3345 case TacticalLines.FPOL: 3346 case TacticalLines.RPOL: 3347 case TacticalLines.DEMONSTRATE: 3348 AddIntegralModifier(tg, label, aboveMiddle, 0, 0, 1, true); 3349 break; 3350 case TacticalLines.RIP: 3351 case TacticalLines.BOMB: 3352 case TacticalLines.TGMF: 3353 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, true); 3354 break; 3355 case TacticalLines.MSDZ: 3356 AddIntegralAreaModifier(tg, "1", area, 0, pt1, pt1, true); 3357 AddIntegralAreaModifier(tg, "2", area, 0, pt2, pt2, true); 3358 AddIntegralAreaModifier(tg, "3", area, 0, pt3, pt3, true); 3359 break; 3360 case TacticalLines.DELAY: 3361 AddIntegralModifier(tg, tg.get_DTG(), aboveMiddle, -1 * csFactor, 0, 1, false); 3362 AddIntegralModifier(tg, label, aboveMiddle, 0, 0, 1, true); 3363 break; 3364 case TacticalLines.GENERIC_LINE: 3365 pt0 = tg.Pixels.get(0); 3366 pt1 = tg.Pixels.get(1); 3367 pt2 = tg.Pixels.get(tg.Pixels.size() - 1); 3368 pt3 = tg.Pixels.get(tg.Pixels.size() - 2); 3369 dist = lineutility.CalcDistanceDouble(pt0, pt1); 3370 dist2 = lineutility.CalcDistanceDouble(pt2, pt3); 3371 stringWidth = (int) ((double) metrics.stringWidth(tg.get_H() + " " + tg.get_Name())); 3372 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG())); 3373 if (stringWidth2 > stringWidth) { 3374 stringWidth = stringWidth2; 3375 } 3376 3377 if (tg.Pixels.size() == 2) //one segment 3378 { 3379 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3380 AddModifier2(tg, tg.get_H() + " " + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3381 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 3382 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 3383 if (dist > 3.5 * stringWidth)//was 28stringwidth+5 3384 { 3385 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 3386 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 3387 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3388 AddModifier2(tg, tg.get_H() + " " + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3389 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 3390 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 3391 } 3392 } else //more than one semgent 3393 { 3394 double dist3 = lineutility.CalcDistanceDouble(pt0, pt2); 3395 if (dist > stringWidth + 5 || dist >= dist2 || dist3 > stringWidth + 5) { 3396 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3397 AddModifier2(tg, tg.get_H() + " " + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3398 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 3399 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 3400 } 3401 if (dist2 > stringWidth + 5 || dist2 > dist || dist3 > stringWidth + 5) { 3402 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 3403 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 3404 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3405 AddModifier2(tg, tg.get_H() + " " + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3406 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 3407 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 3408 } 3409 } 3410 break; 3411 default: 3412 break; 3413 } 3414 } 3415 scaleModifiers(tg); 3416 tg.Pixels = origPoints; 3417 } catch (Exception exc) { 3418 ErrorLogger.LogException(_className, "AddModifiersGeo", 3419 new RendererException("Failed inside AddModifiersGeo", exc)); 3420 } 3421 3422 } 3423 3424 /** 3425 * RFA, NFA, FFA need these for line spacing 3426 * 3427 * @param tg 3428 * @return 3429 */ 3430 private static int getRFALines(TGLight tg) { 3431 int lines = 1; 3432 try { 3433 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 3434 lines++; 3435 } 3436 if (tg.get_DTG() != null && !tg.get_DTG().isEmpty()) { 3437 lines++; 3438 } else if (tg.get_DTG1() != null && !tg.get_DTG1().isEmpty()) { 3439 lines++; 3440 } 3441 } catch (Exception exc) { 3442 ErrorLogger.LogException(_className, "AddModifiers", 3443 new RendererException("Failed inside AddModifiers", exc)); 3444 } 3445 return lines; 3446 } 3447 3448 /** 3449 * Added sector range fan modifiers based using the calculated orientation 3450 * indicator points 3451 * 3452 * @param tg 3453 * @param converter 3454 * @return 3455 */ 3456 private static void addSectorModifiers(TGLight tg, IPointConversion converter) { 3457 try { 3458 if (tg.get_LineType() == TacticalLines.RANGE_FAN_SECTOR) { 3459 ArrayList<Double> AM = new ArrayList<>(); 3460 ArrayList<Double> AN = new ArrayList<>(); 3461 //get the number of sectors 3462 String X = tg.get_X(); 3463 String[] altitudes = null; 3464 String[] am = tg.get_AM().split(","); 3465 String[] an = tg.get_AN().split(","); 3466 int numSectors = an.length / 2; 3467 //there must be at least one sector 3468 if (numSectors < 1) { 3469 return; 3470 } 3471 if (!X.isEmpty()) { 3472 altitudes = X.split(","); 3473 } 3474 try { 3475 for (String s : am) { 3476 AM.add(Double.parseDouble(s)); 3477 } 3478 for (String s : an) { 3479 AN.add(Double.parseDouble(s)); 3480 } 3481 } catch (NumberFormatException e) { 3482 return; 3483 } 3484 if (numSectors + 1 > AM.size()) { 3485 if (Double.parseDouble(am[0]) != 0d) { 3486 AM.add(0, 0d); 3487 } 3488 } 3489 3490 int n = tg.Pixels.size(); 3491 //pt0 and pt1 are points for the location indicator 3492 POINT2 pt0 = tg.Pixels.get(n - 5); 3493 POINT2 pt1 = tg.Pixels.get(n - 4); 3494 Point2D pt02d = new Point2D.Double(pt0.x, pt0.y); 3495 Point2D pt12d = new Point2D.Double(pt1.x, pt1.y); 3496 pt02d = converter.PixelsToGeo(pt02d); 3497 pt12d = converter.PixelsToGeo(pt12d); 3498 pt0.x = pt02d.getX(); 3499 pt0.y = pt02d.getY(); 3500 pt1.x = pt12d.getX(); 3501 pt1.y = pt12d.getY(); 3502 //azimuth of the orientation indicator 3503 double az12 = mdlGeodesic.GetAzimuth(pt0, pt1); 3504 3505 POINT2 pt2 = null; 3506 ArrayList<POINT2> locModifier = new ArrayList(); 3507 //diagnostic 3508 POINT2 ptLeft = null, ptRight = null; 3509 ArrayList<POINT2> locAZModifier = new ArrayList(); 3510 //end section 3511 Point2D pt22d = null; 3512 double radius = 0; 3513 for (int k = 0; k < numSectors; k++) { 3514 if (AM.size() < k + 2) { 3515 break; 3516 } 3517 radius = (AM.get(k) + AM.get(k + 1)) / 2; 3518 pt2 = mdlGeodesic.geodesic_coordinate(pt0, radius, az12); 3519 //need locModifier in geo pixels 3520 pt22d = new Point2D.Double(pt2.x, pt2.y); 3521 pt22d = converter.GeoToPixels(pt22d); 3522 pt2.x = pt22d.getX(); 3523 pt2.y = pt22d.getY(); 3524 locModifier.add(pt2); 3525 //diagnostic 3526 if (tg.get_HideOptionalLabels()) 3527 continue; 3528 ptLeft = mdlGeodesic.geodesic_coordinate(pt0, radius, AN.get(2 * k)); 3529 //need ptLeft in geo pixels 3530 pt22d = new Point2D.Double(ptLeft.x, ptLeft.y); 3531 pt22d = converter.GeoToPixels(pt22d); 3532 ptLeft.x = pt22d.getX(); 3533 ptLeft.y = pt22d.getY(); 3534 ptRight = mdlGeodesic.geodesic_coordinate(pt0, radius, AN.get(2 * k + 1)); 3535 //need ptRight in geo pixels 3536 pt22d = new Point2D.Double(ptRight.x, ptRight.y); 3537 pt22d = converter.GeoToPixels(pt22d); 3538 ptRight.x = pt22d.getX(); 3539 ptRight.y = pt22d.getY(); 3540 locAZModifier.add(ptLeft); 3541 locAZModifier.add(ptRight); 3542 //end section 3543 } 3544 if (altitudes != null) { 3545 for (int k = 0; k < altitudes.length; k++) { 3546 if (k >= locModifier.size()) { 3547 break; 3548 } 3549 pt0 = locModifier.get(k); 3550 AddAreaModifier(tg, "ALT " + altitudes[k], area, 0, pt0, pt0); 3551 } 3552 } 3553 3554 if (!tg.get_HideOptionalLabels()) { 3555 for (int k = 0; k < numSectors; k++) { 3556 pt0 = locModifier.get(k); 3557 AddAreaModifier(tg, "RG " + removeDecimal(AM.get(k + 1)), area, -1, pt0, pt0); 3558 ptLeft = locAZModifier.get(2 * k); 3559 ptRight = locAZModifier.get(2 * k + 1); 3560 AddAreaModifier(tg, removeDecimal(an[2 * k]), area, 0, ptLeft, ptLeft); 3561 AddAreaModifier(tg, removeDecimal(an[2 * k + 1]), area, 0, ptRight, ptRight); 3562 } 3563 } 3564 } else if (tg.get_LineType() == TacticalLines.RADAR_SEARCH) { 3565 // Copies functionality from RANGE_FAN_SECTOR with one sector and different modifiers 3566 String strLeftRightMinMax = tg.get_LRMM(); 3567 String[] sector = strLeftRightMinMax.split(","); 3568 double left = Double.parseDouble(sector[0]); 3569 double right = Double.parseDouble(sector[1]); 3570 3571 while (left > 360) { 3572 left -= 360; 3573 } 3574 while (right > 360) { 3575 right -= 360; 3576 } 3577 while (left < 0) { 3578 left += 360; 3579 } 3580 while (right < 0) { 3581 right += 360; 3582 } 3583 3584 double orientation = 0; 3585 if (left > right) { 3586 orientation = (left - 360 + right) / 2; 3587 } else { 3588 orientation = (left + right) / 2; 3589 } 3590 3591 double dist = Double.parseDouble(sector[3]); 3592 double radius = dist * 1.1; 3593 3594 POINT2 pt0 = tg.LatLongs.get(0); 3595 Point2D ptPixels = converter.GeoToPixels(new Point2D.Double(pt0.x, pt0.y)); 3596 POINT2 pt0F = new POINT2(); 3597 pt0F.x = ptPixels.getX(); 3598 pt0F.y = ptPixels.getY(); 3599 pt0F.style = pt0.style; 3600 3601 POINT2 pt1 = mdlGeodesic.geodesic_coordinate(pt0, radius, orientation); 3602 ptPixels = converter.GeoToPixels(new Point2D.Double(pt1.x, pt1.y)); 3603 POINT2 pt1F = new POINT2(); 3604 pt1F.x = ptPixels.getX(); 3605 pt1F.y = ptPixels.getY(); 3606 pt1F.style = pt1.style; 3607 3608 dist = lineutility.CalcDistanceDouble(pt0F, pt1F); 3609 double base = 10; 3610 if (dist < 100) { 3611 base = dist / 10; 3612 } 3613 if (base < 5) { 3614 base = 5; 3615 } 3616 double basex2 = 2 * base; 3617 POINT2 ptTipF = lineutility.ExtendAlongLineDouble(pt0F, pt1F, dist + basex2); //was 20 3618 3619 pt0 = pt0F; 3620 pt1 = ptTipF; 3621 3622 ArrayList<Double> AM = new ArrayList<>(); 3623 String[] am = tg.get_AM().split(","); 3624 3625 for (String s : am) { 3626 AM.add(Double.parseDouble(s)); 3627 } 3628 3629 if (AM.size() < 2) { 3630 if (Double.parseDouble(am[0]) != 0d) { 3631 AM.add(0, 0d); 3632 } else { 3633 return; 3634 } 3635 } 3636 3637 Point2D pt02d = new Point2D.Double(pt0.x, pt0.y); 3638 Point2D pt12d = new Point2D.Double(pt1.x, pt1.y); 3639 pt02d = converter.PixelsToGeo(pt02d); 3640 pt12d = converter.PixelsToGeo(pt12d); 3641 pt0.x = pt02d.getX(); 3642 pt0.y = pt02d.getY(); 3643 pt1.x = pt12d.getX(); 3644 pt1.y = pt12d.getY(); 3645 double az12 = mdlGeodesic.GetAzimuth(pt0, pt1); 3646 3647 Point2D pt22d = null; 3648 3649 radius = (AM.get(0) + AM.get(1)) / 2; 3650 POINT2 pt2 = mdlGeodesic.geodesic_coordinate(pt0, radius, az12); 3651 pt22d = new Point2D.Double(pt2.x, pt2.y); 3652 pt22d = converter.GeoToPixels(pt22d); 3653 pt2.x = pt22d.getX(); 3654 pt2.y = pt22d.getY(); 3655 AddAreaModifier(tg, tg.get_Name(), area, -1, pt2, pt2); 3656 } 3657 } catch (Exception exc) { 3658 ErrorLogger.LogException(_className, "addSectorModifiers", 3659 new RendererException("Failed inside addSectorModifiers", exc)); 3660 } 3661 } 3662 3663 /** 3664 * Called by the renderer after tg.Pixels has been filled with the 3665 * calculated points. The modifier path depends on points calculated by 3666 * CELineArray. 3667 * 3668 * @param tg 3669 */ 3670 public static void AddModifiers2(TGLight tg, IPointConversion converter) { 3671 try { 3672 if (tg.Pixels == null || tg.Pixels.isEmpty()) { 3673 return; 3674 } 3675 switch (tg.get_LineType()) { 3676 case TacticalLines.BS_RECTANGLE: 3677 case TacticalLines.BBS_RECTANGLE: 3678 case TacticalLines.CONVOY: 3679 case TacticalLines.HCONVOY: 3680 case TacticalLines.BREACH: 3681 case TacticalLines.BYPASS: 3682 case TacticalLines.CANALIZE: 3683 case TacticalLines.PENETRATE: 3684 case TacticalLines.CLEAR: 3685 case TacticalLines.DISRUPT: 3686 case TacticalLines.FIX: 3687 case TacticalLines.ISOLATE: 3688 case TacticalLines.OCCUPY: 3689 case TacticalLines.RETAIN: 3690 case TacticalLines.SECURE: 3691 case TacticalLines.CONTROL: 3692 case TacticalLines.LOCATE: 3693 case TacticalLines.AREA_DEFENSE: 3694 case TacticalLines.CONTAIN: 3695 case TacticalLines.SEIZE: 3696 case TacticalLines.CAPTURE: 3697 case TacticalLines.EVACUATE: 3698 case TacticalLines.TURN: 3699 case TacticalLines.CORDONKNOCK: 3700 case TacticalLines.CORDONSEARCH: 3701 case TacticalLines.DENY: 3702 case TacticalLines.ESCORT: 3703 case TacticalLines.EXFILTRATION: 3704 case TacticalLines.INFILTRATION: 3705 case TacticalLines.FOLLA: 3706 case TacticalLines.FOLSP: 3707 case TacticalLines.ACA_RECTANGULAR: 3708 case TacticalLines.ACA_CIRCULAR: 3709 case TacticalLines.RECTANGULAR: 3710 case TacticalLines.CUED_ACQUISITION: 3711 case TacticalLines.CIRCULAR: 3712 case TacticalLines.BDZ: 3713 case TacticalLines.BBS_POINT: 3714 case TacticalLines.FSA_CIRCULAR: 3715 case TacticalLines.NOTACK: 3716 case TacticalLines.ATI_CIRCULAR: 3717 case TacticalLines.CFFZ_CIRCULAR: 3718 case TacticalLines.SENSOR_CIRCULAR: 3719 case TacticalLines.CENSOR_CIRCULAR: 3720 case TacticalLines.DA_CIRCULAR: 3721 case TacticalLines.CFZ_CIRCULAR: 3722 case TacticalLines.ZOR_CIRCULAR: 3723 case TacticalLines.TBA_CIRCULAR: 3724 case TacticalLines.TVAR_CIRCULAR: 3725 case TacticalLines.FFA_CIRCULAR: 3726 case TacticalLines.NFA_CIRCULAR: 3727 case TacticalLines.RFA_CIRCULAR: 3728 case TacticalLines.KILLBOXBLUE_CIRCULAR: 3729 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 3730 case TacticalLines.BLOCK: 3731 case TacticalLines.FFA_RECTANGULAR: 3732 case TacticalLines.NFA_RECTANGULAR: 3733 case TacticalLines.RFA_RECTANGULAR: 3734 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 3735 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 3736 case TacticalLines.FSA_RECTANGULAR: 3737 case TacticalLines.SHIP_AOI_RECTANGULAR: 3738 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 3739 case TacticalLines.ATI_RECTANGULAR: 3740 case TacticalLines.CFFZ_RECTANGULAR: 3741 case TacticalLines.SENSOR_RECTANGULAR: 3742 case TacticalLines.CENSOR_RECTANGULAR: 3743 case TacticalLines.DA_RECTANGULAR: 3744 case TacticalLines.CFZ_RECTANGULAR: 3745 case TacticalLines.ZOR_RECTANGULAR: 3746 case TacticalLines.TBA_RECTANGULAR: 3747 case TacticalLines.TVAR_RECTANGULAR: 3748 case TacticalLines.PAA: 3749 case TacticalLines.PAA_RECTANGULAR: 3750 case TacticalLines.RECTANGULAR_TARGET: 3751 case TacticalLines.PAA_CIRCULAR: 3752 case TacticalLines.RANGE_FAN: 3753 case TacticalLines.RANGE_FAN_SECTOR: 3754 case TacticalLines.RADAR_SEARCH: 3755 case TacticalLines.SHIP_AOI_CIRCULAR: 3756 case TacticalLines.MFLANE: 3757 case TacticalLines.ENVELOPMENT: 3758 case TacticalLines.MOBILE_DEFENSE: 3759 break; 3760 default: 3761 return; 3762 } 3763 //end section 3764 ArrayList<POINT2> origPoints = lineutility.getDeepCopy(tg.Pixels); 3765 int n = tg.Pixels.size(); 3766 if (tg.modifiers == null) { 3767 tg.modifiers = new ArrayList(); 3768 } 3769 Font font = tg.get_Font(); 3770 POINT2 ptCenter = null; 3771 double csFactor = 1d;//this will be used for text spacing the 3d map (CommandCight) 3772 //String affiliation=tg.get_Affiliation(); 3773 int linetype = tg.get_LineType(); 3774 POINT2 pt0 = null, pt1 = null, pt2 = null, pt3 = null; 3775 int j = 0, k = 0; 3776 double dist = 0; 3777 String label = GetCenterLabel(tg); 3778 String[] X = null; 3779 int lastIndex = tg.Pixels.size() - 1; 3780 int nextToLastIndex = 0; 3781 if (tg.Pixels.size() > 1) { 3782 nextToLastIndex = tg.Pixels.size() - 2; 3783 } 3784 POINT2 ptLast = new POINT2(tg.Pixels.get(lastIndex)); 3785 POINT2 ptNextToLast = null; 3786 if (tg.Pixels.size() > 1) { 3787 ptNextToLast = new POINT2(tg.Pixels.get(nextToLastIndex)); 3788 } 3789 String WDash = ""; // Dash between W and W1 if they're not empty 3790 String TSpace = "", TDash = ""; // Space or dash between label and T modifier if T isn't empty 3791 if (tg.get_DTG() != null && tg.get_DTG1() != null && !tg.get_DTG().isEmpty() && !tg.get_DTG1().isEmpty()) { 3792 WDash = " - "; 3793 } 3794 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 3795 TSpace = " "; 3796 TDash = " - "; 3797 } 3798 3799 POINT2 ptLeft = null, ptRight = null; 3800 BufferedImage bi = new BufferedImage(8, 8, BufferedImage.TYPE_INT_ARGB); 3801 Graphics2D g2d = bi.createGraphics(); 3802 g2d.setFont(tg.get_Font()); 3803 FontMetrics metrics = g2d.getFontMetrics(); 3804 int stringWidth = 0, rfaLines = 0; 3805 pt0 = new POINT2(tg.Pixels.get(0)); 3806 if (tg.Pixels.size() > 1) { 3807 pt1 = new POINT2(tg.Pixels.get(1)); 3808 } 3809 3810 POINT2[] pts = null; 3811 // if the client is the 3d map (CS) then we want to shrink the spacing between 3812 // the lines of text 3813 if (tg.get_Client().equals("cpof3d")) { 3814 csFactor = 0.9d; 3815 } 3816 3817 shiftModifierPath(tg, pt0, pt1, ptLast, ptNextToLast); 3818 3819 boolean modifiersGrouped = false; 3820 if(RendererSettings.getInstance().getGroupModifiers()) 3821 { 3822 switch (linetype) { 3823 case TacticalLines.PAA_RECTANGULAR: 3824 case TacticalLines.PAA_CIRCULAR: 3825 //too complex to duplicate, simpler to group labels in next switch statement 3826 break; 3827 case TacticalLines.ACA_RECTANGULAR: 3828 case TacticalLines.ACA_CIRCULAR: 3829 ptCenter = lineutility.CalcCenterPointDouble2(tg.Pixels.toArray(), tg.Pixels.size()); 3830 AddIntegralAreaModifier(tg, buildAreaGroupString(tg, label), area, 0, ptCenter, ptCenter, false); 3831 modifiersGrouped = true; 3832 break; 3833 case TacticalLines.FSA_CIRCULAR: 3834 case TacticalLines.ATI_CIRCULAR: 3835 case TacticalLines.CFFZ_CIRCULAR: 3836 case TacticalLines.SENSOR_CIRCULAR: 3837 case TacticalLines.CENSOR_CIRCULAR: 3838 case TacticalLines.DA_CIRCULAR: 3839 case TacticalLines.CFZ_CIRCULAR: 3840 case TacticalLines.ZOR_CIRCULAR: 3841 case TacticalLines.TBA_CIRCULAR: 3842 case TacticalLines.TVAR_CIRCULAR: 3843 case TacticalLines.KILLBOXBLUE_CIRCULAR: 3844 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 3845 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(tg.Pixels.size() / 2), 0); 3846 //center labels 3847 AddIntegralAreaModifier(tg, buildAreaGroupString(tg, label), area, 0, ptCenter, ptCenter, false); 3848 //DTG on top left 3849 POINT2 dtgCircularPosition = tg.Pixels.get(Math.round(tg.Pixels.size() * 0.5625f)); 3850 AddIntegralAreaModifier(tg, buildAreaGroupDTGString(tg), toEnd, -1 * csFactor, dtgCircularPosition, new POINT2(dtgCircularPosition.x + 0.001, dtgCircularPosition.y, 0), false); 3851 modifiersGrouped = true; 3852 break; 3853 case TacticalLines.FFA_CIRCULAR: 3854 case TacticalLines.NFA_CIRCULAR: 3855 case TacticalLines.RFA_CIRCULAR: 3856 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(51), 0); 3857 AddIntegralAreaModifier(tg, buildAreaGroupString(tg, label), area, 0, ptCenter, ptCenter, false); 3858 modifiersGrouped = true; 3859 break; 3860 case TacticalLines.FFA_RECTANGULAR: 3861 case TacticalLines.NFA_RECTANGULAR: 3862 case TacticalLines.RFA_RECTANGULAR: 3863 pt0 = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 3864 pt1 = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 3865 ptCenter = lineutility.MidPointDouble(pt0, pt1, 0); 3866 AddIntegralAreaModifier(tg, buildAreaGroupString(tg, label), area, 0, ptCenter, ptCenter, false); 3867 modifiersGrouped = true; 3868 break; 3869 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 3870 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 3871 case TacticalLines.FSA_RECTANGULAR: 3872 case TacticalLines.ATI_RECTANGULAR: 3873 case TacticalLines.CFFZ_RECTANGULAR: 3874 case TacticalLines.SENSOR_RECTANGULAR: 3875 case TacticalLines.CENSOR_RECTANGULAR: 3876 case TacticalLines.DA_RECTANGULAR: 3877 case TacticalLines.CFZ_RECTANGULAR: 3878 case TacticalLines.ZOR_RECTANGULAR: 3879 case TacticalLines.TBA_RECTANGULAR: 3880 case TacticalLines.TVAR_RECTANGULAR: 3881 ptLeft = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 3882 ptRight = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 3883 ptCenter = lineutility.MidPointDouble(ptLeft, ptRight, 0); 3884 AddIntegralAreaModifier(tg, buildAreaGroupString(tg,label), area, 0 * csFactor, ptCenter, ptCenter, false); 3885 3886 //highest point left of center 3887 POINT2 dtgPosition = getHighestPointLeftOfCenter(tg.Pixels,ptCenter); 3888 3889 AddIntegralAreaModifier(tg, buildAreaGroupDTGString(tg), toEnd, 1 * csFactor, dtgPosition, new POINT2(dtgPosition.x + 0.001, dtgPosition.y, 0), false); 3890 modifiersGrouped = true; 3891 break; 3892 } 3893 } 3894 3895 if(!modifiersGrouped) { 3896 switch (linetype) { 3897 case TacticalLines.BS_RECTANGLE: 3898 case TacticalLines.BBS_RECTANGLE: 3899 pts = new POINT2[4]; 3900 for (j = 0; j < 4; j++) { 3901 pts[j] = tg.Pixels.get(j); 3902 } 3903 ptCenter = lineutility.CalcCenterPointDouble2(pts, 4); 3904 AddIntegralAreaModifier(tg, tg.get_Name(), area, -0.125 * csFactor, ptCenter, ptCenter, false); 3905 break; 3906 case TacticalLines.CONVOY: 3907 case TacticalLines.HCONVOY: 3908 pt2 = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(3), 0); 3909 pt3 = lineutility.MidPointDouble(tg.Pixels.get(1), tg.Pixels.get(2), 0); 3910 AddIntegralAreaModifier(tg, tg.get_V(), aboveEndInside, 0, pt2, pt3, false); 3911 AddIntegralAreaModifier(tg, tg.get_H(), aboveStartInside, 0, pt2, pt3, false); 3912 addDTG(tg, aboveMiddle, 1.2 * csFactor, 2.2 * csFactor, pt2, pt3, metrics); 3913 break; 3914 case TacticalLines.BREACH: 3915 case TacticalLines.BYPASS: 3916 case TacticalLines.CANALIZE: 3917 pt0 = tg.Pixels.get(1); 3918 pt1 = tg.Pixels.get(2); 3919 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3920 AddIntegralAreaModifier(tg, label, aboveMiddlePerpendicular, -0.125 * csFactor, pt0, pt1, true); 3921 break; 3922 case TacticalLines.PENETRATE: 3923 case TacticalLines.CLEAR: 3924 pt0 = tg.Pixels.get(2); 3925 pt1 = tg.Pixels.get(3); 3926 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3927 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3928 break; 3929 case TacticalLines.DISRUPT: 3930 pt0 = tg.Pixels.get(4); 3931 pt1 = tg.Pixels.get(5); 3932 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3933 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3934 break; 3935 case TacticalLines.FIX: 3936 pt0 = tg.Pixels.get(0); 3937 pt1 = tg.Pixels.get(1); 3938 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3939 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3940 break; 3941 case TacticalLines.ISOLATE: 3942 case TacticalLines.OCCUPY: 3943 case TacticalLines.RETAIN: 3944 case TacticalLines.SECURE: 3945 case TacticalLines.CONTROL: 3946 case TacticalLines.LOCATE: 3947 case TacticalLines.AREA_DEFENSE: 3948 pt0 = tg.Pixels.get(13); 3949 pt1 = tg.Pixels.get(14); 3950 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3951 ptCenter = lineutility.MidPointDouble(pt0, pt1, 0); 3952 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, ptCenter, ptCenter, true); 3953 break; 3954 case TacticalLines.CONTAIN: 3955 pt0 = tg.Pixels.get(13); 3956 pt1 = tg.Pixels.get(14); 3957 //ptCenter = lineutility.MidPointDouble(pt0, pt1, 0);//maybe figure out which points are center line to apply an angle 3958 ptCenter = tg.Pixels.get(13);//always rightside up at mid-point of curve 3959 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3960 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, ptCenter, ptCenter, true); 3961 3962 // Contain always has "ENY" even if friendly (not N modifier) 3963 for (j = 0; j < n; j++) { 3964 if (tg.Pixels.get(j).style == 14) { 3965 pt0 = tg.Pixels.get(j); 3966 pt1 = tg.Pixels.get(j + 1); 3967 AddIntegralAreaModifier(tg, "ENY", aboveMiddle, 0, pt0, pt1, true); 3968 break; 3969 } 3970 } 3971 break; 3972 case TacticalLines.TURN: 3973 pt0 = tg.Pixels.get(12); 3974 pt1 = tg.Pixels.get(13); 3975 ptCenter = lineutility.MidPointDouble(pt0, pt1, 0); 3976 AddIntegralAreaModifier(tg, label, area, -0.125 * csFactor, ptCenter, ptCenter, true); 3977 break; 3978 case TacticalLines.SEIZE: 3979 case TacticalLines.CAPTURE: 3980 case TacticalLines.EVACUATE: 3981 pt0 = tg.Pixels.get(26); 3982 pt1 = tg.Pixels.get(27); 3983 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3984 ptCenter = lineutility.MidPointDouble(pt0, pt1, 0); 3985 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, ptCenter, ptCenter, true); 3986 break; 3987 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 3988 ptLeft = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 3989 ptRight = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 3990 AddIntegralAreaModifier(tg, label + TDash + tg.get_Name(), aboveMiddle, 0, ptLeft, ptRight, false); 3991 break; 3992 case TacticalLines.SHIP_AOI_RECTANGULAR: 3993 if (tg.Pixels.get(0).x > tg.Pixels.get(3).x) { 3994 AddIntegralAreaModifier(tg, label, aboveMiddle, 0.6 * csFactor, tg.Pixels.get(0), tg.Pixels.get(3), false); 3995 } else { 3996 AddIntegralAreaModifier(tg, label, aboveMiddle, 0.6 * csFactor, tg.Pixels.get(1), tg.Pixels.get(2), false); 3997 } 3998 break; 3999 case TacticalLines.NOTACK: 4000 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(tg.Pixels.size() / 2), 0); 4001 AddIntegralAreaModifier(tg, label, area, -1, ptCenter, ptCenter, false); 4002 addDTG(tg, area, csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 4003 break; 4004 case TacticalLines.SHIP_AOI_CIRCULAR: 4005 // Moved from AddModifiersGeo() 4006 // AddModifiersGeo() called before getGeoEllipse(). Unable to use getMBR with single anchor point 4007 4008 // Get variables from AddModifiersGeo 4009 POINT2 lr = new POINT2(tg.Pixels.get(0)); 4010 POINT2 ll = new POINT2(tg.Pixels.get(0)); 4011 POINT2 ul = new POINT2(tg.Pixels.get(0)); 4012 POINT2 ur = new POINT2(tg.Pixels.get(0)); 4013 GetMBR(tg, ul, ur, lr, ll); 4014 4015 AddIntegralAreaModifier(tg, label, aboveMiddle, csFactor, ll, lr, false); 4016 break; 4017 case TacticalLines.MFLANE: 4018 //pt0=tg.Pixels.get(7); 4019 //pt1=tg.Pixels.get(5); 4020 pt0 = tg.Pixels.get(4); 4021 pt1 = tg.Pixels.get(2); 4022 if (tg.Pixels.get(0).y < tg.Pixels.get(1).y) { 4023 addDTG(tg, aboveMiddle, 0.5 * csFactor, 1.5 * csFactor, pt0, pt1, metrics); 4024 } else { 4025 addDTG(tg, aboveMiddle, -0.5 * csFactor, -1.5 * csFactor, pt0, pt1, metrics); 4026 } 4027 break; 4028 case TacticalLines.CORDONKNOCK: 4029 case TacticalLines.CORDONSEARCH: 4030 case TacticalLines.DENY: 4031 pt0 = tg.Pixels.get(13); 4032 pt1 = tg.Pixels.get(0); 4033 stringWidth = metrics.stringWidth(label); 4034 if (pt0.x < pt1.x) { 4035 stringWidth = -stringWidth; 4036 } 4037 pt1 = lineutility.ExtendAlongLineDouble2(pt0, pt1, 0.75 * stringWidth); 4038 ptCenter = lineutility.MidPointDouble(pt0, pt1, 0); 4039 AddIntegralAreaModifier(tg, label, aboveMiddle, 0, ptCenter, ptCenter, true); 4040 break; 4041 case TacticalLines.ESCORT: 4042 if (tg.Pixels.size() == 6) { 4043 if (tg.Pixels.get(2).x == tg.Pixels.get(3).x && 4044 tg.Pixels.get(2).y == tg.Pixels.get(3).y) { 4045 //No Room for E labels 4046 break;//? 4047 } 4048 AddIntegralAreaModifier(tg, label, toEnd, 0, tg.Pixels.get(2), tg.Pixels.get(1), true); 4049 AddIntegralAreaModifier(tg, label, toEnd, 0, tg.Pixels.get(3), tg.Pixels.get(4), true); 4050 } 4051 break; 4052 case TacticalLines.EXFILTRATION: 4053 case TacticalLines.INFILTRATION: 4054 AddIntegralAreaModifier(tg, label, aboveMiddle, 0, pt0, pt1, true); 4055 break; 4056 case TacticalLines.FOLLA: 4057 pt0 = tg.Pixels.get(0); 4058 pt1 = lineutility.MidPointDouble(tg.Pixels.get(5), tg.Pixels.get(6), 0); 4059 pt1 = lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 4060 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, pt0, pt1, true); 4061 break; 4062 case TacticalLines.FOLSP: 4063 pt0 = tg.Pixels.get(3); 4064 pt1 = tg.Pixels.get(6); 4065 pt1 = lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 4066 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, pt0, pt1, true); 4067 break; 4068 /*case TacticalLines.ACA_RECTANGULAR: 4069 ptLeft = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 4070 ptRight = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 4071 AddModifier2(tg, label + TSpace + tg.get_Name(), aboveMiddle, -3 * csFactor, ptLeft, ptRight, false); 4072 AddModifier2(tg, tg.get_T1(), aboveMiddle, -2 * csFactor, ptLeft, ptRight, false, "T1"); 4073 AddModifier2(tg, "MIN ALT: " + tg.get_X(), aboveMiddle, -1 * csFactor, ptLeft, ptRight, false, "H"); 4074 AddModifier2(tg, "MAX ALT: " + tg.get_X1(), aboveMiddle, 0, ptLeft, ptRight, false, "H1"); 4075 AddModifier2(tg, "GRID " + tg.get_Location(), aboveMiddle, 1 * csFactor, ptLeft, ptRight, false, "H2"); 4076 AddModifier2(tg, "EFF " + tg.get_DTG() + WDash, aboveMiddle, 2 * csFactor, ptLeft, ptRight, false, "W"); 4077 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 3 * csFactor, ptLeft, ptRight, false, "W1"); 4078 break;//*/ 4079 case TacticalLines.ACA_RECTANGULAR://text always right-side-up like circular 4080 case TacticalLines.ACA_CIRCULAR: 4081 ptCenter = lineutility.CalcCenterPointDouble2(tg.Pixels.toArray(), tg.Pixels.size()); 4082 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, -3 * csFactor, ptCenter, ptCenter, false); 4083 AddModifier2(tg, tg.get_T1(), area, -2 * csFactor, ptCenter, ptCenter, false, "T1"); 4084 AddIntegralAreaModifier(tg, "MIN ALT: " + tg.get_X(), area, -1 * csFactor, ptCenter, ptCenter, false, "H"); 4085 AddIntegralAreaModifier(tg, "MAX ALT: " + tg.get_X1(), area, 0, ptCenter, ptCenter, false, "H1"); 4086 AddIntegralAreaModifier(tg, "GRID " + tg.get_Location(), area, 1 * csFactor, ptCenter, ptCenter, false, "H2"); 4087 AddIntegralAreaModifier(tg, "EFF " + tg.get_DTG() + WDash, area, 2 * csFactor, ptCenter, ptCenter, false, "W"); 4088 AddIntegralAreaModifier(tg, tg.get_DTG1(), area, 3 * csFactor, ptCenter, ptCenter, false, "W1"); 4089 break; 4090 case TacticalLines.FSA_CIRCULAR: 4091 case TacticalLines.ATI_CIRCULAR: 4092 case TacticalLines.CFFZ_CIRCULAR: 4093 case TacticalLines.SENSOR_CIRCULAR: 4094 case TacticalLines.CENSOR_CIRCULAR: 4095 case TacticalLines.DA_CIRCULAR: 4096 case TacticalLines.CFZ_CIRCULAR: 4097 case TacticalLines.ZOR_CIRCULAR: 4098 case TacticalLines.TBA_CIRCULAR: 4099 case TacticalLines.TVAR_CIRCULAR: 4100 case TacticalLines.KILLBOXBLUE_CIRCULAR: 4101 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 4102 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(tg.Pixels.size() / 2), 0); 4103 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 4104 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 4105 4106 //labels left of circle 4107 //AddOffsetModifier(tg, tg.get_DTG() + WDash, toEnd, -1 * csFactor, tg.Pixels.size() / 2, 0, 4, "left"); 4108 //AddOffsetModifier(tg, tg.get_DTG1(), toEnd, 0, tg.Pixels.size() / 2, 0, 4, "left"); 4109 4110 //labels top left of circle 4111 POINT2 dtgCircularPosition = tg.Pixels.get(Math.round(tg.Pixels.size() * 0.5625f)); 4112 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, toEnd, -2 * csFactor, dtgCircularPosition, new POINT2(dtgCircularPosition.x + 0.001, dtgCircularPosition.y, 0), false); 4113 AddIntegralAreaModifier(tg, tg.get_DTG1(), toEnd, -1 * csFactor, dtgCircularPosition, new POINT2(dtgCircularPosition.x + 0.001, dtgCircularPosition.y, 0), false); 4114 break; 4115 case TacticalLines.FFA_CIRCULAR: 4116 case TacticalLines.NFA_CIRCULAR: 4117 case TacticalLines.RFA_CIRCULAR: 4118 rfaLines = getRFALines(tg); 4119 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(51), 0); 4120 switch (rfaLines) { 4121 case 3: //2 valid modifiers and a label 4122 AddIntegralAreaModifier(tg, label, area, -1 * csFactor, ptCenter, ptCenter, false); 4123 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 4124 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 4125 break; 4126 case 2: //one valid modifier and a label 4127 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 4128 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 4129 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 4130 } else { 4131 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 4132 } 4133 break; 4134 default: //one label only 4135 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, false); 4136 break; 4137 } 4138 break; 4139 case TacticalLines.BLOCK: 4140 //for (j = 0; j < tg.Pixels.size(); j++) 4141 for (j = 0; j < n; j++) { 4142 if (tg.Pixels.get(j).style == 14) { 4143 AddIntegralModifier(tg, label, aboveMiddle, 0, j, j + 1); 4144 break; 4145 } 4146 } 4147 break; 4148 case TacticalLines.FFA_RECTANGULAR: 4149 case TacticalLines.NFA_RECTANGULAR: 4150 case TacticalLines.RFA_RECTANGULAR: 4151 rfaLines = getRFALines(tg); 4152 pt0 = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 4153 pt1 = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 4154 ptCenter = lineutility.MidPointDouble(pt0, pt1, 0); 4155 switch (rfaLines) { 4156 case 3: //2 valid modifiers and a label 4157 AddIntegralAreaModifier(tg, label, area, -1 * csFactor, ptCenter, ptCenter, false); 4158 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 4159 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 4160 break; 4161 case 2: //one valid modifier and a label 4162 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 4163 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 4164 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 4165 } else { 4166 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 4167 } 4168 break; 4169 default: //one label only 4170 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, false); 4171 break; 4172 } 4173 break; 4174 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 4175 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 4176 case TacticalLines.FSA_RECTANGULAR: 4177 case TacticalLines.ATI_RECTANGULAR: 4178 case TacticalLines.CFFZ_RECTANGULAR: 4179 case TacticalLines.SENSOR_RECTANGULAR: 4180 case TacticalLines.CENSOR_RECTANGULAR: 4181 case TacticalLines.DA_RECTANGULAR: 4182 case TacticalLines.CFZ_RECTANGULAR: 4183 case TacticalLines.ZOR_RECTANGULAR: 4184 case TacticalLines.TBA_RECTANGULAR: 4185 case TacticalLines.TVAR_RECTANGULAR: 4186 4187 ptLeft = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 4188 ptRight = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 4189 ptCenter = lineutility.MidPointDouble(ptLeft, ptRight, 0); 4190 4191 //labels upright 4192 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 4193 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 4194 4195 //labels on angle 4196 //AddModifier2(tg, label, aboveMiddle, -0.5 * csFactor, ptLeft, ptRight, false); 4197 //AddModifier2(tg, tg.get_Name(), aboveMiddle, 0.5 * csFactor, ptLeft, ptRight, false); 4198 4199 /*//DTG modifiers top left following angle 4200 pt0 = tg.Pixels.get(0); 4201 pt1 = tg.Pixels.get(1); 4202 pt2 = tg.Pixels.get(2); 4203 pt3 = tg.Pixels.get(3); 4204 4205 if (tg.get_Client().equalsIgnoreCase("ge")) { 4206 pt0.x -= font.getSize() / 2; 4207 pt2.x -= font.getSize() / 2; 4208 } 4209 if (!tg.get_Client().equalsIgnoreCase("ge"))//added 2-27-12 4210 { 4211 clsUtility.shiftModifiersLeft(pt0, pt3, 12.5); 4212 clsUtility.shiftModifiersLeft(pt1, pt2, 12.5); 4213 } 4214 4215 if (ptLeft.x == ptRight.x) { 4216 ptRight.x += 1; 4217 } 4218 if (ptLeft.x < ptRight.x) { 4219 AddModifier(tg, tg.get_DTG() + WDash, toEnd, 0, pt0, pt3);//was 1,2 switched for CPOF 4220 AddModifier(tg, tg.get_DTG1(), toEnd, 1 * csFactor, pt0, pt3);//was 1,2 4221 } else { 4222 AddModifier(tg, tg.get_DTG() + WDash, toEnd, 0, pt2, pt1);//was 3,0 //switched for CPOF 4223 AddModifier(tg, tg.get_DTG1(), toEnd, 1 * csFactor, pt2, pt1);//was 3,0 4224 }//*/ 4225 4226 //highest point left of center 4227 POINT2 dtgPosition = getHighestPointLeftOfCenter(tg.Pixels, ptCenter); 4228 4229 //DTG at north west-ish point and right-side-up 4230 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, toEnd, 0.5 * csFactor, dtgPosition, new POINT2(dtgPosition.x + 0.001, dtgPosition.y, 0), false); 4231 AddIntegralAreaModifier(tg, tg.get_DTG1() + " ", toEnd, 1.5 * csFactor, dtgPosition, new POINT2(dtgPosition.x + 0.001, dtgPosition.y, 0), false); 4232 4233 //DTG at first point and angled with rectangle 4234 //AddOffsetModifier(tg, tg.get_DTG() + WDash, toEnd, -1 * csFactor, tg.Pixels.size() / 2, 0, 4, "left"); 4235 //AddOffsetModifier(tg, tg.get_DTG1(), toEnd, 0, tg.Pixels.size() / 2, 0, 4, "left"); 4236 4237 break;//*/ 4238 case TacticalLines.PAA_RECTANGULAR: 4239 4240 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 4241 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, true);//label level 4242 //AddIntegralModifier(tg, label, aboveMiddlePerpendicular, 0, 0, 1, true);//label angled with line 4243 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(1), tg.Pixels.get(2), 0); 4244 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, true); 4245 //AddIntegralModifier(tg, label, aboveMiddle, 0, 1, 2, true); 4246 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 4247 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, true); 4248 //AddIntegralModifier(tg, label, aboveMiddlePerpendicular, 0, 2, 3, true); 4249 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(3), tg.Pixels.get(0), 0); 4250 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, true); 4251 //AddIntegralModifier(tg, label, aboveMiddle, 0, 3, 0, true); 4252 rfaLines = getRFALines(tg); 4253 pt0 = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 4254 pt1 = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 4255 ptCenter = lineutility.MidPointDouble(pt0, pt1, 0); 4256 switch (rfaLines) { 4257 case 3: // two valid modifiers 4258 if (!RendererSettings.getInstance().getGroupModifiers()) { 4259 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1.5, ptCenter, ptCenter, false); 4260 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 4261 } else { 4262 String modifier = buildAreaGroupString(tg, label); 4263 AddIntegralAreaModifier(tg, modifier, area, 0, ptCenter, ptCenter, false); 4264 } 4265 break; 4266 case 2: // one valid modifier 4267 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 4268 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 4269 } else { 4270 addDTG(tg, area, 0, csFactor, ptCenter, ptCenter, metrics); 4271 } 4272 break; 4273 default: 4274 break; 4275 } 4276 break; 4277 case TacticalLines.PAA_CIRCULAR: 4278 for (int i = 0; i < 4; i++) { 4279 AddIntegralModifier(tg, label, area, -0.5 * csFactor, n / 4 * i, n / 4 * i, false); 4280 } 4281 4282 rfaLines = getRFALines(tg); 4283 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get((int) (n / 2.0 + 0.5)), 0); 4284 switch (rfaLines) { 4285 case 3: // two valid modifiers 4286 if (!RendererSettings.getInstance().getGroupModifiers()) { 4287 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1.5, ptCenter, ptCenter, false); 4288 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 4289 } else { 4290 String modifier = buildAreaGroupString(tg, label); 4291 AddIntegralAreaModifier(tg, modifier, area, 0, ptCenter, ptCenter, false); 4292 } 4293 break; 4294 case 2: // one valid modifier 4295 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 4296 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 4297 } else { 4298 addDTG(tg, area, 0, csFactor, ptCenter, ptCenter, metrics); 4299 } 4300 break; 4301 default: 4302 break; 4303 } 4304 break; 4305 case TacticalLines.RANGE_FAN: 4306 if (tg.get_X() != null) { 4307 X = tg.get_X().split(","); 4308 for (j = 0; j < X.length; j++) { 4309 if (tg.Pixels.size() > j * 102 + 25) { 4310 pt0 = tg.Pixels.get(j * 102 + 25); 4311 AddAreaModifier(tg, "ALT " + X[j], area, 0, pt0, pt0); 4312 } 4313 } 4314 } 4315 if (!tg.get_HideOptionalLabels()) { 4316 String[] am = tg.get_AM().split(","); 4317 for (j = 0; j < am.length; j++) { 4318 if (tg.Pixels.size() > j * 102 + 25) { 4319 pt0 = tg.Pixels.get(j * 102 + 25); 4320 //AddAreaModifier(tg, "RG " + am[j], area, -1, pt0, pt0); 4321 if (j == 0) 4322 AddAreaModifier(tg, "MIN RG " + removeDecimal(am[j]), 3, -1, pt0, pt0); 4323 else 4324 AddAreaModifier(tg, "MAX RG " + "(" + Integer.toString(j) + ") " + removeDecimal(am[j]), 3, -1, pt0, pt0); 4325 } 4326 } 4327 }// end if set range fan text 4328 break; 4329 case TacticalLines.RANGE_FAN_SECTOR: 4330 case TacticalLines.RADAR_SEARCH: 4331 addSectorModifiers(tg, converter); 4332 break; 4333 case TacticalLines.ENVELOPMENT: 4334 AddIntegralModifier(tg, label, aboveMiddle, 0, 0, 1, true); 4335 break; 4336 case TacticalLines.MOBILE_DEFENSE: 4337 AddIntegralModifier(tg, label, area, 0, 16, 16, true); 4338 break; 4339 default: 4340 break; 4341 }//end switch 4342 } 4343 scaleModifiers(tg); 4344 tg.Pixels = origPoints; 4345 g2d.dispose(); 4346 g2d = null; 4347 } catch (Exception exc) { 4348 ErrorLogger.LogException(_className, "AddModifiers2", 4349 new RendererException("Failed inside AddModifiers2", exc)); 4350 } 4351 } 4352 4353 /** 4354 * Calculates the highest point that is left-of-center given symbol center point and points 4355 * @param pixels Points that make the symbol 4356 * @param ptCenter Represents the center of the symbol 4357 * @return Point that is the highest point, left-of-center 4358 */ 4359 private static POINT2 getHighestPointLeftOfCenter(ArrayList<POINT2> pixels, POINT2 ptCenter) 4360 { 4361 //highest point left of center 4362 POINT2 highest = pixels.get(0); 4363 boolean validPointFound = false; 4364 for (POINT2 p : pixels) //loop through points 4365 { 4366 if(p.x <= ptCenter.x)//we only care about points left of center 4367 { 4368 if(!validPointFound)//find initial left-of-center point 4369 { 4370 highest = p;//set initial value 4371 validPointFound = true; 4372 } 4373 else if(p.y < highest.y)//see if this point is higher than the current point 4374 highest = p;//set new highest, left-of-center point 4375 } 4376 } 4377 return highest; 4378 } 4379 private static String buildAreaGroupString(TGLight tg, String label) 4380 { 4381 int linetype = tg.get_LineType(); 4382 String modifier = ""; 4383 switch (linetype) 4384 { 4385 case TacticalLines.PAA: 4386 case TacticalLines.PAA_CIRCULAR: 4387 case TacticalLines.PAA_RECTANGULAR: 4388 modifier = tg.get_Name(); 4389 if(tg.get_DTG() != null && !tg.get_DTG().isEmpty()) 4390 modifier += "\n" + tg.get_DTG() + " -"; 4391 if(tg.get_DTG1() != null && !tg.get_DTG1().isEmpty()) 4392 modifier += "\n" + tg.get_DTG1(); 4393 break; 4394 case TacticalLines.ACA: 4395 case TacticalLines.ACA_CIRCULAR: 4396 case TacticalLines.ACA_RECTANGULAR: 4397 modifier += label + " " + tg.get_Name(); 4398 modifier += "\n" + tg.get_T1(); 4399 modifier += "\n" + "MIN ALT: " + tg.get_X(); 4400 modifier += "\n" + "MAX ALT: " + tg.get_X1(); 4401 modifier += "\n" + "GRID: " + tg.get_Location(); 4402 modifier += "\n" + "EFF: " + tg.get_DTG() + " -"; 4403 modifier += "\n" + tg.get_DTG1(); 4404 break; 4405 case TacticalLines.FFA: 4406 case TacticalLines.NFA: 4407 case TacticalLines.RFA: 4408 case TacticalLines.FFA_RECTANGULAR: 4409 case TacticalLines.NFA_RECTANGULAR: 4410 case TacticalLines.RFA_RECTANGULAR: 4411 case TacticalLines.FFA_CIRCULAR: 4412 case TacticalLines.NFA_CIRCULAR: 4413 case TacticalLines.RFA_CIRCULAR: 4414 modifier = label + "\n" + tg.get_Name(); 4415 if(tg.get_DTG() != null && !tg.get_DTG().isEmpty()) 4416 modifier += "\n" + tg.get_DTG() + " -"; 4417 if(tg.get_DTG1() != null && !tg.get_DTG1().isEmpty()) 4418 modifier += "\n" + tg.get_DTG1(); 4419 break; 4420 case TacticalLines.FSA: 4421 modifier = label + " " + tg.get_Name(); 4422 if(tg.get_DTG() != null && !tg.get_DTG().isEmpty()) 4423 modifier += "\n" + tg.get_DTG() + " -"; 4424 if(tg.get_DTG1() != null && !tg.get_DTG1().isEmpty()) 4425 modifier += "\n" + tg.get_DTG1(); 4426 break; 4427 case TacticalLines.ATI: 4428 case TacticalLines.CFFZ: 4429 case TacticalLines.CFZ: 4430 case TacticalLines.TBA: 4431 case TacticalLines.TVAR: 4432 case TacticalLines.ZOR: 4433 case TacticalLines.DA: 4434 case TacticalLines.SENSOR: 4435 case TacticalLines.CENSOR: 4436 case TacticalLines.KILLBOXBLUE: 4437 case TacticalLines.KILLBOXPURPLE: 4438 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 4439 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 4440 case TacticalLines.FSA_RECTANGULAR: 4441 case TacticalLines.ATI_RECTANGULAR: 4442 case TacticalLines.CFFZ_RECTANGULAR: 4443 case TacticalLines.SENSOR_RECTANGULAR: 4444 case TacticalLines.CENSOR_RECTANGULAR: 4445 case TacticalLines.DA_RECTANGULAR: 4446 case TacticalLines.CFZ_RECTANGULAR: 4447 case TacticalLines.ZOR_RECTANGULAR: 4448 case TacticalLines.TBA_RECTANGULAR: 4449 case TacticalLines.TVAR_RECTANGULAR: 4450 case TacticalLines.FSA_CIRCULAR: 4451 case TacticalLines.ATI_CIRCULAR: 4452 case TacticalLines.CFFZ_CIRCULAR: 4453 case TacticalLines.SENSOR_CIRCULAR: 4454 case TacticalLines.CENSOR_CIRCULAR: 4455 case TacticalLines.DA_CIRCULAR: 4456 case TacticalLines.CFZ_CIRCULAR: 4457 case TacticalLines.ZOR_CIRCULAR: 4458 case TacticalLines.TBA_CIRCULAR: 4459 case TacticalLines.TVAR_CIRCULAR: 4460 case TacticalLines.KILLBOXBLUE_CIRCULAR: 4461 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 4462 modifier = label + "\n" + tg.get_Name(); 4463 break; 4464 case TacticalLines.WFZ_REVD: 4465 case TacticalLines.OBSFAREA: 4466 modifier = label; 4467 modifier += "\n" + tg.get_Name(); 4468 modifier += "\n" + "TIME FROM: " + tg.get_DTG(); 4469 modifier += "\n" + "TIME TO: " + tg.get_DTG1(); 4470 break; 4471 case TacticalLines.OBSAREA: 4472 modifier = tg.get_Name(); 4473 modifier += "\n" + "TIME FROM: " + tg.get_DTG(); 4474 modifier += "\n" + "TIME TO: " + tg.get_DTG1(); 4475 break; 4476 case TacticalLines.WFZ: 4477 case TacticalLines.ROZ: 4478 case TacticalLines.AARROZ: 4479 case TacticalLines.UAROZ: 4480 case TacticalLines.WEZ: 4481 case TacticalLines.FEZ: 4482 case TacticalLines.JEZ: 4483 case TacticalLines.FAADZ: 4484 case TacticalLines.HIDACZ: 4485 case TacticalLines.MEZ: 4486 case TacticalLines.LOMEZ: 4487 case TacticalLines.HIMEZ: 4488 modifier = label; 4489 modifier += "\n" + tg.get_Name(); 4490 modifier += "\n" + "MIN ALT: " + tg.get_X(); 4491 modifier += "\n" + "MAX ALT: " + tg.get_X1(); 4492 modifier += "\n" + "TIME FROM: " + tg.get_DTG(); 4493 modifier += "\n" + "TIME TO: " + tg.get_DTG1(); 4494 break; 4495 } 4496 return modifier; 4497 } 4498 4499 private static String buildAreaGroupDTGString(TGLight tg) 4500 { 4501 String modifier = ""; 4502 4503 if(tg.get_DTG() != null && !tg.get_DTG().isEmpty()) 4504 modifier += tg.get_DTG() + " -"; 4505 if(tg.get_DTG1() != null && !tg.get_DTG1().isEmpty()) 4506 modifier += "\n" + tg.get_DTG1(); 4507 4508 return modifier; 4509 } 4510 4511 /** 4512 * Displays the tg modifiers using a client Graphics2D, this is an option 4513 * provided to clients for displaying modifiers without using shapes 4514 * 4515 * @param tg the tactical graphic 4516 * @param g2d the graphics object for drawing 4517 * @deprecated 4518 */ 4519 public static void DisplayModifiers(TGLight tg, 4520 Graphics2D g2d) { 4521 try { 4522 Font font = g2d.getFont(); 4523 int j = 0; 4524 Modifier2 modifier = null; 4525 g2d.setBackground(Color.white); 4526 POINT2 pt = null; 4527 double theta = 0; 4528 int stringWidth = 0, stringHeight = 0; 4529 FontMetrics metrics = g2d.getFontMetrics(); 4530 String s = ""; 4531 int x = 0, y = 0; 4532 POINT2 pt1 = null, pt2 = null; 4533 int quadrant = -1; 4534 int n = tg.Pixels.size(); 4535 //for (j = 0; j < tg.modifiers.size(); j++) 4536 for (j = 0; j < n; j++) { 4537 modifier = (Modifier2) tg.modifiers.get(j); 4538 double lineFactor = modifier.lineFactor; 4539 s = modifier.text; 4540 double x1 = 0, y1 = 0, x2 = 0, y2 = 0; 4541 pt = modifier.textPath[0]; 4542 x1 = pt.x; 4543 y1 = pt.y; 4544 pt = modifier.textPath[1]; 4545 x2 = pt.x; 4546 y2 = pt.y; 4547 theta = Math.atan2(y2 - y1, x2 - x1); 4548 POINT2 midPt; 4549 if (x1 > x2) { 4550 theta -= Math.PI; 4551 } 4552 switch (modifier.type) { 4553 case toEnd: //corresponds to LabelAndTextBeforeLineTG 4554 g2d.rotate(theta, x1, y1); 4555 stringWidth = metrics.stringWidth(s); 4556 stringHeight = font.getSize(); 4557 if (x1 < x2 || (x1 == x2 && y1 > y2)) { 4558 x = (int) x1 - stringWidth; 4559 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4560 g2d.setColor(tg.get_FontBackColor()); 4561 g2d.clearRect(x, y, stringWidth, stringHeight); 4562 y = (int) y1 + (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4563 g2d.setColor(tg.get_TextColor()); 4564 g2d.drawString(s, x, y); 4565 } else { 4566 x = (int) x1; 4567 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4568 g2d.setColor(tg.get_FontBackColor()); 4569 g2d.clearRect(x, y, stringWidth, stringHeight); 4570 y = (int) y1 + (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4571 g2d.setColor(tg.get_TextColor()); 4572 g2d.drawString(s, x, y); 4573 } 4574 break; 4575 case aboveMiddle: 4576 midPt = new POINT2((x1 + x2) / 2, (y1 + y2) / 2); 4577 g2d.rotate(theta, midPt.x, midPt.y); 4578 stringWidth = metrics.stringWidth(s); 4579 stringHeight = font.getSize(); 4580 x = (int) midPt.x - stringWidth / 2; 4581 y = (int) midPt.y - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4582 g2d.setColor(tg.get_FontBackColor()); 4583 g2d.clearRect(x, y, stringWidth, stringHeight); 4584 y = (int) midPt.y + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4585 g2d.setColor(tg.get_TextColor()); 4586 g2d.drawString(s, x, y); 4587 break; 4588 case area: 4589 g2d.rotate(0, x1, y1); 4590 stringWidth = metrics.stringWidth(s); 4591 stringHeight = font.getSize(); 4592 4593 x = (int) x1 - stringWidth / 2; 4594 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4595 g2d.setColor(tg.get_FontBackColor()); 4596 g2d.clearRect(x, y, stringWidth, stringHeight); 4597 y = (int) y1 + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4598 g2d.setColor(tg.get_TextColor()); 4599 g2d.drawString(s, x, y); 4600 break; 4601 case screen: //for SCREEN, GUARD, COVER 4602 if (tg.Pixels.size() >= 14) { 4603 pt1 = tg.Pixels.get(3); 4604 pt2 = tg.Pixels.get(10); 4605 quadrant = lineutility.GetQuadrantDouble(pt1, pt2); 4606 theta = Math.atan2(pt2.y - pt1.y, pt2.x - pt1.x); 4607 switch (quadrant) { 4608 case 1: 4609 theta += Math.PI / 2; 4610 break; 4611 case 2: 4612 theta -= Math.PI / 2; 4613 break; 4614 case 3: 4615 theta -= Math.PI / 2; 4616 break; 4617 case 4: 4618 theta += Math.PI / 2; 4619 break; 4620 default: 4621 break; 4622 } 4623 4624 g2d.rotate(theta, x1, y1); 4625 stringWidth = metrics.stringWidth(s); 4626 stringHeight = font.getSize(); 4627 4628 x = (int) x1 - stringWidth / 2; 4629 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4630 g2d.setColor(tg.get_FontBackColor()); 4631 g2d.clearRect(x, y, stringWidth, stringHeight); 4632 y = (int) y1 + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4633 g2d.setColor(tg.get_TextColor()); 4634 g2d.drawString(s, x, y); 4635 } else { 4636 stringWidth = metrics.stringWidth(s); 4637 stringHeight = font.getSize(); 4638 x = (int) tg.Pixels.get(0).x;//(int) x1 - stringWidth / 2; 4639 y = (int) tg.Pixels.get(0).y;//(int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4640 g2d.setColor(tg.get_FontBackColor()); 4641 g2d.clearRect(x, y, stringWidth, stringHeight); 4642 y = (int) y + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4643 g2d.setColor(tg.get_TextColor()); 4644 g2d.drawString(s, x, y); 4645 } 4646 break; 4647 default: 4648 break; 4649 } //end switch 4650 } //end for 4651 } catch (Exception exc) { 4652 ErrorLogger.LogException(_className, "DisplayModifiers", 4653 new RendererException("Failed inside DisplayModifiers", exc)); 4654 } 4655 }//end function 4656 4657 /** 4658 * Returns a Shape object for the text background for labels and modifiers 4659 * 4660 * @param tg the tactical graphic object 4661 * @param pt0 1st point of segment 4662 * @param pt1 last point of segment 4663 * @param stringWidth string width 4664 * @param stringHeight string height 4665 * @param lineFactor number of text lines above or below the segment 4666 * @param isTextFlipped true if text is flipped 4667 * @return the modifier shape 4668 */ 4669 public static Shape2 BuildModifierShape( 4670 TGLight tg, 4671 POINT2 pt0, 4672 POINT2 pt1, 4673 int stringWidth, 4674 int stringHeight, 4675 double lineFactor, 4676 boolean isTextFlipped) { 4677 Shape2 modifierFill = null; 4678 try { 4679 4680 POINT2 ptTemp0 = new POINT2(pt0), ptTemp1 = new POINT2(pt1); 4681 4682 if (isTextFlipped) { 4683 lineFactor += 1; 4684 } 4685 4686 if (lineFactor < 0) //extend pt0,pt1 above the line 4687 { 4688 ptTemp0 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, 2, -lineFactor * stringHeight); 4689 ptTemp1 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 2, -lineFactor * stringHeight); 4690 } 4691 if (lineFactor > 0) //extend pt0,pt1 below the line 4692 { 4693 ptTemp0 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, 3, lineFactor * stringHeight); 4694 ptTemp1 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 3, lineFactor * stringHeight); 4695 } 4696 if (ptTemp0.y == ptTemp1.y) { 4697 ptTemp0.y += 1; 4698 } 4699 4700 POINT2 pt3 = null, pt4 = null, pt5 = null, pt6 = null, pt7 = null; 4701 pt3 = lineutility.ExtendAlongLineDouble(ptTemp0, ptTemp1, -stringWidth); 4702 pt4 = lineutility.ExtendDirectedLine(ptTemp1, ptTemp0, pt3, 0, stringHeight / 2); 4703 pt5 = lineutility.ExtendDirectedLine(ptTemp1, ptTemp0, pt3, 1, stringHeight / 2); 4704 pt6 = lineutility.ExtendDirectedLine(ptTemp1, ptTemp0, ptTemp0, 1, stringHeight / 2); 4705 pt7 = lineutility.ExtendDirectedLine(ptTemp1, ptTemp0, ptTemp0, 0, stringHeight / 2); 4706 modifierFill = new Shape2(Shape2.SHAPE_TYPE_MODIFIER_FILL); 4707 4708 modifierFill.moveTo(pt4); 4709 modifierFill.lineTo(pt5); 4710 modifierFill.lineTo(pt6); 4711 modifierFill.lineTo(pt7); 4712 modifierFill.lineTo(pt4); 4713 } catch (Exception exc) { 4714 ErrorLogger.LogException(_className, "BuildModifierShape", 4715 new RendererException("Failed inside BuildModifierShape", exc)); 4716 } 4717 return modifierFill; 4718 } 4719 4720 /** 4721 * For BOUNDARY and other line types which require breaks for the integral 4722 * text. Currently only boundary uses this 4723 * 4724 * @param tg 4725 * @param g2d the graphics object for drawing 4726 * @param shapes the shape array 4727 */ 4728 public static void GetIntegralTextShapes(TGLight tg, 4729 Graphics2D g2d, 4730 ArrayList<Shape2> shapes) { 4731 try { 4732 if (tg.Pixels == null || shapes == null) { 4733 return; 4734 } 4735 4736 HashMap<Integer, Color> hmap = clsUtility.getMSRSegmentColors(tg); 4737 Color color = null; 4738 4739 Shape2 shape = null; 4740 Shape2 segShape = null;//diangostic 1-22-13 4741 g2d.setFont(tg.get_Font()); 4742 int j = 0; 4743 String affiliation = null; 4744 FontMetrics metrics = g2d.getFontMetrics(); 4745 String echelonSymbol = null; 4746 int stringWidthEchelonSymbol = 0; 4747 //boolean lineTooShort = false; 4748 POINT2 ptEchelonStart = null, ptEchelonEnd = null, midpt, 4749 ptENY0Start = null, ptENY0End = null, ptENY1Start, ptENY1End, pt0 = null, pt1 = null; 4750 double dist = 0; 4751 BasicStroke stroke = null; 4752 switch (tg.get_LineType()) { 4753 case TacticalLines.BOUNDARY: 4754 echelonSymbol = tg.get_EchelonSymbol(); 4755 //shapes = new ArrayList(); 4756 shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE); 4757 shape.setLineColor(tg.get_LineColor()); 4758 shape.set_Style(tg.get_LineStyle()); 4759 stroke = clsUtility.getLineStroke(tg.get_LineThickness(), shape.get_Style(), tg.get_lineCap(), BasicStroke.JOIN_ROUND); 4760 shape.setStroke(stroke); 4761 if (echelonSymbol != null && !echelonSymbol.isEmpty()) { 4762 stringWidthEchelonSymbol = metrics.stringWidth(echelonSymbol); 4763 } 4764 //diagnostic 4765 if (hmap == null || hmap.isEmpty()) { 4766 shape.moveTo(tg.Pixels.get(0)); 4767 for (j = 1; j < tg.Pixels.size(); j++) { 4768 shape.lineTo(tg.Pixels.get(j)); 4769 } 4770 shapes.add(shape); 4771 break; 4772 } 4773 //end section 4774 int n = tg.Pixels.size(); 4775 //for (j = 0; j < tg.Pixels.size() - 1; j++) 4776 for (j = 0; j < n - 1; j++) { 4777 segShape = null; 4778 if (hmap != null) { 4779 if (hmap.containsKey(j)) { 4780 color = (Color) hmap.get(j); 4781 segShape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE); 4782 segShape.setLineColor(color); 4783 segShape.set_Style(tg.get_LineStyle()); 4784 segShape.setStroke(stroke); 4785 } 4786 } 4787 4788 pt0 = tg.Pixels.get(j); 4789 pt1 = tg.Pixels.get(j + 1); 4790 //lineTooShort = GetBoundarySegmentTooShort(tg, g2d, j); 4791 if (segShape != null) { 4792 segShape.moveTo(pt0); 4793 } else { 4794 shape.moveTo(pt0); 4795 } 4796 4797 //uncoment comment to remove line breaks for GE 4798 //if (lineTooShort || tg.get_Client().equals("ge")) 4799 if (tg.get_Client().equals("ge") || GetBoundarySegmentTooShort(tg, g2d, j) == true) { 4800 if (segShape != null) { 4801 segShape.lineTo(pt1); 4802 shapes.add(segShape); 4803 continue; 4804 } else { 4805 shape.lineTo(pt1); 4806 continue; 4807 } 4808 } 4809 4810 midpt = lineutility.MidPointDouble(pt0, pt1, 0); 4811 if (segShape != null) { 4812 segShape.moveTo(pt0); 4813 } else { 4814 shape.moveTo(pt0); 4815 } 4816 4817 if (stringWidthEchelonSymbol > 0) { 4818 midpt = lineutility.MidPointDouble(pt0, pt1, 0); 4819 dist = lineutility.CalcDistanceDouble(pt0, midpt) - stringWidthEchelonSymbol / 1.5; 4820 ptEchelonStart = lineutility.ExtendAlongLineDouble(pt0, pt1, dist); 4821 dist = lineutility.CalcDistanceDouble(pt0, midpt) + stringWidthEchelonSymbol / 1.5; 4822 ptEchelonEnd = lineutility.ExtendAlongLineDouble(pt0, pt1, dist); 4823 if (segShape != null) { 4824 segShape.lineTo(ptEchelonStart); 4825 segShape.moveTo(ptEchelonEnd); 4826 } else { 4827 shape.lineTo(ptEchelonStart); 4828 shape.moveTo(ptEchelonEnd); 4829 } 4830 } 4831 if (segShape != null) { 4832 segShape.lineTo(pt1); 4833 } else { 4834 shape.lineTo(pt1); 4835 } 4836 if (segShape != null) { 4837 shapes.add(segShape); 4838 } 4839 }//end for 4840 shapes.add(shape); 4841 break; 4842 default: 4843 break; 4844 } 4845 } catch (Exception exc) { 4846 ErrorLogger.LogException(_className, "GetIntegralTextShapes", 4847 new RendererException("Failed inside GetIntegralTextShapes", exc)); 4848 } 4849 } 4850 4851 /** 4852 * Displays the modifiers to a Graphics2D from a BufferedImage 4853 * 4854 * @param tg the tactical graphic 4855 * @param g2d the Graphic for drawing 4856 * @param shapes the shape array 4857 * @param isTextFlipped true if text is flipped 4858 * @param converter to convert between geographic and pixel coordinates 4859 */ 4860 public static void DisplayModifiers2(TGLight tg, 4861 Graphics2D g2d, 4862 ArrayList<Shape2> shapes, 4863 boolean isTextFlipped, 4864 IPointConversion converter) { 4865 try { 4866 if (shapes == null) { 4867 return; 4868 } 4869 4870 if (tg.modifiers == null || tg.modifiers.isEmpty()) { 4871 return; 4872 } 4873 Font font = null; 4874 int j = 0; 4875 Modifier2 modifier = null; 4876 Color fontBackColor = tg.get_FontBackColor(); 4877 double theta = 0; 4878 double stringWidth = 0, stringHeight = 0; 4879 String s = ""; 4880 Bitmap image = null; 4881 int x = 0, y = 0; 4882 POINT2 pt0 = null, pt1 = null, pt2 = null, pt3 = null; 4883 int quadrant = -1; 4884 Shape2 shape2 = null; 4885 long lineType = tg.get_LineType(); 4886 font = tg.get_Font(); //might have to change this 4887 if (font == null) { 4888 font = g2d.getFont(); 4889 } 4890 if (font.getSize() == 0) { 4891 return; 4892 } 4893 g2d.setFont(font); 4894 FontMetrics metrics = g2d.getFontMetrics(); 4895 //we need a background color 4896 if (fontBackColor != null) { 4897 g2d.setBackground(fontBackColor); 4898 } else { 4899 g2d.setBackground(Color.white); 4900 } 4901 4902 Point2D anchor = null; 4903 Point2D anchorOffset = null; 4904 4905 int direction = -1; 4906 Point glyphPosition = null; 4907 for (j = 0; j < tg.modifiers.size(); j++) { 4908 modifier = (Modifier2) tg.modifiers.get(j); 4909 4910 double lineFactor = modifier.lineFactor; 4911 4912 if (isTextFlipped) { 4913 lineFactor = -lineFactor; 4914 } 4915 4916 s = modifier.text; 4917 if (s == null || s.equals("")) { 4918 4919 image = modifier.image; 4920 if (image == null) { 4921 continue; 4922 } 4923 } 4924 stringWidth = s != null ? (double) metrics.stringWidth(s) + 1 : image.getWidth() + 1; 4925 stringHeight = s != null ? (double) font.getSize() : image.getHeight(); 4926 4927 double x1 = 0, y1 = 0, x2 = 0, y2 = 0, dist = 0; 4928 pt0 = modifier.textPath[0]; 4929 x1 = Math.round(pt0.x); 4930 y1 = Math.round(pt0.y); 4931 pt1 = modifier.textPath[1]; 4932 x2 = Math.round(pt1.x); 4933 y2 = Math.round(pt1.y); 4934 theta = Math.atan2(y2 - y1, x2 - x1); 4935 POINT2 midPt; 4936 if (x1 > x2) { 4937 theta -= Math.PI; 4938 } 4939 pt0 = new POINT2(x1, y1); 4940 pt1 = new POINT2(x2, y2); 4941 midPt = new POINT2((x1 + x2) / 2, (y1 + y2) / 2); 4942 Point2D modifierPosition = null; //use this if using justify 4943 int justify = ShapeInfo.justify_left; 4944 switch (modifier.type) { 4945 case aboveEnd: // On line 4946 case toEnd: // Next to line 4947 if (x1 == x2) { 4948 x2 += 1; 4949 } 4950 4951 if (lineFactor >= 0) { 4952 direction = 2; 4953 } else { 4954 direction = 3; 4955 } 4956 4957 if (lineType == TacticalLines.LC || tg.get_Client().equalsIgnoreCase("ge")) { 4958 direction = lineutility.reverseDirection(direction); 4959 } 4960 4961 if ((modifier.type == toEnd && x1 < x2) || (modifier.type == aboveEnd && x2 < x1)) { 4962 justify = ShapeInfo.justify_right; 4963 } else { 4964 justify = ShapeInfo.justify_left; 4965 } 4966 4967 //3rd point value is location to start perpendicular line from 4968 pt3 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, direction, lineFactor * stringHeight); 4969 //pt3 is the end point of the perpendicularline 4970 4971 glyphPosition = new Point((int) pt3.x, (int) pt3.y); 4972 modifierPosition = new Point2D.Double(pt3.x, pt3.y); 4973 4974 anchor = new Point2D.Double(pt0.x, pt0.y); 4975 anchorOffset = new Point2D.Double(pt3.x - pt0.x, pt3.y - pt0.y); 4976 4977 //adjust so it doesn't start right on top of the line. 4978 if(justify == ShapeInfo.justify_right) 4979 anchorOffset.setLocation(anchorOffset.getX() - font.getSize()/2f,anchorOffset.getY()); 4980 else if(justify == ShapeInfo.justify_left) 4981 anchorOffset.setLocation(anchorOffset.getX() + font.getSize()/2f,anchorOffset.getY()); 4982 4983 if(image != null)//images are centered and don't have text justification 4984 anchorOffset = new Point2D.Double(pt1.x - pt0.x, pt1.y - pt0.y); 4985 4986 break; 4987 case aboveStartInside: 4988 //returns pt3 which is based on the specified distance from pt0 along the line of pt0 to pt1. 4989 pt3 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 4990 4991 glyphPosition = new Point((int) pt3.x, (int) pt3.y); 4992 modifierPosition = new Point2D.Double((int) pt3.x, pt3.y); 4993 4994 anchor = new Point2D.Double(pt0.x, pt0.y); 4995 anchorOffset = new Point2D.Double(pt3.x - pt0.x, pt3.y - pt0.y); 4996 break; 4997 case aboveEndInside: 4998 //returns pt3 which is based on the specified distance from pt0 along the line of pt1 to pt0. 4999 pt3 = lineutility.ExtendAlongLineDouble(pt1, pt0, stringWidth); 5000 5001 glyphPosition = new Point((int) pt3.x, (int) pt3.y); 5002 modifierPosition = new Point2D.Double((int) pt3.x, pt3.y); 5003 5004 anchor = new Point2D.Double(pt1.x, pt1.y); 5005 anchorOffset = new Point2D.Double(pt3.x - pt1.x, pt3.y - pt1.y); 5006 break; 5007 case aboveMiddle: 5008 case aboveMiddlePerpendicular: 5009 pt2 = midPt; 5010 anchor = new Point2D.Double(midPt.x,midPt.y); 5011 5012 if (tg.get_Client().equals("2D")) { 5013 lineFactor += 0.5; 5014 } 5015 5016 if (lineFactor >= 0) { 5017 pt3 = lineutility.ExtendDirectedLine(pt0, pt2, pt2, 3, Math.abs((lineFactor) * stringHeight)); 5018 midPt = lineutility.ExtendDirectedLine(pt0, midPt, midPt, 3, Math.abs((lineFactor) * stringHeight)); 5019 } else { 5020 pt3 = lineutility.ExtendDirectedLine(pt0, pt2, pt2, 2, Math.abs((lineFactor) * stringHeight)); 5021 midPt = lineutility.ExtendDirectedLine(pt0, midPt, midPt, 2, Math.abs((lineFactor) * stringHeight)); 5022 } 5023 //pt3=lineutility.ExtendDirectedLine(pt0, pt2, pt2, 2, lineFactor*stringHeight); 5024 if (x1 == x2 && y1 > y2) { 5025 pt3 = lineutility.ExtendDirectedLine(pt0, pt2, pt2, 1, Math.abs((lineFactor) * stringHeight)); 5026 midPt = lineutility.ExtendDirectedLine(pt0, midPt, midPt, 1, Math.abs((lineFactor) * stringHeight)); 5027 } 5028 if (x1 == x2 && y1 < y2) { 5029 pt3 = lineutility.ExtendDirectedLine(pt0, pt2, pt2, 0, Math.abs((lineFactor) * stringHeight)); 5030 midPt = lineutility.ExtendDirectedLine(pt0, midPt, midPt, 0, Math.abs((lineFactor) * stringHeight)); 5031 } 5032 5033 glyphPosition = new Point((int) pt3.x, (int) pt3.y); 5034 justify = ShapeInfo.justify_center; 5035 modifierPosition = new Point2D.Double(midPt.x, midPt.y); 5036 5037 //anchor = new Point2D.Double(midPt.x, midPt.y); 5038 anchorOffset = new Point2D.Double(midPt.x - anchor.getX(), midPt.y - anchor.getY()); 5039 5040 if(modifier.type == aboveMiddlePerpendicular) { 5041 // Need to negate the original rotation 5042 if (x1 > x2) { 5043 theta += Math.PI; 5044 } 5045 // Adjust the label rotation based on the y values 5046 if (y1 > y2) { 5047 theta += Math.PI; 5048 } 5049 // Rotate by 90 degrees. This is how we rotate the label perpendicular to the line 5050 theta -= Math.PI / 2; 5051 } 5052 break; 5053 case area: 5054 theta = 0; 5055 5056 //y = (int) y1 + (int) (stringHeight / 2) + (int) (1.25 * lineFactor * stringHeight); 5057 y = (int) y1 + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 5058 x = image != null ? (int) (x1 - stringWidth / 3) : (int) x1; 5059 5060 glyphPosition = new Point(x, y); 5061 justify = ShapeInfo.justify_center; 5062 modifierPosition = new Point2D.Double(x, y); 5063 5064 anchor = new Point2D.Double(x1, y1); 5065 anchorOffset = new Point2D.Double(x - x1, y - y1); 5066 break; 5067 case areaImage: 5068 glyphPosition = new Point((int)x1, (int)y1); 5069 justify = ShapeInfo.justify_center; 5070 modifierPosition = new Point2D.Double((int)x1, (int)y1); 5071 5072 anchor = new Point2D.Double(x1, y1); 5073 anchorOffset = new Point2D.Double(0, 0); 5074 break; 5075 case screen: //for SCREEN, GUARD, COVER, not currently used 5076 if (tg.Pixels.size() >= 14) { 5077 pt1 = tg.Pixels.get(3); 5078 pt2 = tg.Pixels.get(10); 5079 quadrant = lineutility.GetQuadrantDouble(pt1, pt2); 5080 theta = Math.atan2(pt2.y - pt1.y, pt2.x - pt1.x); 5081 if (Math.abs(theta) < Math.PI / 8) { 5082 if (theta < 0) { 5083 theta -= Math.PI / 2; 5084 } else { 5085 theta += Math.PI / 2; 5086 } 5087 } 5088 switch (quadrant) { 5089 case 1: 5090 theta += Math.PI / 2; 5091 break; 5092 case 2: 5093 theta -= Math.PI / 2; 5094 break; 5095 case 3: 5096 theta -= Math.PI / 2; 5097 break; 5098 case 4: 5099 theta += Math.PI / 2; 5100 break; 5101 default: 5102 break; 5103 } 5104 5105 x = (int) x1 - (int) stringWidth / 2; 5106 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 5107 y = (int) y1 + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 5108 anchor = new Point2D.Double(x1, y1); 5109 } else { 5110 theta = 0; 5111 x = (int) tg.Pixels.get(0).x; 5112 y = (int) tg.Pixels.get(0).y; 5113 anchor = new Point2D.Double(x, y); 5114 x = (int) x - (int) stringWidth / 2; 5115 y = (int) y - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 5116 y = (int) y + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 5117 } 5118 5119 glyphPosition = new Point(x, y); 5120 //glyphPosition=new Point2D.Double(x,y); 5121 //anchor = new Point2D.Double(x1, y1); 5122 anchorOffset = new Point2D.Double(x - anchor.getX(), y - anchor.getY()); 5123 break; 5124 default: 5125 break; 5126 } //end switch 5127 5128 shape2 = new Shape2(Shape2.SHAPE_TYPE_MODIFIER_FILL); 5129 5130 shape2.setStroke(new BasicStroke(0, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 3)); 5131 5132 if (tg.get_TextColor() != null) { 5133 shape2.setFillColor(tg.get_TextColor()); 5134 } else if (tg.get_LineColor() != null) { 5135 shape2.setFillColor(tg.get_LineColor()); 5136 } 5137 if (tg.get_LineColor() != null) { 5138 shape2.setLineColor(tg.get_LineColor()); 5139 } 5140 //only GE uses the converter, generic uses the affine transform and draws at 0,0 5141 if (converter != null) { 5142 shape2.setGlyphPosition(glyphPosition); 5143 } else { 5144 shape2.setGlyphPosition(new Point2D.Double(0, 0)); 5145 } 5146 //shape2.setGlyphPosition(new Point(0,0)); 5147 //added two settings for use by GE 5148 if(s != null && !s.equals("")) { 5149 shape2.setModifierString(s); 5150 TextLayout tl = new TextLayout(s, font, g2d.getFontMetrics().getFontRenderContext()); 5151 shape2.setTextLayout(tl); 5152 shape2.setTextJustify(justify); 5153 } else if (image != null) { 5154 shape2.setModifierImage(image); 5155 } 5156 //shape2.setModifierStringPosition(glyphPosition);//M. Deutch 7-6-11 5157 shape2.setModifierAngle(theta * 180 / Math.PI); 5158 shape2.setModifierPosition(modifierPosition); 5159 shape2.setModifierAnchor(anchor); 5160 shape2.setModifierAnchorOffset(anchorOffset); 5161 5162 if (shape2 != null) { 5163 shapes.add(shape2); 5164 } 5165 5166 } //end for 5167 } //end try 5168 catch (Exception exc) { 5169 ErrorLogger.LogException(_className, "DisplayModifiers2", 5170 exc); 5171 } 5172 }//end function 5173 5174 /** 5175 * Builds a shape object to wrap text 5176 * 5177 * @param g2d the Graphic object for drawing 5178 * @param str text to wrap 5179 * @param font the draw font 5180 * @param tx the drawing transform, text rotation and translation 5181 * @return 5182 */ 5183 public static Shape getTextShape(Graphics2D g2d, 5184 String str, 5185 Font font, 5186 AffineTransform tx) { 5187 TextLayout tl = null; 5188 FontRenderContext frc = null; 5189 try { 5190 frc = g2d.getFontRenderContext(); 5191 tl = new TextLayout(str, font, frc); 5192 } catch (Exception exc) { 5193 ErrorLogger.LogException(_className, "getTextShape", 5194 new RendererException("Failed inside getTextShape", exc)); 5195 } 5196 return tl.getOutline(tx); 5197 } 5198 5199 /** 5200 * Creates text outline as a shape 5201 * 5202 * @param originalText the original text 5203 * @return text shape 5204 */ 5205 public static Shape2 createTextOutline(Shape2 originalText) { 5206 Shape2 siOutline = null; 5207 try { 5208 Shape outline = originalText.getShape(); 5209 5210 siOutline = new Shape2(Shape2.SHAPE_TYPE_MODIFIER_FILL); 5211 siOutline.setShape(outline); 5212 5213 if (originalText.getFillColor().getRed() == 255 5214 && originalText.getFillColor().getGreen() == 255 5215 && originalText.getFillColor().getBlue() == 255) { 5216 siOutline.setLineColor(Color.BLACK); 5217 } else { 5218 siOutline.setLineColor(Color.WHITE); 5219 } 5220 5221 int width = RendererSettings.getInstance().getTextOutlineWidth(); 5222 5223 siOutline.setStroke(new BasicStroke(width, BasicStroke.CAP_ROUND, 5224 BasicStroke.JOIN_ROUND, 3)); 5225 5226 } catch (Exception exc) { 5227 ErrorLogger.LogException(_className, "createTextOutline", 5228 new RendererException("Failed inside createTextOutline", exc)); 5229 } 5230 return siOutline; 5231 } 5232 5233 /** 5234 * Channels don't return points in tg.Pixels. For Channels modifiers we only 5235 * need to collect the points, don't need internal arrays, and can calculate 5236 * on which segments the modifiers lie. 5237 * 5238 * @param shape 5239 * @return 5240 */ 5241 private static ArrayList<POINT2> getShapePoints(Shape shape) { 5242 try { 5243 ArrayList<Point2D> ptsPoly = new ArrayList(); 5244 Point2D ptPoly = null; 5245 double[] coords = new double[6]; 5246 int zeros = 0; 5247 for (PathIterator i = shape.getPathIterator(null); !i.isDone(); i.next()) { 5248 int type = i.currentSegment(coords); 5249 if (type == 0 && zeros == 2) { 5250 break; 5251 } 5252 switch (type) { 5253 case PathIterator.SEG_MOVETO: 5254 ptPoly = new Point2D.Double(coords[0], coords[1]); 5255 ptsPoly.add(ptPoly); 5256 zeros++; 5257 break; 5258 case PathIterator.SEG_LINETO: 5259 ptPoly = new Point2D.Double(coords[0], coords[1]); 5260 ptsPoly.add(ptPoly); 5261 break; 5262 case PathIterator.SEG_QUADTO: //quadTo was never used 5263 break; 5264 case PathIterator.SEG_CUBICTO: //curveTo was used for some METOC's 5265 break; 5266 case PathIterator.SEG_CLOSE: //closePath was never used 5267 break; 5268 } 5269 } 5270 if (ptsPoly.size() > 0) { 5271 ArrayList<POINT2> pts = null; 5272 pts = new ArrayList(); 5273 for (int j = 0; j < ptsPoly.size(); j++) { 5274 Point2D pt2d = ptsPoly.get(j); 5275 POINT2 pt = new POINT2(pt2d.getX(), pt2d.getY()); 5276 pts.add(pt); 5277 } 5278 return pts; 5279 } 5280 } catch (Exception exc) { 5281 ErrorLogger.LogException(_className, "getshapePoints", 5282 new RendererException("Failed inside getShapePoints", exc)); 5283 } 5284 return null; 5285 } 5286 5287 private static Bitmap getImageModifier(TGLight tg) { 5288 String symbolID = tg.get_SymbolId(); 5289 ImageInfo symbol = null; 5290 Map<String,String> mods = new HashMap<>(); 5291 Map<String,String> sa = new HashMap<>(); 5292 sa.put(MilStdAttributes.PixelSize, String.valueOf(tg.get_IconSize())); 5293 int contaminationCode = EntityCode.getSymbolForContaminationArea(SymbolID.getEntityCode(symbolID)); 5294 int modifier1Code = SymbolID.getModifier1(symbolID); 5295 int lineType = GetLinetypeFromString(symbolID); 5296 if (contaminationCode > 0) { 5297 sa.put(MilStdAttributes.OutlineSymbol, "true"); 5298 sa.put(MilStdAttributes.FillColor, RendererUtilities.colorToHexString(tg.get_FillColor(), true)); 5299 sa.put(MilStdAttributes.LineColor, RendererUtilities.colorToHexString(tg.get_LineColor(), true)); 5300 String contaminationSP = SymbolID.setEntityCode(symbolID, contaminationCode); 5301 contaminationSP = SymbolID.setHQTFD(contaminationSP, 0); // Remove dummy modifier if necessary 5302 symbol = SinglePointRenderer.getInstance().RenderSP(contaminationSP, mods, sa); 5303 } else if (lineType == TacticalLines.DEPICT || lineType == TacticalLines.MINED || lineType == TacticalLines.FENCED || lineType == TacticalLines.MINE_LINE) { 5304 if (modifier1Code < 13 || modifier1Code > 50) { 5305 // Invalid mine type 5306 modifier1Code = 13;//unspecified mine (default value if not specified as per MilStd 2525) 5307 symbolID = SymbolID.setModifier1(symbolID, modifier1Code); 5308 } 5309 if (tg.get_KeepUnitRation()) { 5310 sa.put(MilStdAttributes.PixelSize, String.valueOf((int) (tg.get_IconSize() * 1.5))); 5311 } 5312 sa.put(MilStdAttributes.OutlineSymbol, "true"); 5313 symbol = SinglePointRenderer.getInstance().RenderModifier(symbolID, sa); 5314 } else if (lineType == TacticalLines.LAA && modifier1Code > 0) { 5315 sa.put(MilStdAttributes.OutlineSymbol, "true"); 5316 sa.put(MilStdAttributes.FillColor, RendererUtilities.colorToHexString(tg.get_FillColor(), true)); 5317 sa.put(MilStdAttributes.LineColor, RendererUtilities.colorToHexString(tg.get_LineColor(), true)); 5318 if (tg.get_KeepUnitRation()) { 5319 sa.put(MilStdAttributes.PixelSize, String.valueOf((int) (tg.get_IconSize() * 1.5))); 5320 } 5321 symbol = SinglePointRenderer.getInstance().RenderModifier(symbolID, sa); 5322 } 5323 else if (lineType == TacticalLines.DECISION_LINE) { 5324 5325 sa.put(MilStdAttributes.PixelSize, String.valueOf((int) (tg.get_IconSize() * 1.5))); 5326 sa.put(MilStdAttributes.KeepUnitRatio, String.valueOf((tg.get_KeepUnitRation()))); 5327 sa.put(MilStdAttributes.FillColor, RendererUtilities.colorToHexString(tg.get_FillColor(), true)); 5328 sa.put(MilStdAttributes.LineColor, RendererUtilities.colorToHexString(tg.get_LineColor(), true)); 5329 sa.put(MilStdAttributes.OutlineSymbol, "false"); 5330 mods.put(Modifiers.T_UNIQUE_DESIGNATION_1, (tg.get_Name())); 5331 5332 String decisionPoint = SymbolID.setEntityCode(symbolID, EntityCode.EntityCode_Decision_Point); 5333 symbol = SinglePointRenderer.getInstance().RenderSP(decisionPoint, mods, sa); 5334 } 5335 else if (lineType == TacticalLines.ANCHORAGE_LINE || lineType == TacticalLines.ANCHORAGE_AREA) { 5336 sa.put(MilStdAttributes.OutlineSymbol, "false"); 5337 String anchorPoint = SymbolID.setEntityCode(symbolID, EntityCode.EntityCode_AnchoragePoint); 5338 symbol = SinglePointRenderer.getInstance().RenderSP(anchorPoint, mods, sa); 5339 } 5340 5341 if (symbol != null) 5342 return symbol.getImage(); 5343 else 5344 return null; 5345 } 5346 5347 private static String removeDecimal(double doubleVal) { 5348 return String.valueOf(Math.round(doubleVal)); 5349 } 5350 5351 private static String removeDecimal(String strDoubleVal) { 5352 if (strDoubleVal.indexOf(" ") > 0) // String contains unit 5353 return removeDecimal(Double.parseDouble(strDoubleVal.substring(0, strDoubleVal.indexOf(" ")))) + strDoubleVal.substring(strDoubleVal.indexOf(" ")); 5354 else 5355 return removeDecimal(Double.parseDouble(strDoubleVal)); 5356 } 5357}