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