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