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.TacticalLines;
008import armyc2.c2sd.JavaLineArray.lineutility;
009import armyc2.c2sd.JavaLineArray.POINT2;
010import armyc2.c2sd.JavaLineArray.ref;
011import java.util.ArrayList;
012import java.util.HashMap;
013import java.util.Map;
014import armyc2.c2sd.JavaLineArray.Shape2;
015import java.io.*;
016
017import armyc2.c2sd.renderer.utilities.IPointConversion;
018import armyc2.c2sd.renderer.utilities.SymbolUtilities;
019import armyc2.c2sd.renderer.utilities.ErrorLogger;
020import armyc2.c2sd.renderer.utilities.RendererException;
021import armyc2.c2sd.renderer.utilities.RendererSettings;
022import armyc2.c2sd.renderer.utilities.Color;
023import armyc2.c2sd.graphics2d.*;
024/**
025 * A general utility class for the tactical renderer
026 * @author Michael Deutch
027 */
028public final class clsUtility {
029    private static Map<String,Object> linetypes=null;
030    private static Map<String,Object> metocs=null;
031    private static final String _className = "clsUtility";
032    protected static Point2D POINT2ToPoint2D(POINT2 pt2) {
033        if (pt2 == null) {
034            return null;
035        }
036
037        double x = pt2.x;
038        double y = pt2.y;
039        Point2D pt = new Point2D.Double(x, y);
040        return pt;
041    }
042    /**
043     * returns true if the line segments are all outside the bounds
044     * @param tg the tactical graphic
045     * @param clipBounds the pixels based clip bounds
046     * @return 
047     */
048    public static boolean linesOutsideClipBounds(TGLight tg,
049            Rectangle2D clipBounds)
050    {
051        try
052        {
053            boolean isAutoshape=isAutoshape(tg);
054            if(isAutoshape)
055                return false;
056
057            double xmin=clipBounds.getMinX();
058            double xmax=clipBounds.getMaxX();
059            double ymin=clipBounds.getMinY();
060            double ymax=clipBounds.getMaxY();
061            int j=0;
062            POINT2 pt0=null,pt1=null;
063            Line2D boundsEdge=null,ptsLine=null;
064            int n=tg.Pixels.size();
065            //for(j=0;j<tg.Pixels.size()-1;j++)
066            for(j=0;j<n-1;j++)
067            {
068                pt0=tg.Pixels.get(j);
069                pt1=tg.Pixels.get(j+1);
070                
071                //if either point is inside the bounds return false
072                if(clipBounds.contains(pt0.x, pt0.y))
073                    return false;
074                if(clipBounds.contains(pt1.x, pt1.y))
075                    return false;
076                
077                ptsLine=new Line2D.Double(pt0.x,pt0.y,pt1.x,pt1.y);
078                
079                //if the pt0-pt1 line intersects any clip bounds edge then return false
080                boundsEdge=new Line2D.Double(xmin,ymin,xmax,ymin);
081                if(ptsLine.intersectsLine(boundsEdge))
082                    return false;                
083                
084                boundsEdge=new Line2D.Double(xmax,ymin,xmax,ymax);
085                if(ptsLine.intersectsLine(boundsEdge))
086                    return false;                
087                
088                boundsEdge=new Line2D.Double(xmax,ymax,xmin,ymax);
089                if(ptsLine.intersectsLine(boundsEdge))
090                    return false;                
091                
092                boundsEdge=new Line2D.Double(xmin,ymax,xmin,ymin);
093                if(ptsLine.intersectsLine(boundsEdge))
094                    return false;                
095            }
096        }
097        catch (Exception exc) 
098        {
099            ErrorLogger.LogException(_className ,"linesOutsideClipBounds",
100                    new RendererException("Failed inside linesOutsideClipBounds", exc));
101        }    
102        return true;
103    }
104    /**
105     * Returns the minimum client points needed for the symbol
106     * @param lineType line type
107     * @return minimum number of clients required to render the line
108     */
109    public static int GetMinPoints(int lineType) {
110        int result = -1;
111        switch (lineType) {
112            case TacticalLines.RECTANGULAR:
113            case TacticalLines.PBS_RECTANGLE:
114            case TacticalLines.PBS_SQUARE:
115                result = 1; //was 3
116                break;
117            case TacticalLines.BBS_POINT:
118            case TacticalLines.CIRCULAR:
119            case TacticalLines.FSA_CIRCULAR:
120            case TacticalLines.FFA_CIRCULAR:
121            case TacticalLines.NFA_CIRCULAR:
122            case TacticalLines.RFA_CIRCULAR:
123            case TacticalLines.ACA_CIRCULAR:
124            case TacticalLines.PAA_CIRCULAR:
125            case TacticalLines.ATI_CIRCULAR:
126            case TacticalLines.CFFZ_CIRCULAR:
127            case TacticalLines.SENSOR_CIRCULAR:
128            case TacticalLines.CENSOR_CIRCULAR:
129            case TacticalLines.DA_CIRCULAR:
130            case TacticalLines.CFZ_CIRCULAR:
131            case TacticalLines.ZOR_CIRCULAR:
132            case TacticalLines.TBA_CIRCULAR:
133            case TacticalLines.TVAR_CIRCULAR:
134            case TacticalLines.KILLBOXBLUE_CIRCULAR:
135            case TacticalLines.KILLBOXPURPLE_CIRCULAR:
136            case TacticalLines.LAUNCH_AREA:
137                result = 1; //was 2
138                break;
139            case TacticalLines.RANGE_FAN:
140            case TacticalLines.RANGE_FAN_SECTOR:
141                result = 1;
142                break;
143            case TacticalLines.PAA_RECTANGULAR_REVC:
144            case TacticalLines.FSA_RECTANGULAR:
145            case TacticalLines.FFA_RECTANGULAR:
146            case TacticalLines.RFA_RECTANGULAR:
147            case TacticalLines.NFA_RECTANGULAR:
148            case TacticalLines.ACA_RECTANGULAR:
149            case TacticalLines.ATI_RECTANGULAR:
150            case TacticalLines.CFFZ_RECTANGULAR:
151            case TacticalLines.SENSOR_RECTANGULAR:
152            case TacticalLines.CENSOR_RECTANGULAR:
153            case TacticalLines.DA_RECTANGULAR:
154            case TacticalLines.CFZ_RECTANGULAR:
155            case TacticalLines.ZOR_RECTANGULAR:
156            case TacticalLines.TBA_RECTANGULAR:
157            case TacticalLines.TVAR_RECTANGULAR:
158            case TacticalLines.KILLBOXBLUE_RECTANGULAR:
159            case TacticalLines.KILLBOXPURPLE_RECTANGULAR:
160                result = 2; //was 3
161                break;
162            case TacticalLines.SPTBYFIRE:
163            case TacticalLines.RIP:
164            case TacticalLines.GAP:
165            case TacticalLines.ASLTXING:
166            case TacticalLines.BRIDGE:
167            case TacticalLines.MSDZ:
168            case TacticalLines.SCREEN_REVC:
169            case TacticalLines.COVER_REVC:
170            case TacticalLines.GUARD_REVC:
171            case TacticalLines.SEIZE_REVC:
172                result = 4;
173                break;
174            case TacticalLines.BYPASS:
175            case TacticalLines.BLOCK:
176            case TacticalLines.BREACH:
177            case TacticalLines.CANALIZE:
178            case TacticalLines.CLEAR:
179            case TacticalLines.CONTAIN:
180            case TacticalLines.DELAY:
181            case TacticalLines.DISRUPT:
182            case TacticalLines.PENETRATE:
183            case TacticalLines.RETIRE:
184            case TacticalLines.SCREEN:
185            case TacticalLines.COVER:
186            case TacticalLines.GUARD:
187            case TacticalLines.SEIZE:
188            case TacticalLines.WITHDRAW:
189            case TacticalLines.WDRAWUP:
190            //non task autoshapes
191            case TacticalLines.SARA:
192            case TacticalLines.DECEIVE:
193            case TacticalLines.DUMMY:
194            case TacticalLines.PDF:
195            case TacticalLines.IL:
196            case TacticalLines.ATKBYFIRE:
197            case TacticalLines.AMBUSH:
198            case TacticalLines.HOLD:
199            case TacticalLines.RELEASE:
200            case TacticalLines.BRDGHD:
201            case TacticalLines.MNFLDBLK:
202            case TacticalLines.MNFLDDIS:
203            case TacticalLines.TURN:
204            case TacticalLines.PLANNED:
205            case TacticalLines.ESR1:
206            case TacticalLines.ESR2:
207            case TacticalLines.ROADBLK:
208            case TacticalLines.TRIP:
209            case TacticalLines.EASY:
210            case TacticalLines.BYDIF:
211            case TacticalLines.BYIMP:
212            case TacticalLines.FORDSITE:
213            case TacticalLines.FORDIF:
214            //METOCs
215            case TacticalLines.IFR:
216            case TacticalLines.MVFR:
217            case TacticalLines.TURBULENCE:
218            case TacticalLines.ICING:
219            case TacticalLines.NON_CONVECTIVE:
220            case TacticalLines.CONVECTIVE:
221            case TacticalLines.FROZEN:
222            case TacticalLines.THUNDERSTORMS:
223            case TacticalLines.FOG:
224            case TacticalLines.SAND:
225            case TacticalLines.FREEFORM:
226            case TacticalLines.DEPTH_AREA:
227            case TacticalLines.ISLAND:
228            case TacticalLines.BEACH:
229            case TacticalLines.WATER:
230            case TacticalLines.WEIRS:
231            case TacticalLines.SWEPT_AREA:
232            case TacticalLines.OIL_RIG_FIELD:
233            case TacticalLines.FOUL_GROUND:
234            case TacticalLines.KELP:
235            case TacticalLines.BEACH_SLOPE_MODERATE:
236            case TacticalLines.BEACH_SLOPE_STEEP:
237            case TacticalLines.ANCHORAGE_AREA:
238            case TacticalLines.TRAINING_AREA:
239            case TacticalLines.FORESHORE_AREA:
240            case TacticalLines.DRYDOCK:
241            case TacticalLines.LOADING_FACILITY_AREA:
242            case TacticalLines.PERCHES:
243            case TacticalLines.UNDERWATER_HAZARD:
244            case TacticalLines.DISCOLORED_WATER:
245            case TacticalLines.BEACH_SLOPE_FLAT:
246            case TacticalLines.BEACH_SLOPE_GENTLE:
247            case TacticalLines.MARITIME_AREA:
248            case TacticalLines.OPERATOR_DEFINED:
249            case TacticalLines.SUBMERGED_CRIB:
250            case TacticalLines.VDR_LEVEL_12:
251            case TacticalLines.VDR_LEVEL_23:
252            case TacticalLines.VDR_LEVEL_34:
253            case TacticalLines.VDR_LEVEL_45:
254            case TacticalLines.VDR_LEVEL_56:
255            case TacticalLines.VDR_LEVEL_67:
256            case TacticalLines.VDR_LEVEL_78:
257            case TacticalLines.VDR_LEVEL_89:
258            case TacticalLines.VDR_LEVEL_910:
259            case TacticalLines.SOLID_ROCK:
260            case TacticalLines.CLAY:
261            case TacticalLines.VERY_COARSE_SAND:
262            case TacticalLines.COARSE_SAND:
263            case TacticalLines.MEDIUM_SAND:
264            case TacticalLines.FINE_SAND:
265            case TacticalLines.VERY_FINE_SAND:
266            case TacticalLines.VERY_FINE_SILT:
267            case TacticalLines.FINE_SILT:
268            case TacticalLines.MEDIUM_SILT:
269            case TacticalLines.COARSE_SILT:
270            case TacticalLines.BOULDERS:
271            case TacticalLines.OYSTER_SHELLS:
272            case TacticalLines.PEBBLES:
273            case TacticalLines.SAND_AND_SHELLS:
274            case TacticalLines.BOTTOM_SEDIMENTS_LAND:
275            case TacticalLines.BOTTOM_SEDIMENTS_NO_DATA:
276            case TacticalLines.BOTTOM_ROUGHNESS_SMOOTH:
277            case TacticalLines.BOTTOM_ROUGHNESS_MODERATE:
278            case TacticalLines.BOTTOM_ROUGHNESS_ROUGH:
279            case TacticalLines.CLUTTER_LOW:
280            case TacticalLines.CLUTTER_MEDIUM:
281            case TacticalLines.CLUTTER_HIGH:
282            case TacticalLines.IMPACT_BURIAL_0:
283            case TacticalLines.IMPACT_BURIAL_10:
284            case TacticalLines.IMPACT_BURIAL_20:
285            case TacticalLines.IMPACT_BURIAL_75:
286            case TacticalLines.IMPACT_BURIAL_100:
287            case TacticalLines.BOTTOM_CATEGORY_A:
288            case TacticalLines.BOTTOM_CATEGORY_B:
289            case TacticalLines.BOTTOM_CATEGORY_C:
290            case TacticalLines.BOTTOM_TYPE_A1:
291            case TacticalLines.BOTTOM_TYPE_A2:
292            case TacticalLines.BOTTOM_TYPE_A3:
293            case TacticalLines.BOTTOM_TYPE_B1:
294            case TacticalLines.BOTTOM_TYPE_B2:
295            case TacticalLines.BOTTOM_TYPE_B3:
296            case TacticalLines.BOTTOM_TYPE_C1:
297            case TacticalLines.BOTTOM_TYPE_C2:
298            case TacticalLines.BOTTOM_TYPE_C3:
299                result = 3;
300                break;
301            case TacticalLines.MRR:
302            case TacticalLines.UAV:
303            case TacticalLines.LLTR:
304            case TacticalLines.FEBA:
305            case TacticalLines.DIRATKAIR:
306            case TacticalLines.ABATIS:
307            case TacticalLines.CLUSTER:
308            case TacticalLines.MNFLDFIX:
309            case TacticalLines.FERRY:
310            case TacticalLines.MFLANE:
311            case TacticalLines.RAFT:
312            case TacticalLines.FOXHOLE:
313            case TacticalLines.LINTGT:
314            case TacticalLines.LINTGTS:
315            case TacticalLines.FPF:
316            case TacticalLines.CONVOY:
317            case TacticalLines.HCONVOY:
318                result = 2;
319                break;
320            default:
321                result = 2;
322                break;
323        }
324        if (isClosedPolygon(lineType)) {
325            result = 3;
326        }
327        //add code for change 1 areas
328        return result;
329    }
330    /**
331     * 
332     * @param linetype the line type
333     * @return true if the line is a basic shape
334     */
335    public static boolean isBasicShape(int linetype)
336    {
337        switch(linetype)
338        {
339            case TacticalLines.BS_AREA:
340            case TacticalLines.BS_LINE:
341            case TacticalLines.BS_CROSS:
342            case TacticalLines.BS_ELLIPSE:
343            case TacticalLines.PBS_ELLIPSE:
344            case TacticalLines.PBS_CIRCLE:
345            case TacticalLines.PBS_SQUARE:
346            case TacticalLines.PBS_RECTANGLE:
347            case TacticalLines.BS_RECTANGLE:
348            case TacticalLines.BBS_AREA:
349            case TacticalLines.BBS_LINE:
350            case TacticalLines.BBS_POINT:
351            case TacticalLines.BBS_RECTANGLE:
352            case TacticalLines.BS_BBOX:
353                return true;
354            default:
355                return false;
356        }
357    }
358    /**
359     * @param linetype line type
360     * @return true if the line is a closed area
361     */
362    public static boolean isClosedPolygon(int linetype) {
363        boolean result = false;
364        switch (linetype) {    
365            case TacticalLines.BBS_AREA:
366            case TacticalLines.BS_BBOX:
367            case TacticalLines.AT:
368            case TacticalLines.DEPICT:
369            case TacticalLines.DZ:
370            case TacticalLines.MINED:
371            case TacticalLines.UXO:
372            case TacticalLines.ROZ:
373            case TacticalLines.FAADZ:
374            case TacticalLines.HIDACZ:
375            case TacticalLines.MEZ:
376            case TacticalLines.LOMEZ:
377            case TacticalLines.HIMEZ:
378            case TacticalLines.WFZ:
379            case TacticalLines.DUMMY:
380            case TacticalLines.PNO:
381            case TacticalLines.BATTLE:
382            case TacticalLines.EA:
383            case TacticalLines.EZ:
384            case TacticalLines.LZ:
385            case TacticalLines.PZ:
386            case TacticalLines.GENERAL:
387            case TacticalLines.BS_AREA:
388            case TacticalLines.EA1:
389            case TacticalLines.ASSAULT:
390            case TacticalLines.ATKPOS:
391            case TacticalLines.OBJ:
392            case TacticalLines.AO:
393            case TacticalLines.AIRHEAD:
394            case TacticalLines.NAI:
395            case TacticalLines.TAI:
396            case TacticalLines.OBSFAREA:
397            case TacticalLines.OBSAREA:
398            case TacticalLines.ZONE:
399            case TacticalLines.BELT:
400            case TacticalLines.STRONG:
401            case TacticalLines.DRCL:
402            case TacticalLines.FSA:
403            case TacticalLines.ACA:
404            case TacticalLines.ASSY:
405            case TacticalLines.BSA:
406            case TacticalLines.NFA:
407            case TacticalLines.RFA:
408            case TacticalLines.FARP:
409            case TacticalLines.AIRFIELD:
410            case TacticalLines.LAA:
411            case TacticalLines.DMA:
412            case TacticalLines.DMAF:
413            case TacticalLines.BOMB:
414            case TacticalLines.FFA:
415            case TacticalLines.SMOKE:
416            case TacticalLines.PAA:
417            case TacticalLines.ENCIRCLE:
418            case TacticalLines.DHA:
419            case TacticalLines.EPW:
420            case TacticalLines.RHA:
421            case TacticalLines.DSA:
422            case TacticalLines.RSA:
423            case TacticalLines.FORT:
424            case TacticalLines.PEN:
425            case TacticalLines.BIO:
426            case TacticalLines.RAD:
427            case TacticalLines.CHEM:
428            case TacticalLines.SERIES:
429            case TacticalLines.ATI:
430            case TacticalLines.TBA:
431            case TacticalLines.TVAR:
432            case TacticalLines.CFFZ:
433            case TacticalLines.CENSOR:
434            case TacticalLines.SENSOR:
435            case TacticalLines.ZOR:
436            case TacticalLines.DA:
437            case TacticalLines.CFZ:
438            case TacticalLines.KILLBOXBLUE:
439            case TacticalLines.KILLBOXPURPLE:
440            //METOCs
441            case TacticalLines.IFR:
442            case TacticalLines.MVFR:
443            case TacticalLines.TURBULENCE:
444            case TacticalLines.ICING:
445            case TacticalLines.NON_CONVECTIVE:
446            case TacticalLines.CONVECTIVE:
447            case TacticalLines.FROZEN:
448            case TacticalLines.THUNDERSTORMS:
449            case TacticalLines.FOG:
450            case TacticalLines.SAND:
451            case TacticalLines.FREEFORM:
452            case TacticalLines.DEPTH_AREA:
453            case TacticalLines.ISLAND:
454            case TacticalLines.BEACH:
455            case TacticalLines.WATER:
456            case TacticalLines.WEIRS:
457            case TacticalLines.SWEPT_AREA:
458            case TacticalLines.OIL_RIG_FIELD:
459            case TacticalLines.FOUL_GROUND:
460            case TacticalLines.KELP:
461            case TacticalLines.BEACH_SLOPE_MODERATE:
462            case TacticalLines.BEACH_SLOPE_STEEP:
463            case TacticalLines.ANCHORAGE_AREA:
464            case TacticalLines.TRAINING_AREA:
465            case TacticalLines.FORESHORE_AREA:
466            case TacticalLines.DRYDOCK:
467            case TacticalLines.LOADING_FACILITY_AREA:
468            case TacticalLines.PERCHES:
469            case TacticalLines.UNDERWATER_HAZARD:
470            case TacticalLines.DISCOLORED_WATER:
471            case TacticalLines.BEACH_SLOPE_FLAT:
472            case TacticalLines.BEACH_SLOPE_GENTLE:
473            case TacticalLines.MARITIME_AREA:
474            case TacticalLines.OPERATOR_DEFINED:
475            case TacticalLines.SUBMERGED_CRIB:
476            case TacticalLines.VDR_LEVEL_12:
477            case TacticalLines.VDR_LEVEL_23:
478            case TacticalLines.VDR_LEVEL_34:
479            case TacticalLines.VDR_LEVEL_45:
480            case TacticalLines.VDR_LEVEL_56:
481            case TacticalLines.VDR_LEVEL_67:
482            case TacticalLines.VDR_LEVEL_78:
483            case TacticalLines.VDR_LEVEL_89:
484            case TacticalLines.VDR_LEVEL_910:
485            case TacticalLines.SOLID_ROCK:
486            case TacticalLines.CLAY:
487            case TacticalLines.VERY_COARSE_SAND:
488            case TacticalLines.COARSE_SAND:
489            case TacticalLines.MEDIUM_SAND:
490            case TacticalLines.FINE_SAND:
491            case TacticalLines.VERY_FINE_SAND:
492            case TacticalLines.VERY_FINE_SILT:
493            case TacticalLines.FINE_SILT:
494            case TacticalLines.MEDIUM_SILT:
495            case TacticalLines.COARSE_SILT:
496            case TacticalLines.BOULDERS:
497            case TacticalLines.OYSTER_SHELLS:
498            case TacticalLines.PEBBLES:
499            case TacticalLines.SAND_AND_SHELLS:
500            case TacticalLines.BOTTOM_SEDIMENTS_LAND:
501            case TacticalLines.BOTTOM_SEDIMENTS_NO_DATA:
502            case TacticalLines.BOTTOM_ROUGHNESS_SMOOTH:
503            case TacticalLines.BOTTOM_ROUGHNESS_MODERATE:
504            case TacticalLines.BOTTOM_ROUGHNESS_ROUGH:
505            case TacticalLines.CLUTTER_LOW:
506            case TacticalLines.CLUTTER_MEDIUM:
507            case TacticalLines.CLUTTER_HIGH:
508            case TacticalLines.IMPACT_BURIAL_0:
509            case TacticalLines.IMPACT_BURIAL_10:
510            case TacticalLines.IMPACT_BURIAL_20:
511            case TacticalLines.IMPACT_BURIAL_75:
512            case TacticalLines.IMPACT_BURIAL_100:
513            case TacticalLines.BOTTOM_CATEGORY_A:
514            case TacticalLines.BOTTOM_CATEGORY_B:
515            case TacticalLines.BOTTOM_CATEGORY_C:
516            case TacticalLines.BOTTOM_TYPE_A1:
517            case TacticalLines.BOTTOM_TYPE_A2:
518            case TacticalLines.BOTTOM_TYPE_A3:
519            case TacticalLines.BOTTOM_TYPE_B1:
520            case TacticalLines.BOTTOM_TYPE_B2:
521            case TacticalLines.BOTTOM_TYPE_B3:
522            case TacticalLines.BOTTOM_TYPE_C1:
523            case TacticalLines.BOTTOM_TYPE_C2:
524            case TacticalLines.BOTTOM_TYPE_C3:
525            case TacticalLines.TGMF:
526                result = true;
527            default:
528                break;
529        }
530        return result;
531    }
532
533    /**
534     * Closes the polygon for areas
535     * @param Pixels the client points
536     */
537    public static void ClosePolygon(ArrayList<POINT2> Pixels) {
538        try {
539            POINT2 pt0 = Pixels.get(0);
540            POINT2 pt1 = Pixels.get(Pixels.size() - 1);
541            if (pt0.x != pt1.x || pt0.y != pt1.y) {
542                Pixels.add(new POINT2(pt0.x, pt0.y));
543            }
544        } catch (Exception exc) {
545               ErrorLogger.LogException(_className ,"ClosePolygon",
546                    new RendererException("Failed inside ClosePolygon", exc));
547        }
548    }
549    /**
550     * for change 1 symbol the W/w1 modifiers run too close to the symbol outline
551     * so it shifts the line along the line away from the edge
552     * @param pt0
553     * @param pt1
554     */
555    protected static void shiftModifiersLeft(POINT2 p1, POINT2 p2, double shift)
556    {
557        try
558        {
559            POINT2 pt1=new POINT2(p1);
560            POINT2 pt2=new POINT2(p2);
561            double dist=lineutility.CalcDistanceDouble(pt1, pt2);
562            if(pt1.x<pt2.x || (pt1.x==pt2.x && pt1.y<pt2.y))
563            {
564                pt1=lineutility.ExtendAlongLineDouble(pt2, pt1, dist+shift);
565                pt2=lineutility.ExtendAlongLineDouble(pt1, pt2, dist-shift);
566            }
567            else
568            {
569                pt1=lineutility.ExtendAlongLineDouble(pt2, pt1, dist-shift);
570                pt2=lineutility.ExtendAlongLineDouble(pt1, pt2, dist+shift);
571            }
572            p1.x=pt1.x;
573            p1.y=pt1.y;
574            p2.x=pt2.x;
575            p2.y=pt2.y;
576        }
577        catch (Exception exc) {
578               ErrorLogger.LogException(_className ,"shiftModifiersLeft",
579                    new RendererException("Failed inside shiftModifiersLeft", exc));
580        }
581    }
582    /**
583     * Overrides shape properties for symbols based on Mil-Std-2525
584     * @param tg
585     * @param shape
586     */
587    protected static void ResolveModifierShape(TGLight tg, Shape2 shape) {
588        try {
589            //shape style was set by CELineArray and takes precedence
590            //whenever it is set
591            int shapeStyle = shape.get_Style();
592            int lineStyle = tg.get_LineStyle();
593            int lineType = tg.get_LineType();
594            boolean hasFill=LinesWithFill(lineType);
595            int bolMETOC=clsMETOC.IsWeather(tg.get_SymbolId());
596            if(bolMETOC>0)
597                return;
598            int fillStyle=0;
599            //for some of these the style must be dashed
600            switch (tg.get_LineType()) {
601                case TacticalLines.FEBA:
602                    shape.setFillColor(null);
603                    shape.set_Style(tg.get_LineStyle());
604                    shape.setLineColor(tg.get_LineColor());                    
605                    break;
606                case TacticalLines.NFA:
607                case TacticalLines.NFA_CIRCULAR:
608                case TacticalLines.NFA_RECTANGULAR:
609                case TacticalLines.KILLBOXBLUE:
610                case TacticalLines.KILLBOXPURPLE:
611                case TacticalLines.KILLBOXBLUE_RECTANGULAR:
612                case TacticalLines.KILLBOXPURPLE_RECTANGULAR:
613                case TacticalLines.KILLBOXBLUE_CIRCULAR:
614                case TacticalLines.KILLBOXPURPLE_CIRCULAR:
615                case TacticalLines.BIO:
616                case TacticalLines.CHEM:
617                case TacticalLines.RAD:
618                case TacticalLines.WFZ:
619                //case TacticalLines.OBSAREA:
620                    fillStyle=3;
621                    if(tg.get_UseHatchFill())
622                        fillStyle=0;
623                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
624                        shape.set_Style(tg.get_LineStyle());
625                        shape.setLineColor(tg.get_LineColor());
626                        shape.set_Fillstyle(fillStyle /*GraphicProperties.FILL_TYPE_RIGHT_SLANTS*/);//was 3
627                        shape.setFillColor(tg.get_FillColor());
628                    }
629                    break;
630                case TacticalLines.OBSAREA:
631                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
632                        shape.set_Style(tg.get_LineStyle());
633                        shape.setLineColor(tg.get_LineColor());
634                        shape.set_Fillstyle(0 /*GraphicProperties.FILL_TYPE_RIGHT_SLANTS*/);
635                        shape.setFillColor(tg.get_FillColor());
636                    }
637                    break;
638                case TacticalLines.LAA:
639                    fillStyle=2;
640                    if(tg.get_UseHatchFill())
641                        fillStyle=0;
642                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
643                        shape.set_Style(tg.get_LineStyle());
644                        shape.setLineColor(tg.get_LineColor());
645                        shape.set_Fillstyle(fillStyle /*GraphicProperties.FILL_TYPE_LEFT_SLANTS*/);//was 2
646                        shape.setFillColor(tg.get_FillColor());
647                    }
648                    break;
649                case TacticalLines.OVERHEAD_WIRE_LS:
650                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) {
651                        shape.set_Fillstyle(1 /*GraphicProperties.FILL_TYPE_SOLID*/);
652                        shape.setFillColor(tg.get_LineColor());
653                    }
654                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
655                        shape.set_Style(1);
656                        shape.setLineColor(tg.get_LineColor());
657                    }
658                    break;
659                case TacticalLines.DIRATKAIR:
660                case TacticalLines.ATDITCHC:
661                case TacticalLines.ATDITCHM:
662                case TacticalLines.SARA:
663                case TacticalLines.FOLSP:
664                case TacticalLines.FERRY:
665                case TacticalLines.MNFLDFIX:
666                case TacticalLines.TURN:
667                case TacticalLines.MNFLDDIS:
668                case TacticalLines.EASY:
669                case TacticalLines.BYDIF:
670                case TacticalLines.BYIMP:
671                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) {
672                        shape.set_Fillstyle(1 /*GraphicProperties.FILL_TYPE_SOLID*/);
673                        shape.setFillColor(tg.get_LineColor());
674                    }
675                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
676                        shape.set_Style(tg.get_LineStyle());
677                        shape.setLineColor(tg.get_LineColor());
678                    }
679                    break;
680                case TacticalLines.DECEIVE: //any shape for these symbols is dashed
681                case TacticalLines.CLUSTER:
682                case TacticalLines.CATK:
683                case TacticalLines.CATKBYFIRE:
684                case TacticalLines.PLD:
685                case TacticalLines.PLANNED:
686                case TacticalLines.CFL:
687                case TacticalLines.FORDSITE:
688                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
689                        shape.set_Style(1 /*GraphicProperties.LINE_TYPE_DASHED*/);
690                        shape.setLineColor(tg.get_LineColor());
691                    }
692                    break;
693                case TacticalLines.PNO: //always dashed
694                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
695                        shape.set_Style(1 /*GraphicProperties.LINE_TYPE_DASHED*/);
696                        shape.setLineColor(tg.get_LineColor());
697                        shape.setFillColor(tg.get_FillColor());
698                        shape.set_Fillstyle(tg.get_FillStyle());
699                    }
700                    break;
701                case TacticalLines.DMA: //these symbols are partially dashed
702                case TacticalLines.DMAF:
703                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
704                        shape.setLineColor(tg.get_LineColor());
705                        if (shapeStyle != lineStyle) {
706                            if (shapeStyle != 1 /*GraphicProperties.LINE_TYPE_DASHED*/) {
707                                shape.set_Style(lineStyle);
708                            }
709                        }
710                    }
711                    break;
712                case TacticalLines.DUMMY:
713                case TacticalLines.DIRATKFNT:
714                case TacticalLines.FOLLA:
715                case TacticalLines.ESR1:
716                case TacticalLines.FORDIF:
717                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
718                        shape.setLineColor(tg.get_LineColor());
719                        if (shapeStyle != lineStyle) {
720                            if (shapeStyle != 1 /*GraphicProperties.LINE_TYPE_DASHED*/) {
721                                shape.set_Style(lineStyle);
722                            }
723                        }
724                    }
725                    break;
726                case TacticalLines.AAFNT:
727                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
728                        shape.setLineColor(tg.get_LineColor());
729                        if (shapeStyle != lineStyle) {
730                            if (shapeStyle != 2 /*GraphicProperties.LINE_TYPE_DOTTED*/) {
731                                shape.set_Style(lineStyle);
732                            }
733                        }
734                    }
735                    break;
736                default:
737                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) {
738                        shape.set_Fillstyle(tg.get_FillStyle());
739                        shape.setFillColor(tg.get_FillColor());
740                    }
741                    if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) {
742                        if (lineType != TacticalLines.LC)//shape linecolor set by Channels class for LC
743                        {
744                            shape.setLineColor(tg.get_LineColor());
745                        }
746                        shape.set_Style(lineStyle);
747                        if (hasFill || clsUtility.isClosedPolygon(lineType) || clsUtility.IsChange1Area(lineType, null))
748                        {
749                            switch(lineType)
750                            {
751                                case TacticalLines.RANGE_FAN:
752                                case TacticalLines.RANGE_FAN_SECTOR:
753                                case TacticalLines.BBS_AREA:
754                                case TacticalLines.BBS_RECTANGLE:
755                                    shape.setFillColor(null);
756                                    break;
757                                default:
758                                    shape.set_Fillstyle(tg.get_FillStyle());
759                                    shape.setFillColor(tg.get_FillColor());
760                                    break;
761                            }
762                        }
763                        switch(lineType)
764                        {
765                            case TacticalLines.BS_ELLIPSE:
766                            //case TacticalLines.PBS_ELLIPSE:
767                            //case TacticalLines.PBS_CIRCLE:
768                            case TacticalLines.BS_RECTANGLE:
769                            //case TacticalLines.BBS_RECTANGLE:
770                                shape.set_Fillstyle(tg.get_FillStyle());
771                                shape.setFillColor(tg.get_FillColor());
772                                break;
773                            case TacticalLines.BBS_RECTANGLE:
774                            case TacticalLines.PBS_RECTANGLE:
775                            case TacticalLines.PBS_SQUARE:
776                            case TacticalLines.PBS_ELLIPSE:
777                            case TacticalLines.PBS_CIRCLE:
778                                shape.setFillColor(null);
779                                break;
780                            default:
781                                break;
782                        }
783                    }
784                    break;
785            }
786
787        } catch (Exception exc) {
788               ErrorLogger.LogException(_className ,"ResolveModifierShape",
789                    new RendererException("Failed inside ResolveModifierShape", exc));
790        }
791    }
792    public static Color GetOpaqueColor(Color color)
793    {
794        int r=color.getRed();
795        int g=color.getGreen();
796        int b=color.getBlue();
797        return new Color(r,g,b);
798    }
799    /**
800     * These lines allow fill
801     * @param linetype
802     * @return
803     */
804    public static boolean LinesWithFill(int linetype)
805    {
806        boolean result=false;
807        try
808        {
809            switch(linetype)
810            {
811                case TacticalLines.BS_LINE:
812                case TacticalLines.PAA_RECTANGULAR:
813                case TacticalLines.CFL:
814                case TacticalLines.DIRATKFNT:
815                case TacticalLines.DIRATKAIR:
816                case TacticalLines.BOUNDARY:
817                case TacticalLines.ISOLATE:
818                case TacticalLines.CORDONKNOCK:
819                case TacticalLines.CORDONSEARCH:
820                case TacticalLines.OCCUPY:
821                case TacticalLines.RETAIN:
822                case TacticalLines.SECURE:
823                case TacticalLines.FLOT:
824                case TacticalLines.LC:
825                case TacticalLines.PL:
826                case TacticalLines.LL:
827//                case TacticalLines.AC:
828//                case TacticalLines.SAAFR:
829                case TacticalLines.FEBA:
830                case TacticalLines.DIRATKGND:
831                case TacticalLines.DIRATKSPT:
832                case TacticalLines.FCL:
833                case TacticalLines.LOA:
834                case TacticalLines.LOD:
835                case TacticalLines.LDLC:
836                case TacticalLines.RELEASE:
837                case TacticalLines.LINE:
838                case TacticalLines.ABATIS:
839                case TacticalLines.ATDITCH:
840                case TacticalLines.ATWALL:
841                case TacticalLines.SFENCE:
842                case TacticalLines.DFENCE:
843                case TacticalLines.UNSP:
844                case TacticalLines.PLD:
845                case TacticalLines.DOUBLEA:
846                case TacticalLines.LWFENCE:
847                case TacticalLines.HWFENCE:
848                case TacticalLines.SINGLEC:
849                case TacticalLines.DOUBLEC:
850                case TacticalLines.TRIPLE:
851                case TacticalLines.FORTL:
852                case TacticalLines.LINTGT:
853                case TacticalLines.LINTGTS:
854                case TacticalLines.FSCL:
855                case TacticalLines.NFL:
856                case TacticalLines.MFP:
857                case TacticalLines.RFL:
858                case TacticalLines.CONVOY:
859                case TacticalLines.HCONVOY:
860                case TacticalLines.MSR:
861                case TacticalLines.ASR:
862                case TacticalLines.ONEWAY:
863                case TacticalLines.TWOWAY:
864                case TacticalLines.ALT:
865                    result = true;
866                    break;
867                default:
868                    result = false;
869                    break;
870            }
871        }
872        catch(Exception exc)
873        {
874               ErrorLogger.LogException(_className ,"LinesWithFill",
875                    new RendererException("Failed inside LinesWithFill", exc));
876        }
877        return result;
878    }
879    /**
880     * @deprecated
881     * if the line color and fill color are the same or very close then we want to
882     * tweak the fill color a bit to make the line appear distinct from the fill.
883     * @param tg
884     */
885    public static void tweakFillColor(TGLight tg)
886    {
887        try
888        {
889            if(isSameColor(tg.get_LineColor(),tg.get_FillColor())==false)
890                return;
891
892            Color fillColor=tg.get_FillColor();
893            int r=fillColor.getRed(),g=fillColor.getGreen(),b=fillColor.getBlue();
894            int alpha=fillColor.getAlpha();
895
896            r*=0.9;
897            g*=0.9;
898            b*=0.9;
899            alpha*=0.8;
900
901            fillColor=new Color(r,g,b,alpha);
902            tg.set_FillColor(fillColor);
903        }
904        catch(Exception exc)
905        {
906               ErrorLogger.LogException(_className ,"tweakFillColor",
907                    new RendererException("Failed inside tweakFillColor", exc));
908        }
909    }
910    /**
911     * @deprecated
912     * Test to see if two colors are similar
913     * @param c1
914     * @param c2
915     * @return true is same (or similar) color
916     */
917    public static Boolean isSameColor(Color c1, Color c2)
918    {
919        try
920        {
921            if(c1==null || c2==null)
922                return true;
923
924            int r1=c1.getRed(),r2=c2.getRed(),g1=c1.getGreen(),g2=c2.getGreen(),
925                    b1=c1.getBlue(),b2=c2.getBlue();
926
927            if(Math.abs(r1-r2)<5)
928                if(Math.abs(g1-g2)<5)
929                    if(Math.abs(b1-b2)<5)
930                        return true;
931        }
932        catch(Exception exc)
933        {
934               ErrorLogger.LogException(_className ,"isSameColor",
935                    new RendererException("Failed inside isSameColor", exc));
936        }
937        return false;
938    }
939    /**
940     * Customer requested routine for setting the stroke dash pattern
941     * @param width
942     * @param style
943     * @param cap
944     * @param round
945     * @return
946     */
947    public static BasicStroke getLineStroke(float width, int style, int cap, int round)
948    {
949        // NOTE: We restrict ourselves to using a base dash array of
950        // approximately length 8 (scaled by width). CPOF's 3D map usesOpenGL
951        // stippling and this works with bit patterns of exactly 16bits.
952        // We could increase our base dash array to length 16 if itwere necessary
953        // in order to support a new stipple type.
954
955        // Some segments are of length 0.1 because the Java2D rendereradds line caps of
956        // width/2 size to both ends of the segment when "round" is oneof BasicStroke.CAP_ROUND
957        // or BasicStroke.CAP_SQUARE. This value is small enough not to affect the
958        // stipple bit pattern calculation for the 3d map and stilllook good on the
959        // 2d map.
960
961        // NOTE: The dash arrays below do not supportBasisStroke.CAP_BUTT line capping,
962        // although it would be relatively simple to change them suchthat they would.
963        BasicStroke stroke=null;
964        try
965        {
966            switch (style)
967            {
968                case 0://GraphicProperties.LINE_TYPE_SOLID:
969                    stroke = new BasicStroke(width, cap, round);
970                    break;
971                case 1://GraphicProperties.LINE_TYPE_DASHED:
972                    float[] dash = {2*width, 2*width, 2*width, 2*width};
973                    stroke = new BasicStroke(width, cap, round, 4f, dash, 0f);
974                    break;
975                case 2://GraphicProperties.LINE_TYPE_DOTTED:
976                    float[] dot = {0.1f*width, 2f*width, 0.1f*width,2f*width, 0.1f*width, 2f*width, 0.1f*width, 2f*width};
977                    stroke = new BasicStroke(width, cap, round, 4f, dot, 0f);
978                    break;
979                case 3://GraphicProperties.LINE_TYPE_DASHDOT:
980                    float[] dashdot = {4f*width, 2f*width, 0.1f*width,2f*width};
981                    stroke = new BasicStroke(width, cap, round, 4f, dashdot,0f );
982                    break;
983                case 4://GraphicProperties.LINE_TYPE_DASHDOTDOT:
984                    float[] dashdotdot = {2f*width, 2f*width, 0.1f*width,2f*width, 0.1f*width, 2f*width};
985                    stroke = new BasicStroke(width, cap, round, 4f,dashdotdot, 0f );
986                    break;
987                default:
988                    stroke = new BasicStroke(width, cap, round);
989                    break;
990            }
991        }
992        catch(Exception exc)
993        {
994               ErrorLogger.LogException(_className ,"getLineStroke",
995                    new RendererException("Failed inside getLineStroke", exc));
996        }
997        return stroke;
998    }
999    /**
1000     * GE clients
1001     * @param width
1002     * @param style
1003     * @param cap
1004     * @param round
1005     * @return 
1006     */
1007    public static BasicStroke getLineStroke2(float width, int style, int cap, int round)
1008    {
1009        // NOTE: We restrict ourselves to using a base dash array of
1010        // approximately length 8 (scaled by width). CPOF's 3D map usesOpenGL
1011        // stippling and this works with bit patterns of exactly 16bits.
1012        // We could increase our base dash array to length 16 if itwere necessary
1013        // in order to support a new stipple type.
1014
1015        // Some segments are of length 0.1 because the Java2D rendereradds line caps of
1016        // width/2 size to both ends of the segment when "round" is oneof BasicStroke.CAP_ROUND
1017        // or BasicStroke.CAP_SQUARE. This value is small enough not to affect the
1018        // stipple bit pattern calculation for the 3d map and stilllook good on the
1019        // 2d map.
1020
1021        // NOTE: The dash arrays below do not supportBasisStroke.CAP_BUTT line capping,
1022        // although it would be relatively simple to change them suchthat they would.
1023        BasicStroke stroke=null;
1024        try
1025        {
1026            switch (style)
1027            {
1028                case 0://GraphicProperties.LINE_TYPE_SOLID:
1029                    stroke = new BasicStroke(width, cap, round);
1030                    break;
1031                case 1://GraphicProperties.LINE_TYPE_DASHED:
1032                    //float[] dash = {2*width, 2*width, 2*width, 2*width};
1033                    float[] dash = {2*width, 2*width};
1034                    stroke = new BasicStroke(width, cap, round, 4f, dash, 0f);
1035                    break;
1036                case 2://GraphicProperties.LINE_TYPE_DOTTED:
1037                    //float[] dot = {0.1f*width, 2f*width, 0.1f*width,2f*width, 0.1f*width, 2f*width, 0.1f*width, 2f*width};
1038                    float[] dot = {0.1f*width, 2f*width};
1039                    stroke = new BasicStroke(width, cap, round, 4f, dot, 0f);
1040                    break;
1041                case 3://GraphicProperties.LINE_TYPE_DASHDOT:
1042                    float[] dashdot = {4f*width, 2f*width, 0.1f*width,2f*width};
1043                    stroke = new BasicStroke(width, cap, round, 4f, dashdot,0f );
1044                    break;
1045                case 4://GraphicProperties.LINE_TYPE_DASHDOTDOT:
1046                    float[] dashdotdot = {2f*width, 2f*width, 0.1f*width,2f*width, 0.1f*width, 2f*width};
1047                    stroke = new BasicStroke(width, cap, round, 4f,dashdotdot, 0f );
1048                    break;
1049                default:
1050                    stroke = new BasicStroke(width, cap, round);
1051                    break;
1052            }
1053        }
1054        catch(Exception exc)
1055        {
1056               ErrorLogger.LogException(_className ,"getLineStroke",
1057                    new RendererException("Failed inside getLineStroke", exc));
1058        }
1059        return stroke;
1060    }
1061    /**
1062     * Sets shape properties based on other properties which were set by JavaLineArray
1063     * @param tg tactical graphic
1064     * @param shapes the ShapeInfo array
1065     * @param bi BufferedImage to use for setting shape TexturePaint
1066     */
1067    public static void SetShapeProperties(TGLight tg, ArrayList<Shape2> shapes,
1068            BufferedImage bi) {
1069        try
1070        {
1071            if (shapes == null)
1072            {
1073                return;
1074            }
1075            
1076            int j = 0;
1077            Shape2 shape = null;
1078            BasicStroke stroke = null;
1079            float[] dash = null;
1080            int lineThickness = tg.get_LineThickness();
1081            int shapeType = -1;
1082            int lineType = tg.get_LineType();
1083            boolean hasFill=LinesWithFill(lineType);
1084            boolean isChange1Area = clsUtility.IsChange1Area(lineType, null);
1085            boolean isClosedPolygon = clsUtility.isClosedPolygon(lineType);
1086            //int n=shapes.size();
1087            //remove air corridors fill shapes if fill is null
1088            if(tg.get_FillColor()==null)
1089            {
1090                switch(tg.get_LineType())
1091                {
1092                    case TacticalLines.AC:
1093                    case TacticalLines.SAAFR:
1094                    case TacticalLines.MRR:
1095                    case TacticalLines.MRR_USAS:
1096                    case TacticalLines.UAV:
1097                    case TacticalLines.UAV_USAS:
1098                    case TacticalLines.LLTR:
1099                        shape=shapes.get(shapes.size()-1);
1100                        shapes.clear();
1101                        shapes.add(shape);
1102                        break;
1103                    case TacticalLines.CATK:
1104                    case TacticalLines.AXAD:
1105                    case TacticalLines.AIRAOA:
1106                    case TacticalLines.AAAAA:
1107                    case TacticalLines.SPT:
1108                    case TacticalLines.AAFNT:           //40
1109                    case TacticalLines.MAIN:
1110                    case TacticalLines.CATKBYFIRE:      //80
1111                        ArrayList<Shape2> tempShapes=new ArrayList();
1112                        for(j=0;j<shapes.size();j++)
1113                        {
1114                            shape=shapes.get(j);
1115                            if(shape.getShapeType() != Shape2.SHAPE_TYPE_FILL)
1116                                tempShapes.add(shape);
1117                        }
1118                        shapes=tempShapes;
1119                        break;
1120                    default:
1121                        break;
1122                }
1123            }
1124            for (j = 0; j < shapes.size(); j++) 
1125            {
1126                shape = shapes.get(j);
1127                if (shape == null || shape.getShape() == null) {
1128                    continue;
1129                }
1130
1131                if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) 
1132                {
1133                    switch(tg.get_LineType())
1134                    {
1135                        case TacticalLines.DEPTH_AREA:
1136                            break;
1137                        default:
1138                            shape.setFillColor(tg.get_FillColor());
1139                            break;
1140                    }
1141                }
1142
1143                //if(lineType != TacticalLines.LEADING_LINE)
1144                ResolveModifierShape(tg, shape);
1145                if(lineType==TacticalLines.AIRFIELD)
1146                    if(j==1)
1147                        shape.setFillColor(null);
1148                //diagnostic
1149                if(lineType==TacticalLines.BBS_POINT)
1150                    if(j==0)
1151                        shape.setLineColor(null);
1152                //end section
1153                
1154                shapeType = shape.getShapeType();
1155
1156                if (lineType == TacticalLines.LC) {
1157                    SetLCColor(tg, shape);
1158                }
1159
1160                Rectangle2D.Double rect = null;
1161                Graphics2D grid = null;
1162                TexturePaint tp = tg.get_TexturePaint();
1163
1164                if (hasFill || isClosedPolygon || isChange1Area || shapeType == Shape2.SHAPE_TYPE_FILL)
1165                {                    
1166                    switch (shape.get_FillStyle()) {
1167                        case 3://GraphicProperties.FILL_TYPE_RIGHT_SLANTS:
1168                            rect = new Rectangle2D.Double(0, 0, 8, 8);
1169                            //rect = new Rectangle2D.Double(0, 0, 100, 100);
1170                            grid = bi.createGraphics();
1171                            //grid.setColor(GetOpaqueColor(shape.get_LineColor()));
1172                            grid.setColor(GetOpaqueColor(tg.get_LineColor()));
1173
1174                            grid.setStroke(new BasicStroke(2));
1175                            grid.drawLine(0, 8, 8, 0);
1176                            //grid.drawLine(0, 0, 100, 100);
1177                            tp = new TexturePaint(bi, rect);
1178                            shape.setTexturePaint(tp);
1179                            shape.setFillColor(tg.get_FillColor());
1180                            grid.dispose();
1181                            //clsUtility.WriteFile("fillstyle = " + Integer.toString(shape.get_FillStyle()));
1182                            break;
1183                        case 2://GraphicProperties.FILL_TYPE_LEFT_SLANTS:
1184                            rect = new Rectangle2D.Double(0, 0, 8, 8);
1185                            //rect = new Rectangle2D.Double(0, 0, 20, 20);
1186                            grid = bi.createGraphics();
1187                            //grid.setColor(GetOpaqueColor(tg.get_LineColor()));
1188                            grid.setColor(GetOpaqueColor(tg.get_LineColor()));
1189
1190                            grid.setStroke(new BasicStroke(2));
1191                            grid.drawLine(0, 0, 8, 8);
1192                            //grid.drawLine(0, 0, 20, 20);
1193                            tp = new TexturePaint(bi, rect);
1194                            shape.setTexturePaint(tp);
1195                            shape.setFillColor(tg.get_FillColor());
1196                            grid.dispose();
1197                            //clsUtility.WriteFile("set TexturePaint");
1198                            break;
1199                        case 6://GraphicProperties.FILL_TYPE_DOTS:
1200                            rect = new Rectangle2D.Double(3, 3, 8, 8);
1201                            grid = bi.createGraphics();
1202                            grid.setColor(tg.get_FillColor());
1203                            grid.drawLine(3, 3, 5, 3);
1204                            grid.drawLine(5, 3, 5, 5);
1205                            grid.drawLine(5, 5, 3, 5);
1206                            grid.drawLine(3, 5, 5, 3);
1207                            tp = new TexturePaint(bi, rect);
1208                            shape.setTexturePaint(tp);
1209                            shape.setFillColor(null);
1210                            grid.dispose();
1211                            break;
1212                        case 4://GraphicProperties.FILL_TYPE_VERTICAL_LINES:
1213                            rect = new Rectangle2D.Double(0, 0, 8, 8);
1214                            //rect = new Rectangle2D.Double(0, 0, 20, 20);
1215                            grid = bi.createGraphics();
1216                            grid.setColor(GetOpaqueColor(tg.get_LineColor()));
1217                            grid.setStroke(new BasicStroke(2));
1218                            grid.drawLine(4, 0, 4, 8);
1219                            //grid.drawLine(10, 0, 10, 20);
1220                            tp = new TexturePaint(bi, rect);
1221                            shape.setTexturePaint(tp);
1222                            shape.setFillColor(tg.get_FillColor());
1223                            grid.dispose();
1224                            break;
1225                        case 5://GraphicProperties.FILL_TYPE_HORIZONTAL_LINES:
1226                            rect = new Rectangle2D.Double(0, 0, 8, 8);
1227                            //rect = new Rectangle2D.Double(0, 0, 20, 20);
1228                            grid = bi.createGraphics();
1229                            grid.setColor(GetOpaqueColor(tg.get_LineColor()));
1230                            grid.setStroke(new BasicStroke(2));
1231                            grid.drawLine(0, 4, 8, 4);
1232                            //grid.drawLine(0, 10, 20, 10);
1233                            tp = new TexturePaint(bi, rect);
1234                            shape.setTexturePaint(tp);
1235                            shape.setFillColor(tg.get_FillColor());
1236                            grid.dispose();
1237                            break;
1238                        case 7://GraphicProperties.FILL_TYPE_HORIZONTAL_PLUSSES:
1239                            rect = new Rectangle2D.Double(0, 0, 8, 8);
1240                            //rect = new Rectangle2D.Double(0, 0, 20, 20);
1241                            grid = bi.createGraphics();
1242                            grid.setColor(GetOpaqueColor(tg.get_LineColor()));
1243                            grid.setStroke(new BasicStroke(2));
1244                            grid.drawLine(4, 2, 4, 6);
1245                            grid.drawLine(2, 4, 6, 4);
1246                            tp = new TexturePaint(bi, rect);
1247                            shape.setTexturePaint(tp);
1248                            shape.setFillColor(tg.get_FillColor());
1249                            grid.dispose();
1250                            break;
1251                        case 8://GraphicProperties.FILL_TYPE_XHATCH:
1252                            rect = new Rectangle2D.Double(0, 0, 10, 10);
1253                            //rect = new Rectangle2D.Double(0, 0, 20, 20);
1254                            grid = bi.createGraphics();
1255                            grid.setColor(GetOpaqueColor(tg.get_LineColor()));
1256                            grid.setStroke(new BasicStroke(2));
1257                            grid.drawLine(2, 2, 8, 8);                            
1258                            grid.drawLine(2, 8, 8, 2);
1259                            tp = new TexturePaint(bi, rect);
1260                            shape.setTexturePaint(tp);
1261                            shape.setFillColor(tg.get_FillColor());
1262                            grid.dispose();
1263                            break;
1264                        case 1://GraphicProperties.FILL_TYPE_SOLID:
1265                            //shape.set_FillColor(tg.get_FillColor());
1266                            break;
1267                        default:
1268                            break;
1269                    }
1270                }
1271                
1272                if(lineThickness==0)
1273                    lineThickness=1;
1274                //set the shape with the default properties
1275                //the switch statement below will override specific properties as needed
1276                stroke=getLineStroke(lineThickness,shape.get_Style(),BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
1277                if(tg.get_Client().equalsIgnoreCase("ge"))
1278                {
1279                    if(tg.get_LineType() == TacticalLines.AAFNT && shape.get_Style()==2)
1280                        shape.set_Style(1);
1281
1282                    stroke=getLineStroke2(lineThickness,shape.get_Style(),BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
1283                }                
1284                if(shape.getShapeType()==Shape2.SHAPE_TYPE_FILL)
1285                {
1286                    stroke = new BasicStroke(lineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
1287                    //shape.setStroke(new BasicStroke(0));
1288                }
1289                shape.setStroke(stroke);
1290            }
1291        }
1292        catch (Exception exc) {
1293               ErrorLogger.LogException(_className ,"SetShapeProperties",
1294                    new RendererException("Failed inside SetShapeProperties", exc));
1295        }
1296    }
1297    /**
1298     * Returns a boolean indicating whether the line type is a change 1 area
1299     * @param lineType the line type
1300     * @param minPoints Out - object to hold the minimum number of client points required
1301     * @return true if change 1 area
1302     */
1303    public static boolean IsChange1Area(int lineType,
1304            ref<int[]> minPoints) {
1305        try {
1306            if (minPoints != null) {
1307                minPoints.value = new int[1];
1308            }
1309            switch (lineType) {
1310                case TacticalLines.LAUNCH_AREA:
1311                    if (minPoints != null) {
1312                        minPoints.value[0] = 1;
1313                    }
1314                    return true;
1315                case TacticalLines.FEBA:
1316                    if (minPoints != null) {
1317                        minPoints.value[0] = 1;
1318                    }
1319                    return false;
1320                case TacticalLines.RECTANGULAR:
1321                case TacticalLines.PBS_RECTANGLE:
1322                case TacticalLines.PBS_SQUARE:
1323                case TacticalLines.CIRCULAR:
1324                case TacticalLines.BBS_POINT:
1325                case TacticalLines.FSA_CIRCULAR:
1326                case TacticalLines.FFA_CIRCULAR:
1327                case TacticalLines.NFA_CIRCULAR:
1328                case TacticalLines.RFA_CIRCULAR:
1329                case TacticalLines.ACA_CIRCULAR:
1330                case TacticalLines.PAA_CIRCULAR:
1331                case TacticalLines.ATI_CIRCULAR:
1332                case TacticalLines.CFFZ_CIRCULAR:
1333                case TacticalLines.SENSOR_CIRCULAR:
1334                case TacticalLines.CENSOR_CIRCULAR:
1335                case TacticalLines.DA_CIRCULAR:
1336                case TacticalLines.CFZ_CIRCULAR:
1337                case TacticalLines.ZOR_CIRCULAR:
1338                case TacticalLines.TBA_CIRCULAR:
1339                case TacticalLines.TVAR_CIRCULAR:
1340                case TacticalLines.KILLBOXBLUE_CIRCULAR:
1341                case TacticalLines.KILLBOXPURPLE_CIRCULAR:
1342                case TacticalLines.RANGE_FAN:
1343                case TacticalLines.RANGE_FAN_FILL:
1344                case TacticalLines.RANGE_FAN_SECTOR:
1345                    if (minPoints != null) {
1346                        minPoints.value[0] = 1;
1347                    }
1348                    return true;
1349                case TacticalLines.PAA_RECTANGULAR_REVC:
1350                case TacticalLines.FSA_RECTANGULAR:
1351                case TacticalLines.FFA_RECTANGULAR:
1352                case TacticalLines.RFA_RECTANGULAR:
1353                case TacticalLines.NFA_RECTANGULAR:
1354                case TacticalLines.ACA_RECTANGULAR:
1355                case TacticalLines.ATI_RECTANGULAR:
1356                case TacticalLines.CFFZ_RECTANGULAR:
1357                case TacticalLines.SENSOR_RECTANGULAR:
1358                case TacticalLines.CENSOR_RECTANGULAR:
1359                case TacticalLines.DA_RECTANGULAR:
1360                case TacticalLines.CFZ_RECTANGULAR:
1361                case TacticalLines.ZOR_RECTANGULAR:
1362                case TacticalLines.TBA_RECTANGULAR:
1363                case TacticalLines.TVAR_RECTANGULAR:
1364                case TacticalLines.KILLBOXBLUE_RECTANGULAR:
1365                case TacticalLines.KILLBOXPURPLE_RECTANGULAR:
1366                    if (minPoints != null) {
1367                        minPoints.value[0] = 1;
1368                    }
1369                    return true;
1370                default:
1371                    return false;
1372            }
1373        } catch (Exception exc) {
1374            //clsUtility.WriteFile("Error in clsUtility.IsChange1Area");
1375               ErrorLogger.LogException(_className ,"IsChange1Area",
1376                    new RendererException("Failed inside IsChange1Area", exc));
1377        }
1378        return false;
1379    }
1380
1381    public static void WriteFile(String str) {
1382        try {
1383            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("Test.txt"));
1384            bufferedWriter.write(str);
1385            //bufferedWriter.newLine();
1386            //bufferedWriter.write(pointType);
1387            bufferedWriter.close();
1388            bufferedWriter = null;
1389        } 
1390        catch (Exception exc) {
1391               ErrorLogger.LogException(_className ,"WriteFile",
1392                    new RendererException("Failed inside WriteFile", exc));
1393        }
1394    }
1395
1396    /**
1397     * Calculates point where two lines intersect.
1398     * First line defined by pt1, m1.
1399     * Second line defined by pt2, m2.
1400     * result will be written to ptIntersect.
1401     * @param pt1 first line point
1402     * @param m1 slope of first line
1403     * @param pt2 second line point
1404     * @param m2 slope of second line
1405     * @param ptIntersect OUT - intersection point
1406     */
1407    protected static void CalcIntersectPt(POINT2 pt1,
1408            double m1,
1409            POINT2 pt2,
1410            double m2,
1411            POINT2 ptIntersect) {
1412        try {
1413            if (m1 == m2) {
1414                return;
1415            }
1416
1417            double x1 = pt1.x;
1418            double y1 = pt1.y;
1419            double x2 = pt2.x;
1420            double y2 = pt2.y;
1421            //formula for the intersection of two lines
1422            double dx2 = (double) ((y1 - y2 + m1 * x2 - m1 * x1) / (m2 - m1));
1423            double x3 = x2 + dx2;
1424            double y3 = (double) (y2 + m2 * dx2);
1425
1426            ptIntersect.x = x3;
1427            ptIntersect.y = y3;
1428        } catch (Exception exc) {
1429            //clsUtility.WriteFile("Error in clsUtility.CalcIntersectPt");
1430            ErrorLogger.LogException(_className, "CalcIntersectPt",
1431                    new RendererException("Failed inside CalcIntersectPt", exc));
1432        }
1433    }
1434
1435    /**
1436     * Calculates the channel width in pixels for channel types
1437     * @param pixels the client points as 2-tuples x,y in pixels
1438     * @param distanceToChannelPOINT2 OUT - the calculated distance in pixels from the tip of the
1439     * arrowhead to the back of the arrowhead.
1440     * @return the channel width in pixels
1441     */
1442    protected static int ChannelWidth(double[] pixels,
1443            ref<double[]> distanceToChannelPOINT2) {
1444        int width = 0;
1445        try {
1446            int numPOINT2s = pixels.length / 2;
1447            if (numPOINT2s < 3) {
1448                return 0;
1449            }
1450
1451            POINT2 channelWidthPOINT2 = new POINT2(0, 0);
1452            POINT2 lastSegmentPt1 = new POINT2(0, 0);
1453            POINT2 lastSegmentPt2 = new POINT2(0, 0);
1454
1455            lastSegmentPt1.x = (double) pixels[2 * numPOINT2s - 6];
1456            lastSegmentPt1.y = (double) pixels[2 * numPOINT2s - 5];
1457            lastSegmentPt2.x = (double) pixels[2 * numPOINT2s - 4];
1458            lastSegmentPt2.y = (double) pixels[2 * numPOINT2s - 3];
1459            channelWidthPOINT2.x = (double) pixels[2 * numPOINT2s - 2];
1460            channelWidthPOINT2.y = (double) pixels[2 * numPOINT2s - 1];
1461
1462            ref<double[]> m = new ref();
1463            double m1 = 0;
1464            //m1.value=new double[1];
1465            double distance = 0;
1466            POINT2 ptIntersect = new POINT2(0, 0);
1467            //boolean bolVertical = TrueSlope(lastSegmentPt1, lastSegmentPt2, ref m);
1468            boolean bolVertical = lineutility.CalcTrueSlopeDouble2(lastSegmentPt1, lastSegmentPt2, m);
1469            if (bolVertical == true && m.value[0] != 0) {
1470                m1 = -1 / m.value[0];
1471                CalcIntersectPt(channelWidthPOINT2, m1, lastSegmentPt2, m.value[0], ptIntersect);
1472                distance = lineutility.CalcDistanceDouble(channelWidthPOINT2, ptIntersect);
1473            }
1474            if (bolVertical == true && m.value[0] == 0) //horizontal segment
1475            {
1476                distance = Math.abs(channelWidthPOINT2.y - lastSegmentPt1.y);
1477            }
1478            if (bolVertical == false) //vertical segment
1479            {
1480                distance = Math.abs(channelWidthPOINT2.x - lastSegmentPt1.x);
1481                distanceToChannelPOINT2.value = new double[1];
1482                distanceToChannelPOINT2.value[0] = distance;
1483                return (int) distance * 4;
1484            }
1485
1486            width = (int) distance * 8;
1487            if (width < 2) {
1488                width = 2;
1489            }
1490
1491            double hypotenuse = lineutility.CalcDistanceDouble(lastSegmentPt2, channelWidthPOINT2);
1492            distanceToChannelPOINT2.value = new double[1];
1493            distanceToChannelPOINT2.value[0] = Math.sqrt(hypotenuse * hypotenuse - distance * distance);
1494
1495        } catch (Exception exc) {
1496            //clsUtility.WriteFile("Error in clsUtility.ChannelWidth");
1497            ErrorLogger.LogException(_className, "ChannelWidth",
1498                    new RendererException("Failed inside ChannelWidth", exc));
1499        }
1500        return width;
1501    }
1502
1503    private static boolean InYOrder(POINT2 pt0,
1504            POINT2 pt1,
1505            POINT2 pt2) {
1506        try {
1507            if (pt0.y <= pt1.y && pt1.y <= pt2.y) {
1508                return true;
1509            }
1510
1511            if (pt2.y <= pt1.y && pt1.y <= pt0.y) {
1512                return true;
1513            }
1514
1515        } catch (Exception exc) {
1516            //clsUtility.WriteFile("Error in clsUtility.InYOrder");
1517            ErrorLogger.LogException(_className, "InYOrder",
1518                    new RendererException("Failed inside InYOrder", exc));
1519        }
1520        return false;
1521    }
1522    /// <summary>
1523    /// tests if POINT2s have successively increasing or decreasing x values.
1524    /// </summary>
1525    /// <param name="pt0"></param>
1526    /// <param name="pt1"></param>
1527    /// <param name="pt2"></param>
1528    /// <returns>true if POINT2s are in X order</returns>
1529
1530    private static boolean InXOrder(POINT2 pt0,
1531            POINT2 pt1,
1532            POINT2 pt2) {
1533        try {
1534            if (pt0.x <= pt1.x && pt1.x <= pt2.x) {
1535                return true;
1536            }
1537
1538            if (pt2.x <= pt1.x && pt1.x <= pt0.x) {
1539                return true;
1540            }
1541
1542        } catch (Exception exc) {
1543            //clsUtility.WriteFile("Error in clsUtility.InXOrder");
1544            ErrorLogger.LogException(_className, "InXOrder",
1545                    new RendererException("Failed inside InXOrder", exc));
1546        }
1547        return false;
1548    }
1549
1550    /**
1551     * For each sector calculates left azimuth, right azimuth, min radius, max radius
1552     * and stuff H2 with the string delimited result. The function is public, called by JavaRendererServer
1553     * @param tg tactical graphic
1554     */
1555    public static void GetSectorRadiiFromPoints(TGLight tg) {
1556        try {
1557            if(tg.get_LineType()==TacticalLines.RANGE_FAN_FILL)
1558                return;
1559            POINT2 ptCenter = tg.LatLongs.get(0);
1560            POINT2 ptLeftMin = new POINT2(), ptRightMax = new POINT2();
1561            int k = 0;
1562            String strLeft = "", strRight = "", strMin = "", strMax = "", temp = "";
1563            double nLeft = 0, nRight = 0, nMin = 0, nMax = 0;
1564            //if tg.PointCollection has more than one point
1565            //we use the points to calculate left,right,min,max
1566            //and then stuff tg.H2 with the comma delimited string
1567            double dist = 0;
1568            ref<double[]> a12 = new ref(), a21 = new ref();
1569            int numSectors = 0;
1570            if (tg.LatLongs.size() > 2) {
1571                numSectors = (tg.LatLongs.size() - 2) / 2;
1572                for (k = 0; k < numSectors; k++) {
1573                    //get the sector points
1574                    ptLeftMin = tg.LatLongs.get(2 * k + 2);
1575                    ptRightMax = tg.LatLongs.get(2 * k + 3);
1576
1577                    dist = mdlGeodesic.geodesic_distance(ptCenter, ptLeftMin, a12, a21);
1578                    nLeft = a12.value[0];
1579                    strLeft = Double.toString(nLeft);
1580
1581                    nMin = dist;
1582                    strMin = Double.toString(nMin);
1583
1584                    dist = mdlGeodesic.geodesic_distance(ptCenter, ptRightMax, a12, a21);
1585                    nRight = a12.value[0];
1586                    strRight = Double.toString(nRight);
1587
1588                    nMax = dist;
1589                    strMax = Double.toString(nMax);
1590
1591                    if (k == 0) {
1592                        temp = strLeft + "," + strRight + "," + strMin + "," + strMax;
1593                    } else {
1594                        temp += "," + strLeft + "," + strRight + "," + strMin + "," + strMax;
1595                    }
1596                }
1597                if (!temp.equals("")) {
1598                    tg.set_H2(temp);
1599                }
1600            }
1601        } catch (Exception exc) {
1602            //clsUtility.WriteFile("Error in clsUtility.GetSectorRadiiFromPoints");
1603            ErrorLogger.LogException(_className, "GetSectorRadiiFromPoints",
1604                    new RendererException("Failed inside GetSectorRadiiFromPoints", exc));
1605        }
1606    }
1607
1608    /**
1609     * Note: Mil-Std-2525 Rev C does not use this function.
1610     * For Rev C the radii are calculated from tg.H2
1611     * Calculates the radii for circular and sector range fans.
1612     * @param tg
1613     * @param lineType
1614     * @return
1615     */
1616    public static double[] GetRadii(TGLight tg, 
1617            int lineType) {
1618        double[] radius = null;
1619        try {
1620            //if the client passed more than one point we use the
1621            //additional points to calculate the radii
1622            //ArrayList<Double> rads=new ArrayList();
1623            if (lineType == TacticalLines.RANGE_FAN &&
1624                    tg.LatLongs.size() > 2)
1625            {
1626
1627                POINT2 ptCenter = tg.LatLongs.get(0);
1628
1629                POINT2 pt = new POINT2();
1630                double dist = 0;
1631                ref<double[]> a12 = new ref(), a21 = new ref();
1632                int rad = 0;
1633                String temp = "";
1634                //we skip tg.PointCollection.get_Point(1) because
1635                //that's the orientation point
1636                int t=tg.LatLongs.size();
1637                //for (int j = 2; j < tg.LatLongs.size(); j++)
1638                for (int j = 2; j < t; j++)
1639                {
1640                    pt = new POINT2(tg.LatLongs.get(j));
1641                    dist = mdlGeodesic.geodesic_distance(ptCenter, pt, a12, a21);
1642                    rad = (int) dist;
1643                    if (rad <= 0) {
1644                        continue;
1645                    }
1646                    if (j == 2) {
1647                        temp = Double.toString(rad);
1648                    } else {
1649                        temp += ",";
1650                        temp += Double.toString(rad);
1651                    }
1652                }
1653                tg.set_H2(temp);
1654                //clsTGProperties.set_H2Field(temp);
1655            }
1656            String[] strRadius = null;
1657            String radii = tg.get_H2();
1658
1659            if (lineType == TacticalLines.RANGE_FAN_SECTOR)
1660            {
1661                GetSectorRadiiFromPoints(tg);
1662                radii = tg.get_H2();
1663            }
1664            strRadius = radii.split(",");
1665
1666
1667            int n = strRadius.length;
1668            if (n > 0) {
1669                radius = new double[n];
1670            } else {
1671                return null;
1672            }
1673
1674            if (lineType == TacticalLines.RANGE_FAN) {
1675                for (int k = 0; k < n; k++) {
1676                    radius[k] = Double.parseDouble(strRadius[k]);
1677                }
1678            } //there are twice as many strings in H1 as radii for scetor range fans
1679            else if (lineType == TacticalLines.RANGE_FAN_SECTOR) {
1680                int numSectors = n / 4;
1681                double[] radius2 = new double[numSectors * 2];
1682                int l = 0;
1683                for (int k = 0; k < numSectors; k++) {
1684                    radius2[l++] = Double.parseDouble(strRadius[4 * k + 2]);
1685                    radius2[l++] = Double.parseDouble(strRadius[4 * k + 3]);
1686                }
1687                radius = radius2;
1688            }
1689        } catch (Exception exc) {
1690            ErrorLogger.LogException(_className, "GetRadii",
1691                    new RendererException("Failed inside GetRadii", exc));
1692        }
1693        return radius;
1694    }
1695
1696    /**
1697     * Reverses the pixels except for the last point. This is used for
1698     * the axis of advance type routes. The pixels are 2-tuples x,y
1699     *
1700     * @param pixels OUT - Array of client points
1701     */
1702    protected static void ReorderPixels(double[] pixels) {
1703        try {
1704            double[] tempPixels;
1705            //reverse the pixels
1706            int j;
1707            double x;
1708            double y;
1709            int counter;
1710            int numPoints;
1711            counter = 0;
1712            numPoints = pixels.length / 2;
1713            tempPixels = new double[pixels.length];
1714            for (j = 0; j < numPoints - 1; j++) {
1715                x = pixels[pixels.length - 2 * j - 4];
1716                y = pixels[pixels.length - 2 * j - 3];
1717                tempPixels[counter] = x;
1718                tempPixels[counter + 1] = y;
1719                counter += 2;
1720            }
1721            //put the last pixel point into the last temppixels point
1722            int intPixelSize = pixels.length;
1723            tempPixels[counter] = pixels[intPixelSize - 2];
1724            tempPixels[counter + 1] = pixels[intPixelSize - 1];
1725            //stuff the pixels
1726            int n=pixels.length;
1727            //for (j = 0; j < pixels.length; j++) 
1728            for (j = 0; j < n; j++) 
1729            {
1730                pixels[j] = tempPixels[j];
1731            }
1732            //tempPixels = null;
1733        } catch (Exception exc) {
1734            ErrorLogger.LogException(_className, "ReorderPixels",
1735                    new RendererException("Failed inside ReorderPixels", exc));
1736        }
1737    }
1738    /**
1739     * do not allow vertical segments for these, move the point x value by 1 pixel
1740     * @param tg tactical graphic
1741     */
1742    public static void FilterVerticalSegments(TGLight tg)
1743    {
1744        try
1745        {
1746            switch(tg.get_LineType())
1747            {
1748                case TacticalLines.AAFNT:
1749                case TacticalLines.MAIN:
1750                case TacticalLines.CATK:
1751                case TacticalLines.CATKBYFIRE:
1752                case TacticalLines.AXAD:
1753                case TacticalLines.AIRAOA:
1754                case TacticalLines.AAAAA:
1755                case TacticalLines.SPT:
1756                case TacticalLines.LC:
1757                case TacticalLines.LC2:
1758                case TacticalLines.UNSP:
1759                case TacticalLines.DFENCE:
1760                case TacticalLines.SFENCE:
1761                case TacticalLines.DOUBLEA:
1762                case TacticalLines.LWFENCE:
1763                case TacticalLines.HWFENCE:
1764                case TacticalLines.BBS_LINE:
1765                case TacticalLines.SINGLEC:
1766                case TacticalLines.SINGLEC2:
1767                case TacticalLines.DOUBLEC:
1768                case TacticalLines.DOUBLEC2:
1769                case TacticalLines.TRIPLE:
1770                case TacticalLines.TRIPLE2:
1771                case TacticalLines.BELT1:
1772                case TacticalLines.ALT:
1773                case TacticalLines.ONEWAY:
1774                case TacticalLines.TWOWAY:
1775                case TacticalLines.ATWALL:
1776                    break;
1777                default:
1778                    return;
1779            }
1780            POINT2 ptCurrent=null;
1781            POINT2 ptLast=null;
1782            int n=tg.Pixels.size();
1783            //for(int j=1;j<tg.Pixels.size();j++)
1784            for(int j=1;j<n;j++)
1785            {
1786                ptLast=new POINT2(tg.Pixels.get(j-1));
1787                ptCurrent=new POINT2(tg.Pixels.get(j));
1788                //if(Math.round(ptCurrent.x)==Math.round(ptLast.x))
1789                if(Math.abs(ptCurrent.x-ptLast.x)<1)
1790                {
1791                    if (ptCurrent.x>=ptLast.x)
1792                        ptCurrent.x += 1;
1793                    else
1794                        ptCurrent.x -= 1;
1795                    tg.Pixels.set(j, ptCurrent);
1796                }
1797            }
1798        }
1799        catch(Exception exc)
1800        {
1801            ErrorLogger.LogException("clsUtility", "FilterVerticalSegments",
1802                    new RendererException("Failed inside FilterVerticalSegments", exc));
1803
1804        }
1805    }
1806    /**
1807     * Client utility to calculate the channel points for channel types.
1808     * This code was ported from CJMTK.
1809     * @param arrLocation the client points
1810     * @return the channel point
1811     */
1812    public static POINT2 ComputeLastPoint(ArrayList<POINT2> arrLocation) {
1813        POINT2 locD = new POINT2(0, 0);
1814        try {
1815            POINT2 locA = arrLocation.get(1);
1816            //Get the first point (b) in pixels.
1817            //var locB:Point=new Point(arrLocation[0].x,arrLocation[0].y);
1818            POINT2 locB = arrLocation.get(0);
1819
1820            //Compute the distance in pixels from (a) to (b).
1821            double dblDx = locB.x - locA.x;
1822            double dblDy = locB.y - locA.y;
1823
1824            //Compute the dblAngle in radians from (a) to (b).
1825            double dblTheta = Math.atan2(-dblDy, dblDx);
1826
1827            //Compute a reasonable intermediate point along the line from (a) to (b).
1828            POINT2 locC = new POINT2(0, 0);
1829            locC.x = (int) (locA.x + 0.85 * dblDx);
1830            locC.y = (int) (locA.y + 0.85 * dblDy);
1831            //Put the last point on the left side of the line from (a) to (b).
1832            double dblAngle = dblTheta + Math.PI / 2.0;
1833            if (dblAngle > Math.PI) {
1834                dblAngle = dblAngle - 2.0 * Math.PI;
1835            }
1836            if (dblAngle < -Math.PI) {
1837                dblAngle = dblAngle + 2.0 * Math.PI;
1838            }
1839
1840            //Set the magnitude of the dblWidth in pixels.  Make sure it is at least 15 pixels.
1841            double dblWidth = 30;//was 15
1842
1843            //Compute the last point in pixels.
1844            locD.x = (locC.x + dblWidth * Math.cos(dblAngle));
1845            locD.y = (locC.y - dblWidth * Math.sin(dblAngle));
1846        } catch (Exception exc) {
1847            //clsUtility.WriteFile("Error in clsUtility.ComputeLatPoint");
1848            ErrorLogger.LogException(_className, "ComputeLastPoint",
1849                    new RendererException("Failed inside ComputeLastPoint", exc));
1850        }
1851        return locD;
1852    }
1853
1854    /**
1855     * Called by clsChannelUtility. The segments are used for managing double-backed segments
1856     * for channel types. If the new point is double-backed then the segment at that index will be false.
1857     *
1858     * @param pixels the client points as 2-tuples x,y in pixels
1859     * @param segments OUT - the segments
1860     * @param factor a steepness factor for calculating whether the segment is double-backed
1861     */
1862    protected static void GetSegments(double[] pixels,
1863            boolean[] segments,
1864            double factor) {
1865        try
1866        {
1867            int j = 0;
1868            ref<double[]> m1 = new ref();
1869            ref<double[]> m2 = new ref();
1870            long numPoints = 0;
1871            boolean bolVertical1 = false;
1872            boolean bolVertical2 = false;
1873
1874            POINT2 pt0F = new POINT2(0, 0);
1875            POINT2 pt1F = new POINT2(0, 0);
1876            POINT2 pt2F = new POINT2(0, 0);
1877
1878            segments[0] = true;
1879            
1880            numPoints = pixels.length / 2;
1881            for (j = 0; j < numPoints - 2; j++)
1882            {
1883                pt0F.x = (double) pixels[2 * j];
1884                pt0F.y = (double) pixels[2 * j + 1];
1885
1886                pt1F.x = (double) pixels[2 * j + 2];
1887                pt1F.y = (double) pixels[2 * j + 3];
1888
1889                pt2F.x = (double) pixels[2 * j + 4];
1890                pt2F.y = (double) pixels[2 * j + 5];
1891
1892                bolVertical1 = lineutility.CalcTrueSlopeDoubleForRoutes(pt0F, pt1F, m1);
1893                bolVertical2 = lineutility.CalcTrueSlopeDoubleForRoutes(pt1F, pt2F, m2);
1894
1895                segments[j + 1] = true;
1896                if (bolVertical1 == true && bolVertical2 == true)
1897                {
1898                    if (Math.abs(Math.atan(m1.value[0]) - Math.atan(m2.value[0])) < 1 / factor && InXOrder(pt0F, pt1F, pt2F) == false) //was 0.1
1899                    {
1900                        segments[j + 1] = false;
1901                    }
1902                }
1903
1904                if ((bolVertical1 == false || Math.abs(m1.value[0]) > factor) && (bolVertical2 == false || Math.abs(m2.value[0]) > factor) && InYOrder(pt0F, pt1F, pt2F) == false) //was 10
1905                {
1906                    segments[j + 1] = false;
1907                }
1908            }   //end for
1909            //int n=segments.length;
1910        }
1911        catch (Exception exc)
1912        {
1913            //System.out.println(e.getMessage());
1914            //clsUtility.WriteFile("Error in clsUtility.GetSegments");
1915            ErrorLogger.LogException(_className, "GetSegments",
1916                    new RendererException("Failed inside GetSegments", exc));
1917        }
1918    }
1919
1920    protected static void GetLCPartitions(double[] pixels,
1921                                          double LCChannelWith,
1922                                          ArrayList<P1> partitions,
1923                                          ArrayList<P1> singleLinePartitions) {
1924        try
1925        {
1926            int numPoints = pixels.length / 2;
1927            POINT2 pt0F = new POINT2(0, 0);
1928            POINT2 pt1F = new POINT2(0, 0);
1929            POINT2 pt2F = new POINT2(0, 0);
1930
1931            P1 nextP = new P1();
1932            nextP.start = 0;
1933
1934            //used for debugging
1935            double[] angles = new double[numPoints - 1];
1936
1937            for (int i = 0; i < numPoints - 2; i++) {
1938                pt0F.x = (double) pixels[2 * i];
1939                pt0F.y = (double) pixels[2 * i + 1];
1940
1941                pt1F.x = (double) pixels[2 * i + 2];
1942                pt1F.y = (double) pixels[2 * i + 3];
1943
1944                pt2F.x = (double) pixels[2 * i + 4];
1945                pt2F.y = (double) pixels[2 * i + 5];
1946
1947                double angle1 = Math.atan2(pt1F.y - pt0F.y, pt1F.x - pt0F.x);
1948                double angle2 = Math.atan2(pt1F.y - pt2F.y, pt1F.x - pt2F.x);
1949                double angle = angle1-angle2;// * 180/Math.PI;
1950                double degrees = angle * 180/Math.PI;
1951                if (angle < 0) {
1952                    degrees = 360 + degrees;
1953                }
1954
1955                if (degrees > 270) {
1956                    boolean angleTooSmall = false;
1957
1958                    if (lineutility.CalcDistanceDouble(pt0F, pt1F) < lineutility.CalcDistanceDouble(pt1F, pt2F)) {
1959                        POINT2 newPt = lineutility.ExtendAlongLineDouble2(pt1F, pt2F, lineutility.CalcDistanceDouble(pt1F, pt0F));
1960                        if (lineutility.CalcDistanceDouble(pt0F, newPt) < LCChannelWith)
1961                            angleTooSmall = true;
1962                    } else {
1963                        POINT2 newPt = lineutility.ExtendAlongLineDouble2(pt1F, pt0F, lineutility.CalcDistanceDouble(pt1F, pt2F));
1964                        if (lineutility.CalcDistanceDouble(pt2F, newPt) < LCChannelWith)
1965                            angleTooSmall = true;
1966                    }
1967                    if (angleTooSmall) {
1968                        // Angle is too small to fit channel, make it a single line partition
1969                        nextP.end_Renamed = i - 1;
1970                        partitions.add(nextP);
1971                        nextP = new P1();
1972                        nextP.start = i;
1973                        nextP.end_Renamed=i + 2;
1974                        singleLinePartitions.add(nextP);
1975                        i++;
1976                        nextP = new P1();
1977                        nextP.start = i + 1;
1978                    }
1979                } else if(degrees < 90) {
1980                    // new Partition
1981                    nextP.end_Renamed = i;
1982                    partitions.add(nextP);
1983                    nextP = new P1();
1984                    nextP.start = i + 1;
1985                }
1986                angles[i] = degrees;
1987            } //end for
1988            nextP.end_Renamed = numPoints - 2;
1989            partitions.add(nextP);
1990        } catch (Exception exc) {
1991            ErrorLogger.LogException(_className, "GetLCPartitions",
1992                    new RendererException("Failed inside GetLCPartitions", exc));
1993        }
1994    }
1995
1996    /**
1997     * Sets the color for the current shape depending on the affiliation
1998     * @param tg
1999     * @param shape
2000     */
2001    protected static void SetLCColor(TGLight tg, Shape2 shape) {
2002        try {
2003            String affiliation = tg.get_Affiliation();
2004            if (affiliation !=null && affiliation.equals("H")) {
2005                if (shape.getLineColor() == Color.RED) {
2006                    shape.setLineColor(tg.get_LineColor());
2007                } else {
2008                    shape.setLineColor(Color.RED);
2009                }
2010            } else {
2011                if (shape.getLineColor() != Color.RED) {
2012                    shape.setLineColor(tg.get_LineColor());
2013                } else {
2014                    shape.setLineColor(Color.RED);
2015                }
2016            }
2017
2018        } catch (Exception exc) {
2019            //WriteFile("Error in clsUtility.SetLCColor");
2020            ErrorLogger.LogException(_className, "SetLCColor",
2021                    new RendererException("Failed inside SetLCColor", exc));
2022        }
2023    }
2024    /**
2025     * USAS requires a left-right orientation for ENY, which negates the upper-lower
2026     * orientation we used for Mil-Std-2525 ENY compliance. Therefore we must reverse
2027     * the client points for two of the quadrants
2028     * @param tg tactical graphic
2029     */
2030    public static void ReverseUSASLCPointsByQuadrant(TGLight tg)
2031    {
2032        try
2033        {
2034            if(tg.Pixels.size()<2)
2035                return;
2036            int quadrant=lineutility.GetQuadrantDouble(tg.Pixels.get(0), tg.Pixels.get(1));
2037            switch(tg.get_LineType())
2038            {
2039                case TacticalLines.LC:
2040                case TacticalLines.LC2:
2041                    if(tg.get_Affiliation()!=null && tg.get_Affiliation().equals("H"))
2042                    {
2043                        switch(quadrant)
2044                        {
2045                            case 2:
2046                            case 3:
2047                                break;
2048                            case 1://reverse the points for these two quadrants
2049                            case 4:
2050                                int n=tg.Pixels.size();
2051                                ArrayList<POINT2> pts2=(ArrayList<POINT2>)tg.Pixels.clone();
2052                                        //for(int j=0;j<tg.Pixels.size();j++)
2053                                        for(int j=0;j<n;j++)
2054                                            tg.Pixels.set(j, pts2.get(n-j-1));
2055                                break;
2056                        }//end switch quadrant
2057                    }//end if
2058                    else
2059                    {
2060                        switch(quadrant)
2061                        {
2062                            case 1:
2063                            case 4:
2064                                break;
2065                            case 2://reverse the points for these two quadrants
2066                            case 3:
2067                                int n=tg.Pixels.size();
2068                                ArrayList<POINT2> pts2=(ArrayList<POINT2>)tg.Pixels.clone();
2069                                        //for(int j=0;j<tg.Pixels.size();j++)
2070                                        for(int j=0;j<n;j++)
2071                                            tg.Pixels.set(j, pts2.get(n-j-1));
2072                                break;
2073                        }//end switch quadrant
2074                    }//end else
2075                default:
2076                    break;
2077            }//end switch linetype
2078        }
2079        catch (Exception exc) {
2080            //WriteFile("Error in clsUtility.SetLCColor");
2081            ErrorLogger.LogException(_className, "ReverseUSASLCPointsByQuadrant",
2082                    new RendererException("Failed inside ReverseUSASLCPointsByQuadrant", exc));
2083        }
2084    }//end ReverseUSASLCPointsByQuadrant
2085    /**
2086     * 
2087     * @param tg tactical graphic
2088     * @param bi buffered image to use for creating a graphics object to draw
2089     * @return ShapeInfo hatch fill
2090     */
2091    public static Shape2 getHatchShape(TGLight tg,
2092            BufferedImage bi)
2093    {
2094        Shape2 shape=null;
2095        try
2096        {
2097            if(tg.get_UseHatchFill())
2098                return null;
2099            switch(tg.get_LineType())
2100            {
2101                case TacticalLines.OBSAREA:
2102                    break;
2103                default:
2104                    return null;
2105            }
2106            shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
2107            shape.moveTo(tg.Pixels.get(0));
2108            int j=0;
2109            int n=tg.Pixels.size();
2110            //for(j=1;j<tg.Pixels.size();j++)
2111            for(j=1;j<n;j++)
2112            {
2113                shape.lineTo(tg.Pixels.get(j));
2114            }
2115            shape.setLineColor(new Color(0,0,0,0));
2116            shape.set_Fillstyle(3);
2117
2118            Rectangle2D.Double rect = null;
2119            Graphics2D grid = null;
2120            TexturePaint tp = tg.get_TexturePaint();
2121
2122            rect = new Rectangle2D.Double(0, 0, 8, 8);
2123            grid = bi.createGraphics();
2124            grid.setColor(clsUtility.GetOpaqueColor(tg.get_LineColor()));
2125
2126            grid.setStroke(new BasicStroke(2));
2127            grid.drawLine(0, 8, 8, 0);
2128            tp = new TexturePaint(bi, rect);
2129            shape.setTexturePaint(tp);
2130            shape.setFillColor(new Color(0,0,0,0));
2131            grid.dispose();
2132        }
2133        catch (Exception exc)
2134        {
2135            ErrorLogger.LogException(_className ,"GetHatchShape",
2136                new RendererException("Failed inside GetHatchShape", exc));
2137        }
2138        return shape;
2139    }
2140    /**
2141     * initialize the hash tables
2142     * @param rev Mil-Standard-2525 revision 
2143     */
2144    public static synchronized void initializeLinetypes(int rev)
2145    {
2146        try
2147        {
2148            if(linetypes != null || metocs != null)
2149                return;
2150            
2151            linetypes=new HashMap<String,Object>();
2152            
2153            //basic shapes
2154            linetypes.put("BS_LINE--------", TacticalLines.BS_LINE);
2155            linetypes.put("BS_AREA--------", TacticalLines.BS_AREA);
2156            linetypes.put("BS_CROSS-------", TacticalLines.BS_CROSS);
2157            linetypes.put("BS_ELLIPSE-----", TacticalLines.BS_ELLIPSE);
2158            linetypes.put("PBS_ELLIPSE----", TacticalLines.PBS_ELLIPSE);
2159            linetypes.put("PBS_CIRCLE-----", TacticalLines.PBS_CIRCLE);
2160            linetypes.put("BS_RECTANGLE---", TacticalLines.BS_RECTANGLE);
2161            linetypes.put("PBS_RECTANGLE--", TacticalLines.PBS_RECTANGLE);
2162            linetypes.put("PBS_SQUARE-----", TacticalLines.PBS_SQUARE);
2163            //end basic shapes
2164            
2165            //buffered shapes
2166            linetypes.put("BBS_LINE-------", TacticalLines.BBS_LINE);
2167            linetypes.put("BBS_AREA-------", TacticalLines.BBS_AREA);
2168            linetypes.put("BBS_POINT------", TacticalLines.BBS_POINT);
2169            linetypes.put("BBS_RECTANGLE--", TacticalLines.BBS_RECTANGLE);
2170            linetypes.put("BS_BBOX--------", TacticalLines.BS_BBOX);
2171            //end basic shapes
2172            
2173            linetypes.put("G*MPOHO---****X", TacticalLines.OVERHEAD_WIRE);
2174            
2175            //Tasks
2176            linetypes.put("G*TPB-----****X", TacticalLines.BLOCK);
2177            linetypes.put("G*TPH-----****X", TacticalLines.BREACH);
2178            linetypes.put("G*TPY-----****X", TacticalLines.BYPASS);
2179            linetypes.put("G*TPC-----****X", TacticalLines.CANALIZE);
2180            linetypes.put("G*TPX-----****X", TacticalLines.CLEAR);
2181            linetypes.put("G*TPJ-----****X", TacticalLines.CONTAIN);
2182            linetypes.put("G*TPK-----****X", TacticalLines.CATK);
2183            linetypes.put("G*TPKF----****X", TacticalLines.CATKBYFIRE);
2184            linetypes.put("G*TPL-----****X", TacticalLines.DELAY);
2185            linetypes.put("G*TPT-----****X", TacticalLines.DISRUPT);
2186            linetypes.put("G*TPF-----****X", TacticalLines.FIX);
2187            linetypes.put("G*TPA-----****X", TacticalLines.FOLLA);
2188            linetypes.put("G*TPAS----****X", TacticalLines.FOLSP);
2189            linetypes.put("G*TPE-----****X", TacticalLines.ISOLATE);
2190            linetypes.put("G*TPO-----****X", TacticalLines.OCCUPY);
2191            linetypes.put("G*TPP-----****X", TacticalLines.PENETRATE);
2192            linetypes.put("G*TPR-----****X", TacticalLines.RIP);
2193            linetypes.put("G*TPQ-----****X", TacticalLines.RETAIN);
2194            linetypes.put("G*TPM-----****X", TacticalLines.RETIRE);
2195            linetypes.put("G*TPS-----****X", TacticalLines.SECURE);
2196            linetypes.put("G*TPUS----****X", TacticalLines.SCREEN);
2197            linetypes.put("G*TPUC----****X", TacticalLines.COVER);
2198            linetypes.put("G*TPUG----****X", TacticalLines.GUARD);
2199            linetypes.put("G*TPZ-----****X", TacticalLines.SEIZE);
2200            linetypes.put("G*TPW-----****X", TacticalLines.WITHDRAW);
2201            linetypes.put("G*TPWP----****X", TacticalLines.WDRAWUP);
2202            linetypes.put("G*TPV-----****X", TacticalLines.CORDONSEARCH);
2203            linetypes.put("G*TP2-----****X", TacticalLines.CORDONKNOCK);
2204            //end Tasks
2205            //C2GM
2206            linetypes.put("G*GPGLB---****X", TacticalLines.BOUNDARY);
2207            linetypes.put("G*GPGLF---****X", TacticalLines.FLOT);
2208            linetypes.put("G*GPGLC---****X", TacticalLines.LC);
2209            linetypes.put("G*GPGLP---****X", TacticalLines.PL);
2210            linetypes.put("G*GPGLL---****X", TacticalLines.LL);
2211            linetypes.put("G*GPGAG---****X", TacticalLines.GENERAL);
2212            linetypes.put("G*GPGAA---****X", TacticalLines.ASSY);
2213            linetypes.put("G*GPGAE---****X", TacticalLines.EA);
2214            linetypes.put("G*GPGAF---****X", TacticalLines.FORT);
2215            linetypes.put("G*GPGAD---****X", TacticalLines.DZ);
2216            linetypes.put("G*GPGAX---****X", TacticalLines.EZ);
2217            linetypes.put("G*GPGAL---****X", TacticalLines.LZ);
2218            linetypes.put("G*GPGAP---****X", TacticalLines.PZ);
2219            linetypes.put("G*GPGAS---****X", TacticalLines.SARA);
2220            linetypes.put("G*GPGAY---****X", TacticalLines.LAA);
2221            linetypes.put("G*GPGAZ---****X", TacticalLines.AIRFIELD);
2222            linetypes.put("G*GPALC---****X", TacticalLines.AC);
2223            linetypes.put("G*GPALM---****X", TacticalLines.MRR);
2224            linetypes.put("G*GPALS---****X", TacticalLines.SAAFR);
2225            linetypes.put("G*GPALU---****X", TacticalLines.UAV);
2226            linetypes.put("G*GPALL---****X", TacticalLines.LLTR);
2227            linetypes.put("G*GPAAR---****X", TacticalLines.ROZ);
2228            linetypes.put("G*GPAAF---****X", TacticalLines.FAADZ);            
2229            linetypes.put("G*GPAAH---****X", TacticalLines.HIDACZ);
2230            linetypes.put("G*GPAAM---****X", TacticalLines.MEZ);
2231            linetypes.put("G*GPAAML--****X", TacticalLines.LOMEZ);
2232            linetypes.put("G*GPAAMH--****X", TacticalLines.HIMEZ);
2233            linetypes.put("G*GPAAW---****X", TacticalLines.WFZ);
2234            linetypes.put("G*GPPD----****X", TacticalLines.DECEIVE);
2235            linetypes.put("G*GPPA----****X", TacticalLines.AAFNT);
2236            linetypes.put("G*GPPF----****X", TacticalLines.DIRATKFNT);
2237            linetypes.put("G*GPPM----****X", TacticalLines.DMA);
2238            linetypes.put("G*GPPY----****X", TacticalLines.DMAF);
2239            linetypes.put("G*GPPC----****X", TacticalLines.DUMMY);
2240            linetypes.put("G*GPDLF---****X", TacticalLines.FEBA);
2241            linetypes.put("G*GPDLP---****X", TacticalLines.PDF);
2242            linetypes.put("G*GPDAB---****X", TacticalLines.BATTLE);
2243            linetypes.put("G*GPDABP--****X", TacticalLines.PNO);
2244            linetypes.put("G*GPDAE---****X", TacticalLines.EA1);
2245            linetypes.put("G*GPOLAV--****X", TacticalLines.AXAD);
2246            linetypes.put("G*GPOLAA--****X", TacticalLines.AIRAOA);
2247            linetypes.put("G*GPOLAR--****X", TacticalLines.AAAAA);
2248            linetypes.put("G*GPOLAGM-****X", TacticalLines.MAIN);
2249            linetypes.put("G*GPOLAGS-****X", TacticalLines.SPT);
2250            linetypes.put("G*GPOLKA--****X", TacticalLines.DIRATKAIR);
2251            linetypes.put("G*GPOLKGM-****X", TacticalLines.DIRATKGND);
2252            linetypes.put("G*GPOLKGS-****X", TacticalLines.DIRATKSPT);
2253            linetypes.put("G*GPOLF---****X", TacticalLines.FCL);
2254            linetypes.put("G*GPOLI---****X", TacticalLines.IL);
2255            linetypes.put("G*GPOLL---****X", TacticalLines.LOA);
2256            linetypes.put("G*GPOLT---****X", TacticalLines.LOD);
2257            linetypes.put("G*GPOLC---****X", TacticalLines.LDLC);
2258            linetypes.put("G*GPOLP---****X", TacticalLines.PLD);
2259            linetypes.put("G*GPOAA---****X", TacticalLines.ASSAULT);
2260            linetypes.put("G*GPOAK---****X", TacticalLines.ATKPOS);
2261            linetypes.put("G*GPOAF---****X", TacticalLines.ATKBYFIRE);
2262            linetypes.put("G*GPOAS---****X", TacticalLines.SPTBYFIRE);
2263            linetypes.put("G*GPOAO---****X", TacticalLines.OBJ);
2264            linetypes.put("G*GPOAP---****X", TacticalLines.PEN);
2265            linetypes.put("G*GPSLA---****X", TacticalLines.AMBUSH);
2266            linetypes.put("G*GPSLH---****X", TacticalLines.HOLD);
2267            linetypes.put("G*GPSLR---****X", TacticalLines.RELEASE);
2268            linetypes.put("G*GPSLB---****X", TacticalLines.BRDGHD);
2269            //linetypes.put("G*GPSLB---****X", TacticalLines.BRDGHD_GE);    //client ge?
2270            linetypes.put("G*GPSAO---****X", TacticalLines.AO);
2271            linetypes.put("G*GPSAA---****X", TacticalLines.AIRHEAD);
2272            linetypes.put("G*GPSAE---****X", TacticalLines.ENCIRCLE);
2273            linetypes.put("G*GPSAN---****X", TacticalLines.NAI);
2274            linetypes.put("G*GPSAT---****X", TacticalLines.TAI);
2275            
2276            //obstacles
2277            linetypes.put("G*MPOGB---****X", TacticalLines.BELT);
2278            //linetypes.put("G*MPOGB---****X", TacticalLines.BELT1);
2279            linetypes.put("G*MPOGL---****X", TacticalLines.LINE);
2280            linetypes.put("G*MPOGZ---****X", TacticalLines.ZONE);
2281            linetypes.put("G*MPOGF---****X", TacticalLines.OBSFAREA);
2282            linetypes.put("G*MPOGR---****X", TacticalLines.OBSAREA);
2283            linetypes.put("G*MPOS----****X", TacticalLines.ABATIS);
2284            linetypes.put("G*MPOADU--****X", TacticalLines.ATDITCH);
2285            linetypes.put("G*MPOADC--****X", TacticalLines.ATDITCHC);
2286            linetypes.put("G*MPOAR---****X", TacticalLines.ATDITCHM);
2287            linetypes.put("G*MPOAW---****X", TacticalLines.ATWALL);
2288            linetypes.put("G*MPOMC---****X", TacticalLines.CLUSTER);
2289            linetypes.put("G*MPOFD---****X", TacticalLines.DEPICT);
2290            linetypes.put("G*MPOFG---****X", TacticalLines.GAP);
2291            linetypes.put("G*MPOFA---****X", TacticalLines.MINED);
2292            linetypes.put("G*MPOEB---****X", TacticalLines.MNFLDBLK);
2293            linetypes.put("G*MPOEF---****X", TacticalLines.MNFLDFIX);
2294            linetypes.put("G*MPOET---****X", TacticalLines.TURN);
2295            linetypes.put("G*MPOED---****X", TacticalLines.MNFLDDIS);
2296            linetypes.put("G*MPOU----****X", TacticalLines.UXO);
2297            linetypes.put("G*MPORP---****X", TacticalLines.PLANNED);
2298            linetypes.put("G*MPORS---****X", TacticalLines.ESR1);
2299            linetypes.put("G*MPORA---****X", TacticalLines.ESR2);
2300            linetypes.put("G*MPORC---****X", TacticalLines.ROADBLK);
2301            linetypes.put("G*MPOT----****X", TacticalLines.TRIP);
2302            linetypes.put("G*MPOWU---****X", TacticalLines.UNSP);
2303            linetypes.put("G*MPOWS---****X", TacticalLines.SFENCE);
2304            linetypes.put("G*MPOWD---****X", TacticalLines.DFENCE);
2305            linetypes.put("G*MPOWA---****X", TacticalLines.DOUBLEA);
2306            linetypes.put("G*MPOWL---****X", TacticalLines.LWFENCE);
2307            linetypes.put("G*MPOWH---****X", TacticalLines.HWFENCE);
2308            linetypes.put("G*MPOWCS--****X", TacticalLines.SINGLEC);
2309            linetypes.put("G*MPOWCD--****X", TacticalLines.DOUBLEC);
2310            linetypes.put("G*MPOWCT--****X", TacticalLines.TRIPLE);
2311            linetypes.put("G*MPBDE---****X", TacticalLines.EASY);
2312            linetypes.put("G*MPBDD---****X", TacticalLines.BYDIF);
2313            linetypes.put("G*MPBDI---****X", TacticalLines.BYIMP);
2314            linetypes.put("G*MPBCA---****X", TacticalLines.ASLTXING);
2315            linetypes.put("G*MPBCB---****X", TacticalLines.BRIDGE);
2316            linetypes.put("G*MPBCF---****X", TacticalLines.FERRY);
2317            linetypes.put("G*MPBCE---****X", TacticalLines.FORDSITE);
2318            linetypes.put("G*MPBCD---****X", TacticalLines.FORDIF);
2319            linetypes.put("G*MPBCL---****X", TacticalLines.MFLANE);
2320            linetypes.put("G*MPBCR---****X", TacticalLines.RAFT);
2321            linetypes.put("G*MPSL----****X", TacticalLines.FORTL);
2322            linetypes.put("G*MPSW----****X", TacticalLines.FOXHOLE);
2323            linetypes.put("G*MPSP----****X", TacticalLines.STRONG);
2324            linetypes.put("G*MPNM----****X", TacticalLines.MSDZ);
2325            linetypes.put("G*MPNR----****X", TacticalLines.RAD);
2326            linetypes.put("G*MPNB----****X", TacticalLines.BIO);
2327            linetypes.put("G*MPNC----****X", TacticalLines.CHEM);
2328            linetypes.put("G*MPNL----****X", TacticalLines.DRCL);
2329            //fire support
2330            linetypes.put("G*FPLT----****X", TacticalLines.LINTGT);
2331            linetypes.put("G*FPLTS---****X", TacticalLines.LINTGTS);
2332            linetypes.put("G*FPLTF---****X", TacticalLines.FPF);
2333            linetypes.put("G*FPLCF---****X", TacticalLines.FSCL);
2334            linetypes.put("G*FPLCC---****X", TacticalLines.CFL);
2335            linetypes.put("G*FPLCN---****X", TacticalLines.NFL);
2336            linetypes.put("G*FPLCR---****X", TacticalLines.RFL);
2337            linetypes.put("G*FPAT----****X", TacticalLines.AT);
2338            linetypes.put("G*FPATR---****X", TacticalLines.RECTANGULAR);
2339            linetypes.put("G*FPATC---****X", TacticalLines.CIRCULAR);
2340            linetypes.put("G*FPATG---****X", TacticalLines.SERIES);
2341            linetypes.put("G*FPATS---****X", TacticalLines.SMOKE);
2342            linetypes.put("G*FPATB---****X", TacticalLines.BOMB);
2343            linetypes.put("G*FPACSI--****X", TacticalLines.FSA);
2344            linetypes.put("G*FPACSR--****X", TacticalLines.FSA_RECTANGULAR);
2345            linetypes.put("G*FPACSC--****X", TacticalLines.FSA_CIRCULAR);
2346            linetypes.put("G*FPACAI--****X", TacticalLines.ACA);
2347            linetypes.put("G*FPACAR--****X", TacticalLines.ACA_RECTANGULAR);
2348            linetypes.put("G*FPACAC--****X", TacticalLines.ACA_CIRCULAR);
2349            linetypes.put("G*FPACFI--****X", TacticalLines.FFA);
2350            linetypes.put("G*FPACFR--****X", TacticalLines.FFA_RECTANGULAR);
2351            linetypes.put("G*FPACFC--****X", TacticalLines.FFA_CIRCULAR);
2352            linetypes.put("G*FPACNI--****X", TacticalLines.NFA);
2353            linetypes.put("G*FPACNR--****X", TacticalLines.NFA_RECTANGULAR);
2354            linetypes.put("G*FPACNC--****X", TacticalLines.NFA_CIRCULAR);
2355            linetypes.put("G*FPACRI--****X", TacticalLines.RFA);
2356            linetypes.put("G*FPACRR--****X", TacticalLines.RFA_RECTANGULAR);
2357            linetypes.put("G*FPACRC--****X", TacticalLines.RFA_CIRCULAR);
2358            linetypes.put("G*FPACPR--****X", TacticalLines.PAA_RECTANGULAR_REVC);
2359            linetypes.put("G*FPACPC--****X", TacticalLines.PAA_CIRCULAR);
2360            linetypes.put("G*FPAZII--****X", TacticalLines.ATI);
2361            linetypes.put("G*FPAZIR--****X", TacticalLines.ATI_RECTANGULAR);
2362            linetypes.put("G*FPAZIC--****X", TacticalLines.ATI_CIRCULAR);
2363            linetypes.put("G*FPAZXI--****X", TacticalLines.CFFZ);
2364            linetypes.put("G*FPAZXR--****X", TacticalLines.CFFZ_RECTANGULAR);
2365            linetypes.put("G*FPAZXC--****X", TacticalLines.CFFZ_CIRCULAR);
2366            linetypes.put("G*FPAZSI--****X", TacticalLines.SENSOR);
2367            linetypes.put("G*FPAZSR--****X", TacticalLines.SENSOR_RECTANGULAR);
2368            linetypes.put("G*FPAZSC--****X", TacticalLines.SENSOR_CIRCULAR);
2369            linetypes.put("G*FPAZCI--****X", TacticalLines.CENSOR);
2370            linetypes.put("G*FPAZCR--****X", TacticalLines.CENSOR_RECTANGULAR);
2371            linetypes.put("G*FPAZCC--****X", TacticalLines.CENSOR_CIRCULAR);
2372            linetypes.put("G*FPAZDI--****X", TacticalLines.DA);
2373            linetypes.put("G*FPAZDR--****X", TacticalLines.DA_RECTANGULAR);
2374            linetypes.put("G*FPAZDC--****X", TacticalLines.DA_CIRCULAR);
2375            linetypes.put("G*FPAZFI--****X", TacticalLines.CFZ);
2376            linetypes.put("G*FPAZFR--****X", TacticalLines.CFZ_RECTANGULAR);
2377            linetypes.put("G*FPAZFC--****X", TacticalLines.CFZ_CIRCULAR);
2378            linetypes.put("G*FPAZZI--****X", TacticalLines.ZOR);
2379            linetypes.put("G*FPAZZR--****X", TacticalLines.ZOR_RECTANGULAR);
2380            linetypes.put("G*FPAZZC--****X", TacticalLines.ZOR_CIRCULAR);
2381            linetypes.put("G*FPAZBI--****X", TacticalLines.TBA);
2382            linetypes.put("G*FPAZBR--****X", TacticalLines.TBA_RECTANGULAR);
2383            linetypes.put("G*FPAZBC--****X", TacticalLines.TBA_CIRCULAR);
2384            linetypes.put("G*FPAZVI--****X", TacticalLines.TVAR);
2385            linetypes.put("G*FPAKBI--****X", TacticalLines.KILLBOXBLUE);
2386            linetypes.put("G*FPAKBR--****X", TacticalLines.KILLBOXBLUE_RECTANGULAR);
2387            linetypes.put("G*FPAKBC--****X", TacticalLines.KILLBOXBLUE_CIRCULAR);
2388            linetypes.put("G*FPAKPI--****X", TacticalLines.KILLBOXPURPLE);
2389            linetypes.put("G*FPAKPR--****X", TacticalLines.KILLBOXPURPLE_RECTANGULAR);
2390            linetypes.put("G*FPAKPC--****X", TacticalLines.KILLBOXPURPLE_CIRCULAR);
2391            
2392            linetypes.put("G*FPAZVR--****X", TacticalLines.TVAR_RECTANGULAR);
2393            linetypes.put("G*FPAZVC--****X", TacticalLines.TVAR_CIRCULAR);
2394            linetypes.put("G*FPAXC---****X", TacticalLines.RANGE_FAN);
2395            linetypes.put("G*FPAXS---****X", TacticalLines.RANGE_FAN_SECTOR);
2396            //css
2397            linetypes.put("G*SPLCM---****X", TacticalLines.CONVOY);
2398            linetypes.put("G*SPLCH---****X", TacticalLines.HCONVOY);
2399            linetypes.put("G*SPLRM---****X", TacticalLines.MSR);
2400            linetypes.put("G*SPLRA---****X", TacticalLines.ASR);
2401            linetypes.put("G*SPLRO---****X", TacticalLines.ONEWAY);
2402            linetypes.put("G*SPLRT---****X", TacticalLines.ALT);
2403            linetypes.put("G*SPLRW---****X", TacticalLines.TWOWAY);
2404            linetypes.put("G*SPAD----****X", TacticalLines.DHA);
2405            linetypes.put("G*SPAE----****X", TacticalLines.EPW);
2406            linetypes.put("G*SPAR----****X", TacticalLines.FARP);
2407            linetypes.put("G*SPAH----****X", TacticalLines.RHA);
2408            linetypes.put("G*SPASB---****X", TacticalLines.BSA);
2409            linetypes.put("G*SPASD---****X", TacticalLines.DSA);
2410            linetypes.put("G*SPASR---****X", TacticalLines.RSA);
2411            //other
2412            linetypes.put("G*OPHN----****X", TacticalLines.NAVIGATION);
2413            linetypes.put("G*OPB-----****X", TacticalLines.BEARING);
2414            linetypes.put("G*OPBE----****X", TacticalLines.ELECTRO);
2415            linetypes.put("G*OPBA----****X", TacticalLines.ACOUSTIC);
2416            linetypes.put("G*OPBT----****X", TacticalLines.TORPEDO);
2417            linetypes.put("G*OPBO----****X", TacticalLines.OPTICAL);
2418            linetypes.put("GENERIC---****X", TacticalLines.GENERIC);
2419            linetypes.put("G*FPLCM---****X", TacticalLines.MFP);
2420            if(rev==RendererSettings.Symbology_2525C)
2421            {
2422                linetypes.put("G*TPUS----****X", TacticalLines.SCREEN_REVC);
2423                linetypes.put("G*TPUC----****X", TacticalLines.COVER_REVC);
2424                linetypes.put("G*TPUG----****X", TacticalLines.GUARD_REVC);
2425                linetypes.put("G*TPZ-----****X", TacticalLines.SEIZE_REVC);
2426                //linetypes.put("G*GPAAF---****X", TacticalLines.SHORADZ );            
2427                
2428                //modified symbol codes for fire support areas
2429                linetypes.put("G*FPACEI--****X", TacticalLines.SENSOR);
2430                linetypes.put("G*FPACEC--****X", TacticalLines.SENSOR_CIRCULAR);
2431                linetypes.put("G*FPACER--****X", TacticalLines.SENSOR_RECTANGULAR);
2432                linetypes.put("G*FPACDI--****X", TacticalLines.DA);
2433                linetypes.put("G*FPACDC--****X", TacticalLines.DA_CIRCULAR);
2434                linetypes.put("G*FPACDR--****X", TacticalLines.DA_RECTANGULAR);
2435                linetypes.put("G*FPACZI--****X", TacticalLines.ZOR);
2436                linetypes.put("G*FPACZC--****X", TacticalLines.ZOR_CIRCULAR);
2437                linetypes.put("G*FPACZR--****X", TacticalLines.ZOR_RECTANGULAR);
2438                linetypes.put("G*FPACBI--****X", TacticalLines.TBA);
2439                linetypes.put("G*FPACBC--****X", TacticalLines.TBA_CIRCULAR);
2440                linetypes.put("G*FPACBR--****X", TacticalLines.TBA_RECTANGULAR);
2441                linetypes.put("G*FPACVI--****X", TacticalLines.TVAR);
2442                linetypes.put("G*FPACVC--****X", TacticalLines.TVAR_CIRCULAR);
2443                linetypes.put("G*FPACVR--****X", TacticalLines.TVAR_RECTANGULAR);
2444                
2445                //MFP added
2446                linetypes.put("G*FPACT---****X", TacticalLines.TGMF);
2447            }
2448                        
2449            //METOCs
2450            metocs=new HashMap<String,Object>();
2451            metocs.put("WA-DPFC----L---",TacticalLines.CF);
2452            metocs.put("WA-DPFCU---L---",TacticalLines.UCF);
2453            metocs.put("WA-DPFC-FG-L---",TacticalLines.CFG);
2454            metocs.put("WA-DPFC-FY-L---",TacticalLines.CFY);
2455            metocs.put("WA-DPFW----L---",TacticalLines.WF);
2456            metocs.put("WA-DPFWU---L---",TacticalLines.UWF);
2457            metocs.put("WA-DPFW-FG-L---",TacticalLines.WFG);
2458            metocs.put("WA-DPFW-FY-L---",TacticalLines.WFY);
2459            metocs.put("WA-DPFO----L---",TacticalLines.OCCLUDED);
2460            metocs.put("WA-DPFOU---L---",TacticalLines.UOF);
2461            metocs.put("WA-DPFO-FY-L---",TacticalLines.OFY);
2462            metocs.put("WA-DPFS----L---",TacticalLines.SF);
2463            metocs.put("WA-DPFSU---L---",TacticalLines.USF);
2464            metocs.put("WA-DPFS-FG-L---",TacticalLines.SFG);
2465            metocs.put("WA-DPFS-FY-L---",TacticalLines.SFY);
2466            metocs.put("WA-DPXT----L---",TacticalLines.TROUGH);
2467            metocs.put("WA-DPXR----L---",TacticalLines.RIDGE);
2468            metocs.put("WA-DPXSQ---L---",TacticalLines.SQUALL);
2469            metocs.put("WA-DPXIL---L---",TacticalLines.INSTABILITY);
2470            metocs.put("WA-DPXSH---L---",TacticalLines.SHEAR);
2471            metocs.put("WA-DPXITCZ-L---",TacticalLines.ITC);
2472            metocs.put("WA-DPXCV---L---",TacticalLines.CONVERGANCE);
2473            metocs.put("WA-DPXITD--L---",TacticalLines.ITD);
2474            
2475            metocs.put("WA-DWJ-----L---",TacticalLines.JET);
2476            metocs.put("WA-DWS-----L---",TacticalLines.STREAM);
2477            
2478            metocs.put("WA-DBAIF----A--",TacticalLines.IFR);
2479            metocs.put("WA-DBAMV----A--",TacticalLines.MVFR);
2480            metocs.put("WA-DBATB----A--",TacticalLines.TURBULENCE);
2481            metocs.put("WA-DBAI-----A--",TacticalLines.ICING);
2482            metocs.put("WA-DBALPNC--A--",TacticalLines.NON_CONVECTIVE);
2483            metocs.put("WA-DBALPC---A--",TacticalLines.CONVECTIVE);
2484            metocs.put("WA-DBAFP----A--",TacticalLines.FROZEN);
2485            metocs.put("WA-DBAT-----A--",TacticalLines.THUNDERSTORMS);
2486            metocs.put("WA-DBAFG----A--",TacticalLines.FOG);
2487            metocs.put("WA-DBAD-----A--",TacticalLines.SAND);
2488            metocs.put("WA-DBAFF----A--",TacticalLines.FREEFORM);
2489            
2490            metocs.put("WA-DIPIB---L---",TacticalLines.ISOBAR);
2491            metocs.put("WA-DIPCO---L---",TacticalLines.UPPER_AIR);
2492            metocs.put("WA-DIPIS---L---",TacticalLines.ISOTHERM);
2493            metocs.put("WA-DIPIT---L---",TacticalLines.ISOTACH);
2494            metocs.put("WA-DIPID---L---",TacticalLines.ISODROSOTHERM);
2495            metocs.put("WA-DIPTH---L---",TacticalLines.ISOPLETHS);
2496            metocs.put("WA-DIPFF---L---",TacticalLines.OPERATOR_FREEFORM);
2497            metocs.put("WO-DHHDB---L---",TacticalLines.BREAKERS);
2498            
2499            metocs.put("WO-DIDID---L---",TacticalLines.ICE_DRIFT);
2500            metocs.put("WO-DILOV---L---",TacticalLines.LVO);
2501            metocs.put("WO-DILUC---L---",TacticalLines.UNDERCAST);
2502            metocs.put("WO-DILOR---L---",TacticalLines.LRO);
2503            metocs.put("WO-DILIEO--L---",TacticalLines.ICE_EDGE);
2504            metocs.put("WO-DILIEE--L---",TacticalLines.ESTIMATED_ICE_EDGE);
2505            metocs.put("WO-DILIER--L---",TacticalLines.ICE_EDGE_RADAR);
2506            metocs.put("WO-DIOC----L---",TacticalLines.CRACKS);
2507            metocs.put("WO-DIOCS---L---",TacticalLines.CRACKS_SPECIFIC_LOCATION);
2508            metocs.put("WO-DIOL----L---",TacticalLines.ICE_OPENINGS_LEAD);
2509            metocs.put("WO-DIOLF---L---",TacticalLines.ICE_OPENINGS_FROZEN);
2510            metocs.put("WO-DHDDL---L---",TacticalLines.DEPTH_CURVE);
2511            metocs.put("WO-DHDDC---L---",TacticalLines.DEPTH_CONTOUR);
2512            metocs.put("WO-DHDDA----A--",TacticalLines.DEPTH_AREA);
2513            metocs.put("WO-DHCC----L---",TacticalLines.COASTLINE);
2514            metocs.put("WO-DHCI-----A--",TacticalLines.ISLAND);
2515            metocs.put("WO-DHCB-----A--",TacticalLines.BEACH);
2516            metocs.put("WO-DHCW-----A--",TacticalLines.WATER);
2517            metocs.put("WO-DHCF----L---",TacticalLines.FORESHORE_LINE);
2518            metocs.put("WO-DHCF-----A--",TacticalLines.FORESHORE_AREA);
2519            metocs.put("WO-DHPBA---L---",TacticalLines.ANCHORAGE_LINE);
2520            metocs.put("WO-DHPBA----A--",TacticalLines.ANCHORAGE_AREA);
2521            metocs.put("WO-DHPBP---L---",TacticalLines.PIER);
2522            metocs.put("WOS-HPFF----A--",TacticalLines.WEIRS);
2523            metocs.put("WO-DHPMD----A--",TacticalLines.DRYDOCK);
2524            metocs.put("WO-DHPMO---L---",TacticalLines.LOADING_FACILITY_LINE);
2525            metocs.put("WO-DHPMO----A--",TacticalLines.LOADING_FACILITY_AREA);
2526            metocs.put("WO-DHPMRA--L---",TacticalLines.RAMP_ABOVE_WATER);
2527            metocs.put("WO-DHPMRB--L---",TacticalLines.RAMP_BELOW_WATER);
2528            metocs.put("WO-DHPSPA--L---",TacticalLines.JETTY_ABOVE_WATER);
2529            metocs.put("WO-DHPSPB--L---",TacticalLines.JETTY_BELOW_WATER);
2530            metocs.put("WO-DHPSPS--L---",TacticalLines.SEAWALL);
2531            metocs.put("WO-DHABP----A--",TacticalLines.PERCHES);
2532            metocs.put("WO-DHALLA--L---",TacticalLines.LEADING_LINE);
2533            metocs.put("WO-DHHD-----A--",TacticalLines.UNDERWATER_HAZARD);
2534            metocs.put("WO-DHHDF----A--",TacticalLines.FOUL_GROUND);
2535            metocs.put("WO-DHHDK----A--",TacticalLines.KELP);
2536            metocs.put("WOS-HHDR---L---",TacticalLines.REEF);
2537            metocs.put("WO-DHHDD----A--",TacticalLines.DISCOLORED_WATER);
2538            metocs.put("WO-DTCCCFE-L---",TacticalLines.EBB_TIDE);
2539            metocs.put("WO-DTCCCFF-L---",TacticalLines.FLOOD_TIDE);
2540            
2541            metocs.put("WO-DOBVA----A--",TacticalLines.VDR_LEVEL_12);
2542            metocs.put("WO-DOBVB----A--",TacticalLines.VDR_LEVEL_23);
2543            metocs.put("WO-DOBVC----A--",TacticalLines.VDR_LEVEL_34);
2544            metocs.put("WO-DOBVD----A--",TacticalLines.VDR_LEVEL_45);
2545            metocs.put("WO-DOBVE----A--",TacticalLines.VDR_LEVEL_56);
2546            metocs.put("WO-DOBVF----A--",TacticalLines.VDR_LEVEL_67);
2547            metocs.put("WO-DOBVG----A--",TacticalLines.VDR_LEVEL_78);
2548            metocs.put("WO-DOBVH----A--",TacticalLines.VDR_LEVEL_89);
2549            metocs.put("WO-DOBVI----A--",TacticalLines.VDR_LEVEL_910);
2550            
2551            metocs.put("WO-DBSF-----A--",TacticalLines.BEACH_SLOPE_FLAT);
2552            metocs.put("WO-DBSG-----A--",TacticalLines.BEACH_SLOPE_GENTLE);
2553            metocs.put("WO-DBSM-----A--",TacticalLines.BEACH_SLOPE_MODERATE);
2554            metocs.put("WO-DBST-----A--",TacticalLines.BEACH_SLOPE_STEEP);
2555            
2556            metocs.put("WO-DGMSR----A--",TacticalLines.SOLID_ROCK);
2557            metocs.put("WO-DGMSC----A--",TacticalLines.CLAY);
2558            metocs.put("WO-DGMSSVS--A--",TacticalLines.VERY_COARSE_SAND);
2559            metocs.put("WO-DGMSSC---A--",TacticalLines.COARSE_SAND);
2560            metocs.put("WO-DGMSSM---A--",TacticalLines.MEDIUM_SAND);
2561            metocs.put("WO-DGMSSF---A--",TacticalLines.FINE_SAND);
2562            metocs.put("WO-DGMSSVF--A--",TacticalLines.VERY_FINE_SAND);
2563            metocs.put("WO-DGMSIVF--A--",TacticalLines.VERY_FINE_SILT);
2564            metocs.put("WO-DGMSIF---A--",TacticalLines.FINE_SILT);
2565            metocs.put("WO-DGMSIM---A--",TacticalLines.MEDIUM_SILT);
2566            metocs.put("WO-DGMSIC---A--",TacticalLines.COARSE_SILT);
2567            metocs.put("WO-DGMSB----A--",TacticalLines.BOULDERS);
2568            metocs.put("WO-DGMS-CO--A--",TacticalLines.OYSTER_SHELLS);
2569            metocs.put("WO-DGMS-PH--A--",TacticalLines.PEBBLES);
2570            metocs.put("WO-DGMS-SH--A--",TacticalLines.SAND_AND_SHELLS);
2571            metocs.put("WO-DGML-----A--",TacticalLines.BOTTOM_SEDIMENTS_LAND);
2572            metocs.put("WO-DGMN-----A--",TacticalLines.BOTTOM_SEDIMENTS_NO_DATA);
2573            metocs.put("WO-DGMRS----A--",TacticalLines.BOTTOM_ROUGHNESS_SMOOTH);
2574            metocs.put("WO-DGMRM----A--",TacticalLines.BOTTOM_ROUGHNESS_MODERATE);
2575            metocs.put("WO-DGMRR----A--",TacticalLines.BOTTOM_ROUGHNESS_ROUGH);
2576            
2577            metocs.put("WO-DGMCL----A--",TacticalLines.CLUTTER_LOW);
2578            metocs.put("WO-DGMCM----A--",TacticalLines.CLUTTER_MEDIUM);
2579            metocs.put("WO-DGMCH----A--",TacticalLines.CLUTTER_HIGH);
2580            
2581            metocs.put("WO-DGMIBA---A--",TacticalLines.IMPACT_BURIAL_0);
2582            metocs.put("WO-DGMIBB---A--",TacticalLines.IMPACT_BURIAL_10);
2583            metocs.put("WO-DGMIBC---A--",TacticalLines.IMPACT_BURIAL_20);
2584            metocs.put("WO-DGMIBD---A--",TacticalLines.IMPACT_BURIAL_75);
2585            metocs.put("WO-DGMIBE---A--",TacticalLines.IMPACT_BURIAL_100);
2586            
2587            metocs.put("WO-DGMBCA---A--",TacticalLines.BOTTOM_CATEGORY_A);
2588            metocs.put("WO-DGMBCB---A--",TacticalLines.BOTTOM_CATEGORY_B);
2589            metocs.put("WO-DGMBCC---A--",TacticalLines.BOTTOM_CATEGORY_C);
2590            
2591            metocs.put("WO-DGMBTA---A--",TacticalLines.BOTTOM_TYPE_A1);
2592            metocs.put("WO-DGMBTB---A--",TacticalLines.BOTTOM_TYPE_A2);
2593            metocs.put("WO-DGMBTC---A--",TacticalLines.BOTTOM_TYPE_A3);
2594            metocs.put("WO-DGMBTD---A--",TacticalLines.BOTTOM_TYPE_B1);
2595            metocs.put("WO-DGMBTE---A--",TacticalLines.BOTTOM_TYPE_B2);
2596            metocs.put("WO-DGMBTF---A--",TacticalLines.BOTTOM_TYPE_B3);
2597            metocs.put("WO-DGMBTG---A--",TacticalLines.BOTTOM_TYPE_C1);
2598            metocs.put("WO-DGMBTH---A--",TacticalLines.BOTTOM_TYPE_C2);
2599            metocs.put("WO-DGMBTI---A--",TacticalLines.BOTTOM_TYPE_C3);
2600            
2601            metocs.put("WO-DL-ML---L---",TacticalLines.MARITIME_LIMIT);
2602            metocs.put("WO-DL-MA----A--",TacticalLines.MARITIME_AREA);
2603            metocs.put("WO-DL-RA---L---",TacticalLines.RESTRICTED_AREA);
2604            metocs.put("WO-DL-SA----A--",TacticalLines.SWEPT_AREA);
2605            metocs.put("WO-DL-TA----A--",TacticalLines.TRAINING_AREA);
2606            metocs.put("WO-DL-O-----A--",TacticalLines.OPERATOR_DEFINED);
2607            metocs.put("WO-DMCA----L---",TacticalLines.CABLE);
2608            metocs.put("WO-DMCC-----A--",TacticalLines.SUBMERGED_CRIB);
2609            metocs.put("WO-DMCD----L---",TacticalLines.CANAL);
2610            metocs.put("WO-DMOA-----A--",TacticalLines.OIL_RIG_FIELD);
2611            metocs.put("WO-DMPA----L---",TacticalLines.PIPE);
2612        }   
2613        catch (Exception exc)
2614        {
2615            ErrorLogger.LogException(_className ,"initializeLinetypes",
2616                new RendererException("Failed inside initializeLinetypes", exc));
2617        }
2618    }
2619    /**
2620     * use str if tg is null
2621     * @param tg tactical graphic
2622     * @param str Mil=Standard-2525 symbol id
2623     * @return line type
2624     */
2625    public static int GetLinetypeFromString(String str)
2626    {
2627        int result=-1;
2628        try
2629        {
2630            String strLine=str;
2631            String strMask=strLine.substring(0,1)+"*"+strLine.substring(2,3)+"P"+strLine.substring(4, 10)+"****X";            
2632            if(str.equalsIgnoreCase("GENERIC---****X"))
2633            {
2634                strMask=str;
2635            }
2636            else if(str.equalsIgnoreCase("BS_LINE--------"))
2637            {
2638                strMask=str;
2639            }
2640            else if(str.equalsIgnoreCase("BBS_LINE-------"))
2641            {
2642                strMask=str;
2643            }
2644            else if(str.equalsIgnoreCase("BS_AREA--------"))
2645            {
2646                strMask=str;
2647            }
2648            else if(str.equalsIgnoreCase("BBS_AREA-------"))
2649            {
2650                strMask=str;
2651            }
2652            else if(str.equalsIgnoreCase("BS_CROSS-------"))
2653            {
2654                strMask=str;
2655            }
2656            else if(str.equalsIgnoreCase("BBS_POINT------"))
2657            {
2658                strMask=str;
2659            }
2660            else if(str.equalsIgnoreCase("BS_ELLIPSE-----"))
2661            {
2662                strMask=str;
2663            }
2664            else if(str.equalsIgnoreCase("PBS_ELLIPSE----"))
2665            {
2666                strMask=str;
2667            }
2668            else if(str.equalsIgnoreCase("PBS_CIRCLE-----"))
2669            {
2670                strMask=str;
2671            }
2672            else if(str.equalsIgnoreCase("BS_RECTANGLE---"))
2673            {
2674                strMask=str;
2675            }
2676            else if(str.equalsIgnoreCase("PBS_RECTANGLE--"))
2677            {
2678                strMask=str;
2679            }
2680            else if(str.equalsIgnoreCase("PBS_SQUARE-----"))
2681            {
2682                strMask=str;
2683            }
2684            else if(str.equalsIgnoreCase("BBS_RECTANGLE--"))
2685            {
2686                strMask=str;
2687            }
2688            else if(str.equalsIgnoreCase("BS_BBOX--------"))
2689            {
2690                strMask=str;
2691            }
2692            
2693            Object objResult=null;
2694            if(linetypes != null && metocs != null)
2695            {
2696                objResult=linetypes.get(strMask);
2697                if(objResult != null)
2698                    return (Integer)objResult;
2699                
2700                objResult=metocs.get(strLine);
2701                if(objResult != null)
2702                    return (Integer)objResult;
2703            }            
2704        }
2705        catch (Exception exc) {
2706            ErrorLogger.LogException(_className ,"CGetLinetypeFromString2",
2707                    new RendererException("Failed inside CGetLinetypeFromString2", exc));
2708        }
2709        return result;
2710    }
2711    /**
2712     * Rev C requires max 50 anchor points for the axis of advance symbols
2713     * 
2714     * @param tg tactical graphic
2715     */
2716    public static void setRevC(TGLight tg)
2717    {
2718        try
2719        {
2720            //if(tg.getSymbologyStandard()!=RendererSettings.Symbology_2525C)
2721                //return;
2722            
2723            int rev=tg.getSymbologyStandard();
2724            if(rev==RendererSettings.Symbology_2525B)
2725            {
2726                switch(tg.get_LineType())
2727                {
2728                    case TacticalLines.MRR:
2729                        //if(tg.Pixels.size()>2)                        
2730                            tg.set_LineType(TacticalLines.MRR_USAS);                        
2731                        return;
2732                    case TacticalLines.UAV:
2733                        //if(tg.Pixels.size()>2)                        
2734                            tg.set_LineType(TacticalLines.UAV_USAS);                        
2735                        return;
2736                    default:
2737                        return;
2738                }
2739            }
2740            //should be rev C at this point
2741            if(rev==RendererSettings.Symbology_2525C)
2742            {
2743                switch(tg.get_LineType())
2744                {
2745                    case TacticalLines.SCREEN:
2746                        if(tg.Pixels.size()==4)
2747                            tg.set_LineType(TacticalLines.SCREEN_REVC);
2748                        break;
2749                    case TacticalLines.GUARD:
2750                        if(tg.Pixels.size()==4)
2751                            tg.set_LineType(TacticalLines.GUARD_REVC);
2752                        break;
2753                    case TacticalLines.COVER:
2754                        if(tg.Pixels.size()==4)
2755                            tg.set_LineType(TacticalLines.COVER_REVC);
2756                        break;
2757                    case TacticalLines.SEIZE:                    
2758                        if(tg.Pixels.size()==4)
2759                            tg.set_LineType(TacticalLines.SEIZE_REVC);
2760                        break;
2761                    case TacticalLines.PAA_RECTANGULAR:                    
2762                        tg.set_LineType(TacticalLines.PAA_RECTANGULAR_REVC);
2763                        break;
2764                    default:
2765                        break;
2766                }
2767            }
2768            switch(tg.get_LineType())
2769            {
2770                case TacticalLines.SCREEN_REVC:
2771                    if(tg.Pixels.size()<4)
2772                        tg.set_LineType(TacticalLines.SCREEN);
2773                    break;
2774                case TacticalLines.GUARD_REVC:
2775                    if(tg.Pixels.size()<4)
2776                        tg.set_LineType(TacticalLines.GUARD);
2777                    break;
2778                case TacticalLines.COVER_REVC:
2779                    if(tg.Pixels.size()<4)
2780                        tg.set_LineType(TacticalLines.COVER);
2781                    break;
2782                case TacticalLines.SEIZE_REVC:                    
2783                    if(tg.Pixels.size()<4)
2784                        tg.set_LineType(TacticalLines.SEIZE);
2785                    break;
2786                default:
2787                    break;
2788            }//end switch            
2789        }//end try
2790        catch (Exception exc) 
2791        {
2792            ErrorLogger.LogException(_className ,"setRevC",
2793                    new RendererException("Failed inside setRevC", exc));
2794        }
2795    }
2796    /**
2797     * 
2798     * @param tg tactical graphic
2799     * @return true if auto-shape
2800     */
2801    public static boolean isAutoshape(TGLight tg)
2802    {
2803        try
2804        {
2805            int linetype=tg.get_LineType();
2806            switch(linetype)
2807            {
2808                case TacticalLines.BS_ELLIPSE:
2809                case TacticalLines.PBS_ELLIPSE:
2810                case TacticalLines.PBS_CIRCLE:
2811                case TacticalLines.BS_RECTANGLE:
2812                case TacticalLines.BBS_RECTANGLE:
2813                case TacticalLines.BBS_POINT:
2814                case TacticalLines.BS_CROSS:
2815                case TacticalLines.BS_BBOX:
2816                //the Tasks
2817                case TacticalLines.CORDONKNOCK:
2818                case TacticalLines.CORDONSEARCH:
2819                case TacticalLines.BLOCK:
2820                case TacticalLines.BREACH:
2821                case TacticalLines.BYPASS:
2822                case TacticalLines.CANALIZE:
2823                case TacticalLines.CLEAR:
2824                case TacticalLines.CONTAIN:
2825                case TacticalLines.DELAY:
2826                case TacticalLines.DISRUPT:
2827                case TacticalLines.FIX:
2828                case TacticalLines.FOLLA:
2829                case TacticalLines.FOLSP:
2830                case TacticalLines.ISOLATE:
2831                case TacticalLines.OCCUPY:
2832                case TacticalLines.PENETRATE:
2833                case TacticalLines.RIP:
2834                case TacticalLines.RETAIN:
2835                case TacticalLines.RETIRE:
2836                case TacticalLines.SECURE:
2837                case TacticalLines.SCREEN:
2838                case TacticalLines.COVER:
2839                case TacticalLines.GUARD:
2840                case TacticalLines.SCREEN_REVC:
2841                case TacticalLines.COVER_REVC:
2842                case TacticalLines.GUARD_REVC:
2843                case TacticalLines.SEIZE:
2844                case TacticalLines.SEIZE_REVC:
2845                case TacticalLines.WITHDRAW:
2846                case TacticalLines.WDRAWUP:
2847                //autoshapes which are not Tasks
2848                case TacticalLines.SARA:
2849                case TacticalLines.AC:
2850                case TacticalLines.MRR:
2851                case TacticalLines.SAAFR:
2852                case TacticalLines.LLTR:
2853                case TacticalLines.UAV:
2854                case TacticalLines.DECEIVE:
2855                case TacticalLines.PDF:
2856                case TacticalLines.IL:
2857                case TacticalLines.ATKBYFIRE:
2858                case TacticalLines.SPTBYFIRE:
2859                case TacticalLines.AMBUSH:
2860                case TacticalLines.CLUSTER:
2861                case TacticalLines.GAP:
2862                case TacticalLines.MNFLDBLK:
2863                case TacticalLines.MNFLDFIX:
2864                case TacticalLines.MNFLDDIS:
2865                case TacticalLines.TURN:
2866                case TacticalLines.PLANNED:
2867                case TacticalLines.ROADBLK:
2868                case TacticalLines.ESR1:
2869                case TacticalLines.ESR2:
2870                case TacticalLines.TRIP:
2871                case TacticalLines.EASY:
2872                case TacticalLines.BYDIF:
2873                case TacticalLines.BYIMP:
2874                case TacticalLines.ASLTXING:
2875                case TacticalLines.BRIDGE:
2876                case TacticalLines.FERRY:
2877                case TacticalLines.FORDSITE:
2878                case TacticalLines.FORDIF:
2879                case TacticalLines.MFLANE:
2880                case TacticalLines.RAFT:
2881                case TacticalLines.FOXHOLE:
2882                case TacticalLines.MSDZ:
2883                case TacticalLines.CONVOY:
2884                case TacticalLines.HCONVOY:
2885                case TacticalLines.LINTGT:
2886                case TacticalLines.LINTGTS:
2887                case TacticalLines.FPF:
2888                case TacticalLines.BEARING:
2889                case TacticalLines.ACOUSTIC:
2890                case TacticalLines.ELECTRO:
2891                case TacticalLines.OPTICAL:
2892                case TacticalLines.TORPEDO:
2893                    return true;
2894            }
2895
2896        }
2897        catch (Exception exc)
2898        {
2899            ErrorLogger.LogException(_className, "isAutoshape",
2900                    new RendererException("Failed inside isAutoshape", exc));
2901        }
2902        return false;
2903    }
2904    /**
2905     * Client will send the segment colors within a modifier.
2906     * Format is 0:FFBBBB,4:FFAAAA,...
2907     * For the time being will assume the modifier being used is the H modifier
2908     * @param tg
2909     * @return 
2910     */
2911    public static HashMap<Integer,Color> getMSRSegmentColors(TGLight tg)
2912    {
2913        HashMap hMap=null;
2914        try
2915        {
2916            int linetype=tg.get_LineType();
2917            switch(linetype)
2918            {
2919                case TacticalLines.MSR:
2920                case TacticalLines.ASR:
2921                case TacticalLines.BOUNDARY:
2922                    if(tg.get_H()==null || tg.get_H().isEmpty())
2923                        return null;
2924                    hMap=new HashMap<Integer,Color>();
2925                    break;
2926                default:
2927                    return null;
2928            }
2929            String[]colorStrs=tg.get_H().split(",");
2930            int j=0,numSegs=colorStrs.length;
2931            String segPlusColor="";
2932            String[]seg=null;     
2933            Color color=null;
2934            int index=-1;
2935            for(j=0;j<numSegs;j++)
2936            {
2937                segPlusColor=colorStrs[j];
2938                if(!segPlusColor.contains(":"))
2939                    continue;
2940                seg=segPlusColor.split(":");
2941                color=SymbolUtilities.getColorFromHexString(seg[1]);
2942                index=Integer.parseInt(seg[0]);
2943                hMap.put(index, color);
2944            }
2945        }
2946        catch (Exception exc)
2947        {
2948            ErrorLogger.LogException(_className ,"getMSRSegmentColors",
2949                    new RendererException("Failed inside getMSRSegmentColors", exc));
2950        }
2951        return hMap;
2952    }
2953    public static HashMap getMSRSegmentColorStrings(TGLight tg)
2954    {   
2955        HashMap hMap=null;
2956        try
2957        {
2958            int linetype = tg.get_LineType();
2959            switch (linetype) {
2960                case 25221000:
2961                case 25222000:
2962                case 22121000:
2963                    if (tg.get_H() == null || tg.get_H().isEmpty())
2964                        return null;
2965                    hMap = new java.util.HashMap();
2966                    break;
2967                default:
2968                    return null;
2969            }
2970            String[] colorStrs = tg.get_H().split(",");
2971            int j = 0;
2972            int numSegs = colorStrs.length;
2973            String segPlusColor = "";
2974            String[] seg = null;
2975            //Color color = null;
2976            int index = -1;
2977            for (j = 0; j < numSegs; j++) {
2978                segPlusColor = colorStrs[j];
2979                if (!segPlusColor.contains(":"))
2980                    continue;
2981                seg = segPlusColor.split(":");
2982                //color = armyc2.c2sd.renderer.utilities.SymbolUtilities.getColorFromHexString(seg[1]);
2983                index = Integer.parseInt(seg[0]);
2984                //hMap.put(new Integer(index), color);
2985                hMap.put(new Integer(index), seg[1]);
2986            }            
2987        }
2988        catch (Exception exc)
2989        {
2990            ErrorLogger.LogException(_className ,"getMSRSegmentColorStrings",
2991                    new RendererException("Failed inside getMSRSegmentColorStrings", exc));
2992        }
2993        return hMap;
2994    }
2995    /**
2996     * tg.H must be revised for clipped MSR, ASR and Boundary
2997     * This function is called after the pixels were clipped
2998     * @param originalPixels the tactical graphic pixels before clipping
2999     * @param tg 
3000     */
3001    public static void reviseHModifier(ArrayList<POINT2>originalPixels, 
3002            TGLight tg)
3003    {
3004        try
3005        {
3006            //only revise tg.H if it is not null or empty
3007            //and the linetype is bounday, MSR, or ASR
3008            if(tg.get_H()==null || tg.get_H().isEmpty())
3009                return;
3010            int linetype=tg.get_LineType();
3011            switch(linetype)
3012            {
3013                case TacticalLines.ASR:
3014                case TacticalLines.MSR:
3015                case TacticalLines.BOUNDARY:
3016                    break;
3017                default:
3018                    return;
3019            }
3020            int j=0,k=0;
3021            //Line2D line=new Line2D.Double();
3022            
3023            //get the first common point between the original points and tg.Pixels
3024            //if it is n then n segments will have been dropped at the front end of
3025            //the clipped array (from the original pixels) so then we would want to
3026            //set the start index to n for the loop through the original points
3027            int n=-1; 
3028            boolean foundPt=false;
3029            int t=originalPixels.size();
3030            int u=tg.Pixels.size();
3031            //for(j=0;j<originalPixels.size();j++)
3032            for(j=0;j<t;j++)
3033            {
3034                //for(k=0;k<tg.Pixels.size();k++)
3035                for(k=0;k<u;k++)
3036                {
3037                    if(originalPixels.get(j).x==tg.Pixels.get(k).x && originalPixels.get(j).y==tg.Pixels.get(k).y)
3038                    {
3039                        n=j;
3040                        foundPt=true;
3041                        break;
3042                    }
3043                }
3044                if(foundPt)
3045                    break;
3046            }
3047            HashMap<Integer,Color> hmap=getMSRSegmentColors(tg);
3048            //use a 2nd hashmap to store the revised segment numbers, and exisitng Colors
3049            HashMap<Integer,Color> hmap2=new HashMap<Integer,Color>();
3050            POINT2 segPt0=null,segPt1=null; //the original segments
3051            POINT2 pt0=null,pt1=null;   //the clipped segments
3052            Color color=null;
3053            if(n<1)
3054                n=1;
3055            for(Integer key : hmap.keySet()) //keys can begin at 0
3056            {
3057                if(key<n-1)
3058                    continue;
3059                if(key+1>originalPixels.size()-1)
3060                    break;
3061                color=hmap.get(key);
3062                segPt0=originalPixels.get(key);
3063                segPt1=originalPixels.get(key+1);
3064                u=tg.Pixels.size();
3065                //for(j=0;j<tg.Pixels.size()-1;j++)
3066                for(j=0;j<u-1;j++)
3067                {
3068                    pt0=tg.Pixels.get(j);//clipped pixels
3069                    pt1=tg.Pixels.get(j+1);
3070                    if(segPt0.x==pt0.x && segPt0.y==pt0.y)
3071                    {
3072                        hmap2.put(j, color);
3073                        break;
3074                    }
3075                    else if(segPt1.x==pt1.x && segPt1.y==pt1.y)
3076                    {
3077                        hmap2.put(j, color);
3078                        break;
3079                    }
3080                    else
3081                    {
3082                        if(pt0.x==segPt1.x && pt0.y==segPt1.y)
3083                            continue;
3084                        if(pt1.x==segPt0.x && pt1.y==segPt0.y)
3085                            continue;
3086                        else    
3087                        {       
3088                            //if the original segment straddles or clips the clipping area
3089                            //then the original segment will contain the clipped segment
3090                            double dist0=lineutility.CalcDistanceToLineDouble(segPt0, segPt1, pt0);
3091                            double dist1=lineutility.CalcDistanceToLineDouble(segPt0, segPt1, pt1);
3092                            Line2D lineOrigPts=new Line2D.Double(segPt0.x,segPt0.y, segPt1.x,segPt1.y);
3093                            Rectangle2D rectOrigPts=lineOrigPts.getBounds2D();
3094                            Line2D lineClipPts=new Line2D.Double(pt0.x,pt0.y, pt1.x, pt1.y);
3095                            Rectangle2D rectClipPts=lineClipPts.getBounds2D();
3096                            //test if the lines coincide and the clipped segment is within the original segment
3097                            if(dist0<1 && dist1<1 && rectOrigPts.contains(rectClipPts))
3098                            {
3099                                hmap2.put(j, color);                                
3100                            }
3101                        }
3102                    }
3103                }
3104            }        
3105            if(hmap2.isEmpty())
3106            {
3107                tg.set_H(null);
3108                return;
3109            }
3110           
3111            String h="",temp="";
3112            for(Integer key : hmap2.keySet()) 
3113            {
3114                color=hmap2.get(key);
3115                temp=Integer.toHexString(color.toARGB());
3116                h+=key.toString()+":"+temp+",";
3117            }
3118            h=h.substring(0, h.length()-1);
3119            tg.set_H(h);
3120        }
3121        catch (Exception exc) {
3122            ErrorLogger.LogException(_className, "reviseHModifer",
3123                    new RendererException("Failed inside reviseHModifier", exc));
3124        }
3125    }
3126
3127    /**
3128     * Adds extra points to LC if there are angles too small to fit the channel
3129     * @param tg
3130     * @param converter
3131     */
3132    public static void SegmentLCPoints(TGLight tg, IPointConversion converter) {
3133        try {
3134            if (tg.get_LineType() != TacticalLines.LC && tg.get_LineType() != TacticalLines.LC_HOSTILE)
3135                return;
3136
3137            ArrayList<POINT2> points = tg.get_Pixels();
3138
3139            double LCChannelWith = 40;
3140
3141            for (int i = 0; i < points.size() - 2; i++) {
3142                POINT2 ptA = new POINT2(points.get(i).x, points.get(i).y);
3143                POINT2 ptB = new POINT2(points.get(i+1).x, points.get(i+1).y);
3144                POINT2 ptC = new POINT2(points.get(i+2).x, points.get(i+2).y);
3145
3146                double angle1 = Math.atan2(ptB.y - ptA.y, ptB.x - ptA.x);
3147                double angle2 = Math.atan2(ptB.y - ptC.y, ptB.x - ptC.x);
3148                double angle = angle1 - angle2;
3149                double degrees = angle * 180/Math.PI;
3150
3151                if(angle < 0) {
3152                    degrees = 360 + degrees;
3153                }
3154
3155                if (degrees > 270) {
3156                    // For acute angles where red is the outer line
3157                    // Determine shorter segment (BA or BC)
3158                    // On longer segment calculate potential new point (newPt) that is length of smaller segment from B
3159                    // If distance between smaller segment end point (A or C) and newPt is smaller than the channel width add newPt to points
3160                    // In GetLCPartitions() the black line won't be included between the smaller line and newPt since there isn't enough space to fit the channel
3161                    if (lineutility.CalcDistanceDouble(ptB, ptA) < lineutility.CalcDistanceDouble(ptB, ptC)) {
3162                        // BA is smaller segment
3163                        POINT2 newPt = lineutility.ExtendAlongLineDouble2(ptB, ptC, lineutility.CalcDistanceDouble(ptB, ptA));
3164                        if (lineutility.CalcDistanceDouble(ptA, newPt) < LCChannelWith) {
3165                            points.add(i + 2, new POINT2(newPt.x, newPt.y));
3166                            i++;
3167                        }
3168                    } else {
3169                        // BC is smaller segment
3170                        POINT2 newPt = lineutility.ExtendAlongLineDouble2(ptB, ptA, lineutility.CalcDistanceDouble(ptB, ptC));
3171                        if (lineutility.CalcDistanceDouble(ptC, newPt) < LCChannelWith) {
3172                            points.add(i + 1, new POINT2(newPt.x, newPt.y));
3173                            i++;
3174                        }
3175                    }
3176                }
3177            }
3178            tg.Pixels = points;
3179            tg.LatLongs = armyc2.c2sd.JavaRendererServer.RenderMultipoints.clsUtility.PixelsToLatLong(points, converter);
3180        } catch (Exception exc) {
3181            ErrorLogger.LogException(_className, "segmentLCPoints",
3182                    new RendererException("Failed inside segmentLCPoints", exc));
3183        }
3184    }
3185    /**
3186     * Interpolate pixels for lines with points too close together.
3187     * Drops successive points until the next point is at least 10 pixels from the preceding point
3188     * @param tg 
3189     */
3190    public static void InterpolatePixels(TGLight tg)
3191    {
3192        try
3193        {
3194            if(tg.get_UseLineInterpolation()==false)
3195                return;
3196            
3197            int linetype=tg.get_LineType();
3198            double glyphSize=10;
3199            switch(linetype)
3200            {
3201                case TacticalLines.ATDITCH:
3202                case TacticalLines.ATDITCHC:
3203                    glyphSize=25;
3204                    break;
3205                case TacticalLines.ATDITCHM:
3206                    glyphSize=50;
3207                    break;
3208                case TacticalLines.DMAF:
3209                    glyphSize=20;
3210                    break;
3211                case TacticalLines.FLOT:
3212                case TacticalLines.LC:
3213                case TacticalLines.FORT:
3214                case TacticalLines.FORTL:
3215                case TacticalLines.ENCIRCLE:
3216                case TacticalLines.BELT:
3217                case TacticalLines.ZONE:
3218                case TacticalLines.OBSFAREA:
3219                case TacticalLines.OBSAREA:
3220                case TacticalLines.DOUBLEA:
3221                case TacticalLines.LWFENCE:
3222                case TacticalLines.HWFENCE:
3223                case TacticalLines.BBS_LINE:
3224                case TacticalLines.SINGLEC:
3225                case TacticalLines.DOUBLEC:
3226                case TacticalLines.TRIPLE:
3227                case TacticalLines.STRONG:
3228                    glyphSize=30;
3229                    break;
3230                case TacticalLines.UNSP:
3231                case TacticalLines.LINE:
3232                case TacticalLines.ATWALL:
3233                case TacticalLines.SFENCE:
3234                    glyphSize=40;
3235                    break;
3236                case TacticalLines.DFENCE:
3237                    glyphSize=50;
3238                    break;
3239                default:
3240                    return;
3241            }
3242            HashMap hmapPixels=new HashMap<Integer,POINT2>();
3243            HashMap hmapGeo=new HashMap<Integer,POINT2>();
3244            int j=0,currentIndex=0;
3245            double dist=0,dist2=0;
3246            double direction1=0,direction2=0,delta=0;
3247            POINT2 pt0=null,pt1=null,pt2=null;
3248            int n=tg.Pixels.size();
3249            //for(j=0;j<tg.Pixels.size();j++)
3250            for(j=0;j<n;j++)
3251            {
3252                if(j==0)
3253                {
3254                    hmapPixels.put(j, tg.Pixels.get(j));
3255                    hmapGeo.put(j, tg.LatLongs.get(j));
3256                    currentIndex=0;
3257                }
3258                else if(j==tg.Pixels.size()-1)
3259                {
3260                    hmapPixels.put(j, tg.Pixels.get(j));
3261                    hmapGeo.put(j, tg.LatLongs.get(j));                    
3262                }
3263                else
3264                {
3265                    dist=lineutility.CalcDistanceDouble(tg.Pixels.get(currentIndex), tg.Pixels.get(j));
3266                    dist2=lineutility.CalcDistanceDouble(tg.Pixels.get(j), tg.Pixels.get(j+1));
3267                    
3268                    //change of direction test 2-28-13
3269                    pt0=tg.Pixels.get(currentIndex);
3270                    pt1=tg.Pixels.get(j);
3271                    pt2=tg.Pixels.get(j+1);
3272                    direction1=(180/Math.PI)*Math.atan((pt0.y-pt1.y)/(pt0.x-pt1.x));
3273                    direction2=(180/Math.PI)*Math.atan((pt1.y-pt2.y)/(pt1.x-pt2.x));
3274                    delta=Math.abs(direction1-direction2);
3275                    if(dist>glyphSize || dist2>glyphSize || delta>20)
3276                    {
3277                        hmapPixels.put(j, tg.Pixels.get(j));
3278                        hmapGeo.put(j, tg.LatLongs.get(j));
3279                        currentIndex=j;
3280                    }
3281                }
3282            }
3283            ArrayList<POINT2>pixels=new ArrayList();
3284            ArrayList<POINT2>geo=new ArrayList();
3285            n=tg.Pixels.size();
3286            //for(j=0;j<tg.Pixels.size();j++)
3287            for(j=0;j<n;j++)
3288            {
3289                if(hmapPixels.containsKey(j))
3290                    pixels.add((POINT2)hmapPixels.get(j));
3291                if(hmapGeo.containsKey(j))
3292                    geo.add((POINT2)hmapGeo.get(j));
3293            }
3294            switch(linetype)
3295            {
3296                case TacticalLines.DMAF:
3297                case TacticalLines.FORT:
3298                case TacticalLines.ENCIRCLE:
3299                case TacticalLines.BELT:
3300                case TacticalLines.ZONE:
3301                case TacticalLines.OBSFAREA:
3302                case TacticalLines.OBSAREA:
3303                case TacticalLines.STRONG:
3304                    if(pixels.size()==2)
3305                    {
3306                        n=tg.Pixels.size();
3307                        //for(j=0;j<tg.Pixels.size();j++)
3308                        for(j=0;j<n;j++)
3309                        {
3310                            if(hmapPixels.containsKey(j)==false && hmapGeo.containsKey(j)==false)
3311                            {
3312                                pixels.add(j,tg.Pixels.get(j));
3313                                geo.add(j,tg.LatLongs.get(j));
3314                                break;
3315                            }
3316                        }                        
3317                    }
3318                    break;
3319                default:
3320                    break;
3321            }            
3322            tg.Pixels=pixels;
3323            tg.LatLongs=geo;
3324        }
3325        catch (Exception exc) {
3326            ErrorLogger.LogException(_className, "InterpolatePixels",
3327                    new RendererException("Failed inside InterpolatePixels", exc));
3328        }
3329    }
3330    /**
3331     * construct a line segment outside the polygon corresponding to some index
3332     * @param tg
3333     * @param index
3334     * @param dist
3335     * @return 
3336     */
3337    protected static Line2D getExtendedLine(TGLight tg,
3338            int index,
3339            double dist)
3340    {
3341        Line2D line=null;
3342        try
3343        {
3344            Polygon polygon=new Polygon();
3345            int j=0;
3346            int n=tg.Pixels.size();
3347            //for(j=0;j<tg.Pixels.size();j++)
3348            for(j=0;j<n;j++)
3349            {
3350                polygon.addPoint((int)tg.Pixels.get(j).x, (int)tg.Pixels.get(j).y);
3351            }
3352            POINT2 pt0=null; 
3353            POINT2 pt1=null; 
3354            if(tg.Pixels.size()>3)
3355            {
3356                pt0=tg.Pixels.get(index);
3357                pt1=tg.Pixels.get(index+1);
3358            }
3359            else
3360            {
3361                pt0=tg.Pixels.get(1);
3362                pt1=tg.Pixels.get(2);                
3363            }
3364            
3365            POINT2 ptExtend=null;
3366            int extend=-1;
3367            POINT2 midPt=lineutility.MidPointDouble(pt0, pt1,0);
3368            double slope=Math.abs(pt1.y-pt0.y)/(pt1.x-pt0.x);
3369            if(slope<=1)
3370            {
3371                ptExtend=lineutility.ExtendDirectedLine(pt0, pt1, midPt, lineutility.extend_above, 2);
3372                if(polygon.contains(ptExtend.x,ptExtend.y))
3373                    extend=lineutility.extend_below;
3374                else
3375                    extend=lineutility.extend_above;
3376            }
3377            else
3378            {
3379                ptExtend=lineutility.ExtendDirectedLine(pt0, pt1, midPt, lineutility.extend_left, 2);
3380                if(polygon.contains(ptExtend.x,ptExtend.y))
3381                    extend=lineutility.extend_right;
3382                else
3383                    extend=lineutility.extend_left;
3384                
3385            }
3386            POINT2 pt3=null;
3387            POINT2 pt4=null;
3388            pt3=lineutility.ExtendDirectedLine(pt0, pt1, pt0, extend, dist);
3389            pt4=lineutility.ExtendDirectedLine(pt0, pt1, pt1, extend, dist);
3390            line=new Line2D.Double(pt3.x, pt3.y, pt4.x, pt4.y);
3391        }
3392        catch (Exception exc) {            
3393            ErrorLogger.LogException(_className, "getExtendedLine",
3394                    new RendererException("Failed inside getExtendedLine", exc));
3395        }
3396        return line;
3397    }
3398
3399}//end clsUtility