001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005
006package armyc2.c5isr.RenderMultipoints;
007import static armyc2.c5isr.JavaTacticalRenderer.clsUtility.isAutoshape;
008
009import armyc2.c5isr.graphics2d.Area;
010import armyc2.c5isr.graphics2d.BasicStroke;
011import armyc2.c5isr.graphics2d.Rectangle;
012import armyc2.c5isr.renderer.PatternFillRenderer;
013import armyc2.c5isr.renderer.utilities.IPointConversion;
014import armyc2.c5isr.JavaTacticalRenderer.TGLight;
015import armyc2.c5isr.JavaLineArray.TacticalLines;
016import armyc2.c5isr.JavaLineArray.lineutility;
017import armyc2.c5isr.JavaLineArray.POINT2;
018import java.util.ArrayList;
019import armyc2.c5isr.renderer.utilities.ErrorLogger;
020import armyc2.c5isr.renderer.utilities.RendererException;
021import armyc2.c5isr.JavaLineArray.Shape2;
022
023import android.graphics.BitmapShader;
024import android.graphics.Shader;
025import armyc2.c5isr.renderer.utilities.Color;
026import armyc2.c5isr.renderer.utilities.ShapeInfo;
027import armyc2.c5isr.graphics2d.Point;
028import armyc2.c5isr.graphics2d.Point2D;
029import armyc2.c5isr.graphics2d.Rectangle2D;
030
031/**
032 * Server general utility class
033*
034 */
035public final class clsUtility {
036    private static final String _className="clsUtility";
037    public static final int Hatch_ForwardDiagonal=2;
038    public static final int Hatch_BackwardDiagonal=3;
039    public static final int Hatch_Vertical=4;
040    public static final int Hatch_Horizontal=5;
041    public static final int Hatch_Cross=8;
042
043    /**
044     * Adds hatch fill to shapes via PatternFillRendererD.MakeHatchPatternFill() or buildHatchFill()
045     * @param tg
046     * @param shapes
047     */
048    protected static void addHatchFills(TGLight tg, ArrayList<ShapeInfo>shapes)
049    {
050        try
051        {
052            if(shapes==null || shapes.size()==0)
053                return;
054
055            int lineType=tg.get_LineType();
056            int hatchStyle=tg.get_FillStyle();
057            int j=0,hatch2=0;
058            Shape2 shape2=null;
059            int index=0;
060            float hatchLineThickness = (tg.get_LineThickness() * 0.75f) * (float) tg.get_patternScale();//1.5f + ((tg.get_LineThickness() / 2f) - 1.5f) * (float) tg.get_patternScale();
061            Color hatchColor = tg.get_LineColor();
062            int hatchSpacing = (int) (hatchLineThickness * 6);//(int) (hatchLineThickness * 10);
063
064//            if(armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(lineType)==false)
065//                if(armyc2.c5isr.JavaTacticalRenderer.clsUtility.IsChange1Area(lineType, null)==false)
066//                    return;
067            if(armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(lineType)==false)
068            {
069                if(armyc2.c5isr.JavaTacticalRenderer.clsUtility.IsChange1Area(lineType)==false)
070                {
071                    switch(lineType)
072                    {
073                        case TacticalLines.BBS_AREA:
074                        case TacticalLines.BBS_LINE:
075                        case TacticalLines.BBS_RECTANGLE:
076                            break;
077                        default:
078                            return;
079                    }
080                }
081            }
082
083            switch(lineType)
084            {
085                case TacticalLines.NFA:
086                case TacticalLines.NFA_CIRCULAR:
087                case TacticalLines.NFA_RECTANGULAR:
088                case TacticalLines.LAA:
089                    hatchStyle = Hatch_BackwardDiagonal;
090                    break;
091                case TacticalLines.BIO:
092                case TacticalLines.BIOT:
093                case TacticalLines.NUC:
094                case TacticalLines.CHEM:
095                case TacticalLines.CHEMT:
096                case TacticalLines.RAD:
097                case TacticalLines.RADT:
098                    hatchStyle=Hatch_BackwardDiagonal;
099                    hatchColor = Color.yellow;
100                    hatchLineThickness = (tg.get_LineThickness() * 0.85f) * (float) tg.get_patternScale();
101                    //hatchLineThickness = 1.5f + (tg.get_LineThickness() - 1.5f) * (float) tg.get_patternScale();
102                    //hatchSpacing = (int) (hatchLineThickness * 4);
103                    break;
104                case TacticalLines.WFZ_REVD:
105                case TacticalLines.WFZ:
106                    hatchStyle=Hatch_BackwardDiagonal;
107                    if (tg.get_LineColor() == Color.BLACK)
108                        hatchColor = Color.GRAY;
109                    hatchSpacing /= 2;
110                    break;
111                case TacticalLines.OBSAREA:
112                    //CPOF client required adding a simple shape for
113                    //setting texturepaint which WebRenderer does not use
114                    for(j=0;j<shapes.size();j++)
115                    {
116                        ShapeInfo shape=shapes.get(j);
117                        Color color=shape.getLineColor();
118                        if(color==null)
119                            continue;
120                        //if(shape.getLineColor().getRGB()==0)
121                        if(shape.getLineColor().toARGB()==0)
122                            shapes.remove(j);
123                    }
124                    hatchStyle = Hatch_BackwardDiagonal;
125                    hatchSpacing *= 1.25;
126                    break;
127                default:
128                    if(hatchStyle<=0)
129                        return;
130                    break;
131            }
132            //get the index of the shape with the same fillstyle
133            int n=shapes.size();
134            //for(j=0;j<shapes.size();j++)
135            for(j=0;j<n;j++)
136            {
137                shape2=(Shape2)shapes.get(j);
138                hatch2=shape2.get_FillStyle();
139                if(hatch2==hatchStyle)
140                {
141                    index=j;
142                    break;
143                }
144            }
145            n=shapes.size();
146            //for(int k=0;k<shapes.size();k++)
147            for(int k=0;k<n;k++)
148            {
149                //the outline should always be the 0th shape for areas
150                ShapeInfo shape=null;
151                if(lineType==TacticalLines.RANGE_FAN || lineType==TacticalLines.RANGE_FAN_SECTOR || lineType==TacticalLines.RADAR_SEARCH)
152                {
153                    shape=shapes.get(k);
154                    shape2=(Shape2)shapes.get(k);
155                    hatchStyle=shape2.get_FillStyle();
156                }
157                else
158                    shape=shapes.get(index);
159
160                if(hatchStyle<Hatch_ForwardDiagonal)//Hatch_ForwardDiagonal is the 0th hatch element
161                    continue;
162
163                if (tg.get_UseHatchFill())
164                {
165                    shape.setPatternFillImage(PatternFillRenderer.MakeHatchPatternFill(hatchStyle, hatchSpacing, (int) hatchLineThickness, hatchColor));
166                    shape.setShader(new BitmapShader(shape.getPatternFillImage(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
167                }
168                else if(hatchStyle != Hatch_Cross)
169                {
170                    Shape2 shape3= buildHatchArea(tg, shape,hatchStyle, hatchSpacing);
171                    //shape.setStroke(new BasicStroke(1));
172                    shape3.setStroke(new BasicStroke(hatchLineThickness));
173                    shape3.setLineColor(hatchColor);
174                    shapes.add(shape3);
175                }
176                else    //cross hatch
177                {
178                    Shape2 shapeBk= buildHatchArea(tg, shape,Hatch_BackwardDiagonal,hatchSpacing);
179                    Shape2 shapeFwd= buildHatchArea(tg, shape,Hatch_ForwardDiagonal,hatchSpacing);
180                    //shapeBk.setStroke(new BasicStroke(1));
181                    shapeBk.setStroke(new BasicStroke(hatchLineThickness));
182                    shapeBk.setLineColor(hatchColor);
183                    shapes.add(shapeBk);
184                    //shapeFwd.setStroke(new BasicStroke(1));
185                    shapeFwd.setStroke(new BasicStroke(hatchLineThickness));
186                    shapeFwd.setLineColor(hatchColor);
187                    shapes.add(shapeFwd);
188                }
189                if(lineType != TacticalLines.RANGE_FAN && lineType != TacticalLines.RANGE_FAN_SECTOR && lineType != TacticalLines.RADAR_SEARCH)
190                    break;
191            }
192        }
193        catch (Exception exc) {
194            ErrorLogger.LogException(_className, "addHatchFills",
195                    new RendererException("Failed inside addHatchFills", exc));
196        }
197    }
198
199    /**
200     * Build Hatch fill. Does not use texture paint or shader.
201     * @param tg
202     * @param shape
203     * @param hatchStyle
204     * @return
205     */
206    protected static Shape2 buildHatchArea(TGLight tg, ShapeInfo shape, int hatchStyle, double spacing)
207    {
208        Shape2 hatchLineShape=null;
209        try
210        {
211            hatchLineShape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
212            Area hatchLineArea=null;
213            Rectangle rect=shape.getBounds();
214            double x0=rect.getX();
215            double y0=rect.getY();
216            double width=rect.getWidth();
217            double height=rect.getHeight();
218            //we need a square
219            if(width>height)
220                height=width;
221            else
222                width=height;
223
224            //diagnostic
225            if(tg.get_UseHatchFill())
226            {
227//                hatchLineShape.moveTo(new POINT2(x0,y0));
228//                hatchLineShape.lineTo(new POINT2(x0+width,y0));
229//                hatchLineShape.lineTo(new POINT2(x0+width,y0+width));
230//                hatchLineShape.lineTo(new POINT2(x0,y0+width));
231                hatchLineShape.set_Fillstyle(hatchStyle);
232//                hatchLineShape.lineTo(new POINT2(x0,y0));
233//                Area shapeArea=new Area(shape.getShape());
234//                hatchLineArea=new Area(hatchLineShape.getShape());
235//                //intersect the hatch lines with the original shape area to get the fill
236//                hatchLineArea.intersect(shapeArea);
237//                hatchLineShape.setShape(hatchLineArea);
238                hatchLineShape.setShape(lineutility.createStrokedShape(shape.getShape()));
239                return hatchLineShape;
240            }
241            //end section
242
243            width *= 2;
244            height *= 2;
245            //the next two values should be equal
246            int horizLimit=0;
247            int vertLimit=0;
248            int j=0;
249            ArrayList<POINT2>vertPts=new ArrayList();
250            ArrayList<POINT2>horizPts=new ArrayList();
251            POINT2 vertPt=null,horizPt=null;
252            if(hatchStyle==Hatch_BackwardDiagonal)
253            {
254                horizLimit=(int)(width/spacing);
255                vertLimit=(int)(height/spacing);
256                for(j=0;j<vertLimit;j++)
257                {
258                    vertPt=new POINT2(x0,y0+spacing*j);
259                    vertPts.add(vertPt);
260                }
261                for(j=0;j<horizLimit;j++)
262                {
263                    horizPt=new POINT2(x0+spacing*j,y0);
264                    horizPts.add(horizPt);
265                }
266
267                hatchLineShape.moveTo(new POINT2(x0-spacing/2,y0-spacing/2));
268                hatchLineShape.lineTo(new POINT2(x0,y0));
269                for(j=0;j<vertLimit;j++)
270                {
271                    if(j%2==0)
272                    {
273                        hatchLineShape.lineTo(vertPts.get(j));
274                        hatchLineShape.lineTo(horizPts.get(j));
275                    }
276                    else
277                    {
278                        hatchLineShape.lineTo(horizPts.get(j));
279                        hatchLineShape.lineTo(vertPts.get(j));
280                    }
281                }
282                //go outside the bottom right corner to complete a valid area
283                hatchLineShape.lineTo(new POINT2(x0+width+spacing/2,y0+height+spacing/2));
284                hatchLineShape.lineTo(new POINT2(x0+width+spacing,y0+height+spacing/2));
285                hatchLineShape.lineTo(new POINT2(x0+width+spacing,y0-spacing/2));
286                hatchLineShape.lineTo(new POINT2(x0-spacing/2,y0-spacing/2));
287            }
288            if(hatchStyle==Hatch_ForwardDiagonal)
289            {
290                horizLimit=(int)(width/spacing);
291                vertLimit=(int)(height/spacing);
292                width /= 2;
293                for(j=0;j<vertLimit;j++)
294                {
295                    vertPt=new POINT2(x0+width,y0+spacing*j);
296                    vertPts.add(vertPt);
297                }
298                for(j=0;j<horizLimit;j++)
299                {
300                    horizPt=new POINT2(x0+width-spacing*j,y0);
301                    horizPts.add(horizPt);
302                }
303
304                hatchLineShape.moveTo(new POINT2(x0+width+spacing/2,y0-spacing/2));
305                hatchLineShape.lineTo(new POINT2(x0,y0));
306                for(j=0;j<vertLimit;j++)
307                {
308                    if(j%2==0)
309                    {
310                        hatchLineShape.lineTo(vertPts.get(j));
311                        hatchLineShape.lineTo(horizPts.get(j));
312                    }
313                    else
314                    {
315                        hatchLineShape.lineTo(horizPts.get(j));
316                        hatchLineShape.lineTo(vertPts.get(j));
317                    }
318                }
319                //go outside the bottom left corner to complete a valid area
320                hatchLineShape.lineTo(new POINT2(x0-spacing/2,y0+height+spacing/2));
321                hatchLineShape.lineTo(new POINT2(x0-spacing,y0+height+spacing/2));
322                hatchLineShape.lineTo(new POINT2(x0-spacing,y0-spacing/2));
323                hatchLineShape.lineTo(new POINT2(x0+width+spacing/2,y0-spacing/2));
324            }
325            if(hatchStyle==Hatch_Vertical)
326            {
327                horizLimit=(int)(width/(spacing/2));
328                vertLimit=(int)(height/(spacing/2));
329                for(j=0;j<horizLimit;j++)
330                {
331                    if(j%2==0)
332                    {
333                        vertPt=new POINT2(x0+spacing/2*j,y0);
334                        vertPts.add(vertPt);
335                        vertPt=new POINT2(x0+spacing/2*j,y0+height);
336                        vertPts.add(vertPt);
337                    }
338                    else
339                    {
340                        vertPt=new POINT2(x0+spacing/2*j,y0+height);
341                        vertPts.add(vertPt);
342                        vertPt=new POINT2(x0+spacing/2*j,y0);
343                        vertPts.add(vertPt);
344                    }
345                }
346                hatchLineShape.moveTo(new POINT2(x0-spacing/2,y0-spacing/2));
347                hatchLineShape.lineTo(new POINT2(x0,y0));
348                for(j=0;j<vertLimit-1;j++)
349                {
350                    hatchLineShape.lineTo(vertPts.get(j));
351                }
352                //go outside the bottom right corner to complete a valid area
353                hatchLineShape.lineTo(new POINT2(x0+width+spacing/2,y0+height+spacing/2));
354                hatchLineShape.lineTo(new POINT2(x0+width+spacing,y0+height+spacing/2));
355                hatchLineShape.lineTo(new POINT2(x0+width+spacing,y0-spacing/2));
356                hatchLineShape.lineTo(new POINT2(x0-spacing/2,y0-spacing/2));
357            }
358            if(hatchStyle==Hatch_Horizontal)
359            {
360                horizLimit=(int)(width/(spacing/2));
361                vertLimit=(int)(height/(spacing/2));
362                for(j=0;j<vertLimit;j++)
363                {
364                    if(j%2==0)
365                    {
366                        horizPt=new POINT2(x0,y0+spacing/2*j);
367                        horizPts.add(horizPt);
368                        horizPt=new POINT2(x0+width,y0+spacing/2*j);
369                        horizPts.add(horizPt);
370                    }
371                    else
372                    {
373                        horizPt=new POINT2(x0+width,y0+spacing/2*j);
374                        horizPts.add(horizPt);
375                        horizPt=new POINT2(x0,y0+spacing/2*j);
376                        horizPts.add(horizPt);
377                    }
378                }
379                hatchLineShape.moveTo(new POINT2(x0-spacing/2,y0-spacing/2));
380                hatchLineShape.lineTo(new POINT2(x0,y0));
381                for(j=0;j<vertLimit-1;j++)
382                {
383                    hatchLineShape.lineTo(horizPts.get(j));
384                }
385                //go outside the bottom left corner to complete a valid area
386                hatchLineShape.lineTo(new POINT2(x0-spacing/2,y0+height+spacing/2));
387                hatchLineShape.lineTo(new POINT2(x0-spacing,y0+height+spacing/2));
388                hatchLineShape.lineTo(new POINT2(x0-spacing,y0-spacing/2));
389                hatchLineShape.lineTo(new POINT2(x0+width+spacing/2,y0-spacing/2));
390            }
391
392            Area shapeArea=new Area(shape.getShape());
393            hatchLineArea=new Area(hatchLineShape.getShape());
394            //intersect the hatch lines with the original shape area to get the fill
395            hatchLineArea.intersect(shapeArea);
396            hatchLineShape.setShape(hatchLineArea);
397            //return null;
398        }
399        catch(Exception exc)
400        {
401            ErrorLogger.LogException(_className, "buildHatchArea",
402                    new RendererException("Failed inside buildHatchArea", exc));
403        }
404        return hatchLineShape;
405    }
406
407    protected static Point POINT2ToPoint(POINT2 pt2)
408    {
409        Point pt=new Point();
410        pt.x=(int)pt2.x;
411        pt.y=(int)pt2.y;
412        return pt;
413    }
414    protected static POINT2 PointToPOINT2(Point pt)
415    {
416        POINT2 pt2=new POINT2(pt.x,pt.y);
417        return pt2;
418    }
419    protected static Point2D.Double POINT2ToPoint2D(POINT2 pt2)
420    {
421        Point2D.Double pt2d=new Point2D.Double(pt2.x,pt2.y);
422        return pt2d;
423    }
424    protected static ArrayList<POINT2> Points2DToPOINT2(ArrayList<Point2D>pts2d)
425    {
426        ArrayList<POINT2>pts=new ArrayList();
427        POINT2 pt=null;
428        int n=pts2d.size();
429        //for(int j=0;j<pts2d.size();j++)        
430        for(int j=0;j<n;j++)        
431        {
432            pt=new POINT2(pts2d.get(j).getX(),pts2d.get(j).getY());
433            pts.add(pt);
434        }        
435        return pts;
436    }
437    protected static POINT2 Point2DToPOINT2(Point2D pt2d)
438    {
439        POINT2 pt2=new POINT2(pt2d.getX(),pt2d.getY());
440        return pt2;
441    }
442    /**
443     * @deprecated   
444     * @param tg
445     * @return 
446     */
447    protected static boolean addModifiersBeforeClipping(TGLight tg)
448    {
449        boolean result=false;
450        int linetype=tg.get_LineType();
451        switch(linetype)
452        {
453            case TacticalLines.TORPEDO:
454            case TacticalLines.OPTICAL:
455            case TacticalLines.ELECTRO:
456            case TacticalLines.BEARING_EW:
457            case TacticalLines.ACOUSTIC:
458            case TacticalLines.ACOUSTIC_AMB:
459            case TacticalLines.BEARING:
460            case TacticalLines.BEARING_J:
461            case TacticalLines.BEARING_RDF:
462            case TacticalLines.MSR:
463            case TacticalLines.MSR_ONEWAY:
464            case TacticalLines.MSR_TWOWAY:
465            case TacticalLines.MSR_ALT:
466            case TacticalLines.ASR:
467            case TacticalLines.ASR_ONEWAY:
468            case TacticalLines.ASR_TWOWAY:
469            case TacticalLines.ASR_ALT:
470            case TacticalLines.TRAFFIC_ROUTE:
471            case TacticalLines.TRAFFIC_ROUTE_ONEWAY:
472            case TacticalLines.TRAFFIC_ROUTE_ALT:
473            case TacticalLines.HCONVOY:
474            case TacticalLines.CONVOY:
475            case TacticalLines.MFP:
476            case TacticalLines.RFL:
477            case TacticalLines.NFL:
478            case TacticalLines.CFL:
479            case TacticalLines.TRIP:
480            case TacticalLines.FSCL:
481            case TacticalLines.BCL_REVD:
482            case TacticalLines.BCL:
483            case TacticalLines.ICL:
484            case TacticalLines.IFF_OFF:
485            case TacticalLines.IFF_ON:
486            case TacticalLines.GENERIC_LINE:
487            case TacticalLines.FPF:
488            case TacticalLines.LINTGT:
489            case TacticalLines.LINTGTS:
490            case TacticalLines.MSDZ:
491            case TacticalLines.GAP:
492            case TacticalLines.IL:
493            case TacticalLines.DIRATKAIR:
494            case TacticalLines.PDF:
495            case TacticalLines.AC:
496            case TacticalLines.SAAFR:
497            case TacticalLines.LLTR:
498            case TacticalLines.SC:
499            case TacticalLines.MRR:
500            case TacticalLines.SL:
501            case TacticalLines.TC:
502            case TacticalLines.BOUNDARY:
503            case TacticalLines.WDRAWUP:
504            case TacticalLines.WITHDRAW:
505            case TacticalLines.DISENGAGE:
506            case TacticalLines.RETIRE:
507            case TacticalLines.FPOL:
508            case TacticalLines.RPOL:
509            case TacticalLines.RIP:
510            case TacticalLines.MOBILE_DEFENSE:
511            case TacticalLines.DEMONSTRATE:
512            case TacticalLines.DELAY:
513            case TacticalLines.CATK:
514            case TacticalLines.CATKBYFIRE:
515            case TacticalLines.SCREEN:
516            case TacticalLines.COVER:
517            case TacticalLines.GUARD:
518            case TacticalLines.ESCORT:
519            case TacticalLines.FLOT:
520            case TacticalLines.LC:
521            case TacticalLines.PL:
522            case TacticalLines.DECISION_LINE:
523            case TacticalLines.FEBA:
524            case TacticalLines.LL:
525            case TacticalLines.EWL:
526            case TacticalLines.FCL:
527            case TacticalLines.HOLD:
528            case TacticalLines.BRDGHD:
529            case TacticalLines.HOLD_GE:
530            case TacticalLines.BRDGHD_GE:
531            case TacticalLines.LOA:
532            case TacticalLines.LOD:
533            case TacticalLines.LDLC:
534            case TacticalLines.PLD:
535            case TacticalLines.RELEASE:
536            case TacticalLines.HOL:
537            case TacticalLines.BHL:
538                result = true;
539                break;
540            default:
541                break;
542        }
543        if(armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(linetype)==true)
544            result=true;
545        return result;
546    }
547
548    /**
549     * @deprecated
550     */
551    protected static void FilterPoints(TGLight tg)
552    {
553        try
554        {
555            int lineType = tg.get_LineType();
556            double minSpikeDistance = 0;
557            switch (lineType)
558            {
559                //case TacticalLines.LC:
560                case TacticalLines.ATDITCH:
561                case TacticalLines.ATDITCHC:
562                case TacticalLines.ATDITCHM:
563                case TacticalLines.FLOT:
564                case TacticalLines.FORT_REVD:
565                case TacticalLines.FORT:
566                case TacticalLines.FORTL:
567                case TacticalLines.STRONG:
568                    minSpikeDistance=25;
569                    break;
570                case TacticalLines.LC:
571                case TacticalLines.OBSAREA:
572                case TacticalLines.OBSFAREA:
573                case TacticalLines.ENCIRCLE:
574                case TacticalLines.ZONE:
575                case TacticalLines.LINE:
576                case TacticalLines.ATWALL:
577                case TacticalLines.UNSP:
578                case TacticalLines.SFENCE:
579                case TacticalLines.DFENCE:
580                case TacticalLines.DOUBLEA:
581                case TacticalLines.LWFENCE:
582                case TacticalLines.HWFENCE:
583                case TacticalLines.SINGLEC:
584                case TacticalLines.DOUBLEC:
585                case TacticalLines.TRIPLE:
586                    minSpikeDistance=35;
587                    break;
588                case TacticalLines.UCF:
589                case TacticalLines.CF:
590                case TacticalLines.CFG:
591                case TacticalLines.CFY:
592                    minSpikeDistance=60;
593                    break;
594                case TacticalLines.SF:
595                case TacticalLines.USF:
596                case TacticalLines.OCCLUDED:
597                case TacticalLines.UOF:
598                    minSpikeDistance=60;//was 120
599                    break;
600                case TacticalLines.SFG:
601                case TacticalLines.SFY:
602                    minSpikeDistance=60;//was 180
603                    break;
604                case TacticalLines.WFY:
605                case TacticalLines.WFG:
606                case TacticalLines.OFY:
607                    minSpikeDistance=60;//was 120
608                    break;
609                case TacticalLines.WF:
610                case TacticalLines.UWF:
611                    minSpikeDistance=40;
612                    break;
613
614                case TacticalLines.RIDGE:
615                case TacticalLines.ICE_EDGE_RADAR:  //METOCs
616                case TacticalLines.ICE_OPENINGS_FROZEN:
617                case TacticalLines.CRACKS_SPECIFIC_LOCATION:
618                    minSpikeDistance=35;
619                    break;
620                default:
621                    return;
622            }
623            int j=0;
624            double dist=0;
625            ArrayList<POINT2>pts=new ArrayList();
626            ArrayList<POINT2>ptsGeo=new ArrayList();
627            pts.add(tg.Pixels.get(0));
628            ptsGeo.add(tg.LatLongs.get(0));
629            POINT2 lastGoodPt=tg.Pixels.get(0);
630            POINT2 currentPt=null;
631            POINT2 currentPtGeo=null;
632            boolean foundGoodPt=false;
633            int n=tg.Pixels.size();
634            //for(j=1;j<tg.Pixels.size();j++)
635            for(j=1;j<n;j++)
636            {
637                //we can not filter out the original end points
638                currentPt=tg.Pixels.get(j);
639                currentPtGeo=tg.LatLongs.get(j);
640                if(currentPt.style==-1)
641                {
642                    lastGoodPt=currentPt;
643                    pts.add(currentPt);
644                    ptsGeo.add(currentPtGeo);
645                    foundGoodPt=true;
646                    currentPt.style=0;
647                    continue;
648                }
649                dist=lineutility.CalcDistanceDouble(lastGoodPt, currentPt);
650                switch(lineType)
651                {
652                    case TacticalLines.LC:
653                        if(dist>minSpikeDistance)
654                        {
655                            lastGoodPt=currentPt;
656                            pts.add(currentPt);
657                            ptsGeo.add(currentPtGeo);
658                            foundGoodPt=true;
659                        }
660                        else
661                        {   //the last point is no good
662                            //replace the last good point with the last point
663                            if(j==tg.Pixels.size()-1)
664                            {
665                                pts.set(pts.size()-1, currentPt);
666                                ptsGeo.set(ptsGeo.size()-1, currentPtGeo);
667                            }
668                        }
669                        break;
670                    default:
671                        if(dist>minSpikeDistance || j==tg.Pixels.size()-1)
672                        {
673                            lastGoodPt=currentPt;
674                            pts.add(currentPt);
675                            ptsGeo.add(currentPtGeo);
676                            foundGoodPt=true;
677                        }
678                        break;
679                }
680            }
681            if(foundGoodPt==true)
682            {
683                tg.Pixels=pts;
684                tg.LatLongs=ptsGeo;
685            }
686        }
687        catch(Exception exc)
688        {
689            ErrorLogger.LogException("clsUtility", "FilterPoints",
690                    new RendererException("Failed inside FilterPoints", exc));
691
692        }
693    }
694
695    public static ArrayList<POINT2> PixelsToLatLong(ArrayList<POINT2> pts, IPointConversion converter)
696    {
697        int j=0;
698        POINT2 pt=null;
699        POINT2 ptGeo=null;
700        ArrayList<POINT2> ptsGeo=new ArrayList();
701        int n=pts.size();
702        //for(j=0;j<pts.size();j++)
703        for(j=0;j<n;j++)
704        {
705            pt=pts.get(j);
706            ptGeo=PointPixelsToLatLong(pt,converter);
707            ptsGeo.add(ptGeo);
708        }
709        return ptsGeo;
710    }
711
712    protected static ArrayList<POINT2> LatLongToPixels(ArrayList<POINT2> pts, IPointConversion converter)
713    {
714        int j=0;
715        POINT2 pt=null;
716        POINT2 ptPixels=null;
717        ArrayList<POINT2> ptsPixels=new ArrayList();
718        int n=pts.size();
719        //for(j=0;j<pts.size();j++)
720        for(j=0;j<n;j++)
721        {
722            pt=pts.get(j);
723            ptPixels=PointLatLongToPixels(pt,converter);
724            ptsPixels.add(ptPixels);
725        }
726        return ptsPixels;
727    }
728
729    private static POINT2 PointLatLongToPixels(POINT2 ptLatLong,IPointConversion converter)
730    {
731        POINT2 pt2 = new POINT2();
732        try
733        {
734            Point2D pt2d=POINT2ToPoint2D(ptLatLong);            
735            pt2d=converter.GeoToPixels(pt2d);
736            pt2=Point2DToPOINT2(pt2d);
737            pt2.style=ptLatLong.style;
738        } catch (Exception e) {
739            armyc2.c5isr.JavaTacticalRenderer.clsUtility.WriteFile("Error in clsUtility.PointLatLongToPixels");
740        }
741        return pt2;
742    }
743
744    protected static void FilterAXADPoints(TGLight tg, IPointConversion converter) {
745        try {
746            int lineType = tg.get_LineType();
747            switch (lineType) {
748                case TacticalLines.CATK:
749                case TacticalLines.CATKBYFIRE:
750                case TacticalLines.AIRAOA:
751                case TacticalLines.AAAAA:
752                case TacticalLines.SPT:
753                case TacticalLines.FRONTAL_ATTACK:
754                case TacticalLines.TURNING_MOVEMENT:
755                case TacticalLines.MOVEMENT_TO_CONTACT:
756                case TacticalLines.MAIN:
757                    break;
758                default:
759                    return;
760            }
761            int j=0;
762            ArrayList<POINT2> pts = new ArrayList();
763            ArrayList<POINT2> ptsGeo = new ArrayList();
764            POINT2 pt0 = tg.Pixels.get(0);
765            POINT2 pt1 = tg.Pixels.get(1);
766
767            Point2D pt=new Point2D.Double(pt1.x,pt1.y);
768            Point2D pt1Geo2d=converter.PixelsToGeo(pt);
769
770            POINT2 pt1geo=new POINT2(pt1Geo2d.getX(),pt1Geo2d.getY());
771            POINT2 ptj=null,ptjGeo=null;
772            POINT2 controlPt=tg.Pixels.get(tg.Pixels.size()-1); //the control point
773            POINT2 pt0Relative=lineutility.PointRelativeToLine(pt0, pt1, pt0, controlPt);
774            double relativeDist=lineutility.CalcDistanceDouble(pt0Relative, controlPt);
775            relativeDist += 5;
776            double pt0pt1dist=lineutility.CalcDistanceDouble(pt0, pt1);
777            boolean foundGoodPoint=false;
778            if(relativeDist>pt0pt1dist)
779            {
780                //first point is too close, begin rebuilding the arrays
781                pts.add(pt0);
782                pt=new Point2D.Double(pt0.x,pt0.y);
783                pt1Geo2d=converter.PixelsToGeo(pt);
784
785                pt1geo=new POINT2(pt1Geo2d.getX(),pt1Geo2d.getY());
786                ptsGeo.add(pt1geo);
787                //create a good first point and add it to the array
788                pt1=lineutility.ExtendAlongLineDouble(pt0, pt1, relativeDist);
789                pts.add(pt1);
790
791                pt=new Point2D.Double(pt1.x,pt1.y);
792                pt1Geo2d=converter.PixelsToGeo(pt);
793                pt1geo=new POINT2(pt1Geo2d.getX(),pt1Geo2d.getY());
794                ptsGeo.add(pt1geo);
795            }
796            else
797            {
798                //the first point is good, there is no need to do anything
799                foundGoodPoint=true;
800                pts=tg.Pixels;
801                ptsGeo=tg.LatLongs;
802            }
803
804            //do not add mores points to the array until we find at least one good point
805            int n=tg.Pixels.size();
806            if(foundGoodPoint==false)
807            {
808                //for(j=2;j<tg.Pixels.size()-1;j++)
809                for(j=2;j<n-1;j++)
810                {
811                    ptj=tg.Pixels.get(j);
812                    ptjGeo=tg.LatLongs.get(j);
813                    if(foundGoodPoint)
814                    {
815                       //then stuff the remainder of the arrays with the original points
816                        pts.add(ptj);
817                        ptsGeo.add(ptjGeo);
818                    }
819                    else    //no good points yet
820                    {
821                        //calculate the distance and continue if it is no good
822                        pt0pt1dist=lineutility.CalcDistanceDouble(pt0, ptj);
823                        if(relativeDist>pt0pt1dist)
824                            continue;
825                        else
826                        {
827                           //found a good point
828                           pts.add(ptj);
829                           ptsGeo.add(ptjGeo);
830                           //set the boolean so that it will stuff the array with the rest of the points
831                           foundGoodPoint=true;
832                        }
833                    }
834                }
835                //finally add the control point to the arrays and set the arrays
836                pts.add(controlPt);
837                //pt1Geo2d=converter.convertPixelsToLonLat(controlPt.x, controlPt.y);
838                pt=new Point2D.Double(controlPt.x, controlPt.y);
839                pt1Geo2d=converter.PixelsToGeo(pt);
840
841                pt1geo=new POINT2(pt1Geo2d.getX(),pt1Geo2d.getY());
842                ptsGeo.add(pt1geo);
843            }   //end if foundGoodPoint is false
844
845            //add all the successive points which are far enough apart
846            POINT2 lastGoodPt=pts.get(1);
847            POINT2 currentPt=null;
848            POINT2 currentPtGeo=null;
849            double dist=0;
850            tg.Pixels=new ArrayList();
851            tg.LatLongs=new ArrayList();
852            for(j=0;j<2;j++)
853            {
854                tg.Pixels.add(pts.get(j));
855                tg.LatLongs.add(ptsGeo.get(j));
856            }
857            n=pts.size();
858            //for(j=2;j<pts.size()-1;j++)
859            for(j=2;j<n-1;j++)
860            {
861                currentPt=pts.get(j);
862                currentPtGeo=ptsGeo.get(j);
863                dist=lineutility.CalcDistanceDouble(currentPt, lastGoodPt);
864                if(dist>5)
865                {
866                    lastGoodPt=currentPt;
867                    tg.Pixels.add(currentPt);
868                    tg.LatLongs.add(currentPtGeo);
869                }
870            }
871            //add the control point
872            tg.Pixels.add(pts.get(pts.size()-1));
873            tg.LatLongs.add(ptsGeo.get(ptsGeo.size()-1));
874        }
875        catch (Exception exc) {
876            ErrorLogger.LogException("clsUtility", "FilterAXADPoints",
877                    new RendererException("Failed inside FilterAXADPoints", exc));
878
879        }
880    }
881    /**
882     *
883     * @param tg
884     */
885    protected static void RemoveDuplicatePoints(TGLight tg)
886    {
887        try
888        {
889            //do not remove autoshape duplicate points
890//            if(isAutoshape(tg))
891//                return;
892            switch (tg.get_LineType()) {
893                case TacticalLines.SC:
894                case TacticalLines.MRR:
895                case TacticalLines.SL:
896                case TacticalLines.TC:
897                case TacticalLines.LLTR:
898                case TacticalLines.AC:
899                case TacticalLines.SAAFR:
900                    break;
901                default:
902                    if(isAutoshape(tg))
903                        return;
904            }
905
906            //we assume tg.H to have colors if it is comma delimited.
907            //only exit if colors are not set
908            switch(tg.get_LineType())   //preserve segment data
909            {
910                case TacticalLines.CATK:
911                case TacticalLines.AIRAOA:
912                case TacticalLines.AAAAA:
913                case TacticalLines.SPT:
914                case TacticalLines.FRONTAL_ATTACK:
915                case TacticalLines.TURNING_MOVEMENT:
916                case TacticalLines.MOVEMENT_TO_CONTACT:
917                case TacticalLines.MAIN:
918                case TacticalLines.CATKBYFIRE:  //80
919                    return;
920                case TacticalLines.BOUNDARY:
921                case TacticalLines.MSR:
922                case TacticalLines.ASR:
923                case TacticalLines.TRAFFIC_ROUTE:
924                    String strH=tg.get_H();
925                    if(strH != null && !strH.isEmpty())
926                    {
927                        String[] strs=strH.split(",");
928                        if(strs.length>1)
929                            return;
930                    }
931                    break;
932                default:
933                    break;
934            }
935            int linetype=tg.get_LineType();
936            if(armyc2.c5isr.JavaTacticalRenderer.clsUtility.IsChange1Area(linetype))
937                return;
938
939            POINT2 ptCurrent=null;
940            POINT2 ptLast=null;
941            Boolean isClosedPolygon= armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(tg.get_LineType());
942            int minSize=2;
943            if(isClosedPolygon)
944                minSize=3;
945            for(int j=1;j<tg.Pixels.size();j++)
946            {
947                ptLast=new POINT2(tg.Pixels.get(j-1));
948                ptCurrent=new POINT2(tg.Pixels.get(j));
949                //if(ptCurrent.x==ptLast.x && ptCurrent.y==ptLast.y)
950                if (Math.abs(ptCurrent.x - ptLast.x)<0.5 && Math.abs(ptCurrent.y - ptLast.y)<0.5)
951                {
952                    if(tg.Pixels.size()>minSize)
953                    {
954                        tg.Pixels.remove(j);
955                        tg.LatLongs.remove(j);
956                        j=1;
957                    }
958                }
959            }
960        }
961        catch(Exception exc)
962        {
963            ErrorLogger.LogException("clsUtility", "RemoveDuplicatePoints",
964                    new RendererException("Failed inside RemoveDuplicatePoints", exc));
965
966        }
967    }
968    protected static POINT2 PointPixelsToLatLong(POINT2 ptPixels,IPointConversion converter)
969    {
970        POINT2 pt2 = new POINT2();
971        try
972        {
973            //Point pt=POINT2ToPoint(ptPixels);
974            Point2D pt=new Point2D.Double(ptPixels.x,ptPixels.y);
975            Point2D pt2d=converter.PixelsToGeo(pt);
976            pt2=Point2DToPOINT2(pt2d);
977            pt2.style=ptPixels.style;
978
979        }
980        catch(Exception exc)
981        {
982            ErrorLogger.LogException("clsUtility" ,"PointPixelsToLatLong",
983                    new RendererException("Could not convert point to geo", exc));
984        }
985        return pt2;
986    }
987    
988    protected static Rectangle2D getMBR(ArrayList<Point2D> clipBounds)
989    {
990        Rectangle2D rect=null;
991        try
992        {
993            int j=0;
994            Point2D pt=null;
995            double xmax=clipBounds.get(0).getX(),xmin=xmax,ymax=clipBounds.get(0).getY(),ymin=ymax;
996            int n=clipBounds.size();
997            //for(j=0;j<clipBounds.size();j++)
998            for(j=0;j<n;j++)
999            {
1000                pt=clipBounds.get(j);
1001                if(pt.getX()<xmin)
1002                    xmin=pt.getX();
1003                if(pt.getX()>xmax)
1004                    xmax=pt.getX();
1005                if(pt.getY()<=ymin)
1006                    ymin=pt.getY();
1007                if(pt.getY()>ymax)
1008                    ymax=pt.getY();
1009            }
1010            rect=new Rectangle2D.Double(xmin, ymin, xmax-xmin, ymax-ymin);
1011        }
1012        catch (Exception exc) {
1013            ErrorLogger.LogException(_className, "AddBoundaryPointsForLines",
1014                    new RendererException("Failed inside AddBoundaryPointsForLines", exc));
1015        }
1016        return rect;
1017    }
1018
1019    static void GetMBR(ArrayList<Shape2> shapes,
1020                              POINT2 ptUl,
1021                              POINT2 ptUr,
1022                              POINT2 ptLr,
1023                              POINT2 ptLl) {
1024        try {
1025            POINT2 firstPoint = shapes.get(0).getPoints().get(0);
1026            ptUl.x = firstPoint.x;
1027            ptUl.y = firstPoint.y;
1028            ptUr.x = firstPoint.x;
1029            ptUr.y = firstPoint.y;
1030            ptLl.x = firstPoint.x;
1031            ptLl.y = firstPoint.y;
1032            ptLr.x = firstPoint.x;
1033            ptLr.y = firstPoint.y;
1034            for (Shape2 shape: shapes) {
1035                ArrayList<POINT2> points = shape.getPoints();
1036                for (int j = 0; j < points.size(); j++) {
1037                    double x = points.get(j).x;
1038                    double y = points.get(j).y;
1039                    if (x < ptLl.x) {
1040                        ptLl.x = x;
1041                        ptUl.x = x;
1042                    }
1043                    if (x > ptLr.x) {
1044                        ptLr.x = x;
1045                        ptUr.x = x;
1046                    }
1047                    if (y > ptLl.y) {
1048                        ptLl.y = y;
1049                        ptLr.y = y;
1050                    }
1051                    if (y < ptUl.y) {
1052                        ptUl.y = y;
1053                        ptUr.y = y;
1054                    }
1055                }
1056            }
1057
1058        } catch (Exception exc) {
1059            ErrorLogger.LogException(_className, "GetMBR",
1060                    new RendererException("Failed inside GetMBR", exc));
1061        }
1062    }
1063}