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