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 = (float) (tg.get_LineThickness() / 2.0);
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 = tg.get_LineThickness();
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.FSCL:
466            case TacticalLines.BCL_REVD:
467            case TacticalLines.BCL:
468            case TacticalLines.ICL:
469            case TacticalLines.IFF_OFF:
470            case TacticalLines.IFF_ON:
471            case TacticalLines.GENERIC_LINE:
472            case TacticalLines.FPF:
473            case TacticalLines.LINTGT:
474            case TacticalLines.LINTGTS:
475            case TacticalLines.MSDZ:
476            case TacticalLines.GAP:
477            case TacticalLines.IL:
478            case TacticalLines.DIRATKAIR:
479            case TacticalLines.PDF:
480            case TacticalLines.AC:
481            case TacticalLines.SAAFR:
482            case TacticalLines.LLTR:
483            case TacticalLines.SC:
484            case TacticalLines.MRR:
485            case TacticalLines.SL:
486            case TacticalLines.TC:
487            case TacticalLines.BOUNDARY:
488            case TacticalLines.WDRAWUP:
489            case TacticalLines.WITHDRAW:
490            case TacticalLines.RETIRE:
491            case TacticalLines.FPOL:
492            case TacticalLines.RPOL:
493            case TacticalLines.RIP:
494            case TacticalLines.DELAY:
495            case TacticalLines.CATK:
496            case TacticalLines.CATKBYFIRE:
497            case TacticalLines.SCREEN:
498            case TacticalLines.COVER:
499            case TacticalLines.GUARD:
500            case TacticalLines.FLOT:
501            case TacticalLines.LC:
502            case TacticalLines.PL:
503            case TacticalLines.FEBA:
504            case TacticalLines.LL:
505            case TacticalLines.EWL:
506            case TacticalLines.FCL:
507            case TacticalLines.HOLD:
508            case TacticalLines.BRDGHD:
509            case TacticalLines.HOLD_GE:
510            case TacticalLines.BRDGHD_GE:
511            case TacticalLines.LOA:
512            case TacticalLines.LOD:
513            case TacticalLines.LDLC:
514            case TacticalLines.PLD:
515            case TacticalLines.RELEASE:
516            case TacticalLines.HOL:
517            case TacticalLines.BHL:
518                result = true;
519                break;
520            default:
521                break;
522        }
523        if(armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(linetype)==true)
524            result=true;
525        return result;
526    }
527
528    /**
529     * @deprecated
530     */
531    protected static void FilterPoints(TGLight tg)
532    {
533        try
534        {
535            int lineType = tg.get_LineType();
536            double minSpikeDistance = 0;
537            switch (lineType)
538            {
539                //case TacticalLines.LC:
540                case TacticalLines.ATDITCH:
541                case TacticalLines.ATDITCHC:
542                case TacticalLines.ATDITCHM:
543                case TacticalLines.FLOT:
544                case TacticalLines.FORT_REVD:
545                case TacticalLines.FORT:
546                case TacticalLines.FORTL:
547                case TacticalLines.STRONG:
548                    minSpikeDistance=25;
549                    break;
550                case TacticalLines.LC:
551                case TacticalLines.OBSAREA:
552                case TacticalLines.OBSFAREA:
553                case TacticalLines.ENCIRCLE:
554                case TacticalLines.ZONE:
555                case TacticalLines.LINE:
556                case TacticalLines.ATWALL:
557                case TacticalLines.UNSP:
558                case TacticalLines.SFENCE:
559                case TacticalLines.DFENCE:
560                case TacticalLines.DOUBLEA:
561                case TacticalLines.LWFENCE:
562                case TacticalLines.HWFENCE:
563                case TacticalLines.SINGLEC:
564                case TacticalLines.DOUBLEC:
565                case TacticalLines.TRIPLE:
566                    minSpikeDistance=35;
567                    break;
568                case TacticalLines.UCF:
569                case TacticalLines.CF:
570                case TacticalLines.CFG:
571                case TacticalLines.CFY:
572                    minSpikeDistance=60;
573                    break;
574                case TacticalLines.SF:
575                case TacticalLines.USF:
576                case TacticalLines.OCCLUDED:
577                case TacticalLines.UOF:
578                    minSpikeDistance=60;//was 120
579                    break;
580                case TacticalLines.SFG:
581                case TacticalLines.SFY:
582                    minSpikeDistance=60;//was 180
583                    break;
584                case TacticalLines.WFY:
585                case TacticalLines.WFG:
586                case TacticalLines.OFY:
587                    minSpikeDistance=60;//was 120
588                    break;
589                case TacticalLines.WF:
590                case TacticalLines.UWF:
591                    minSpikeDistance=40;
592                    break;
593
594                case TacticalLines.RIDGE:
595                case TacticalLines.ICE_EDGE_RADAR:  //METOCs
596                case TacticalLines.ICE_OPENINGS_FROZEN:
597                case TacticalLines.CRACKS_SPECIFIC_LOCATION:
598                    minSpikeDistance=35;
599                    break;
600                default:
601                    return;
602            }
603            int j=0;
604            double dist=0;
605            ArrayList<POINT2>pts=new ArrayList();
606            ArrayList<POINT2>ptsGeo=new ArrayList();
607            pts.add(tg.Pixels.get(0));
608            ptsGeo.add(tg.LatLongs.get(0));
609            POINT2 lastGoodPt=tg.Pixels.get(0);
610            POINT2 currentPt=null;
611            POINT2 currentPtGeo=null;
612            boolean foundGoodPt=false;
613            int n=tg.Pixels.size();
614            //for(j=1;j<tg.Pixels.size();j++)
615            for(j=1;j<n;j++)
616            {
617                //we can not filter out the original end points
618                currentPt=tg.Pixels.get(j);
619                currentPtGeo=tg.LatLongs.get(j);
620                if(currentPt.style==-1)
621                {
622                    lastGoodPt=currentPt;
623                    pts.add(currentPt);
624                    ptsGeo.add(currentPtGeo);
625                    foundGoodPt=true;
626                    currentPt.style=0;
627                    continue;
628                }
629                dist=lineutility.CalcDistanceDouble(lastGoodPt, currentPt);
630                switch(lineType)
631                {
632                    case TacticalLines.LC:
633                        if(dist>minSpikeDistance)
634                        {
635                            lastGoodPt=currentPt;
636                            pts.add(currentPt);
637                            ptsGeo.add(currentPtGeo);
638                            foundGoodPt=true;
639                        }
640                        else
641                        {   //the last point is no good
642                            //replace the last good point with the last point
643                            if(j==tg.Pixels.size()-1)
644                            {
645                                pts.set(pts.size()-1, currentPt);
646                                ptsGeo.set(ptsGeo.size()-1, currentPtGeo);
647                            }
648                        }
649                        break;
650                    default:
651                        if(dist>minSpikeDistance || j==tg.Pixels.size()-1)
652                        {
653                            lastGoodPt=currentPt;
654                            pts.add(currentPt);
655                            ptsGeo.add(currentPtGeo);
656                            foundGoodPt=true;
657                        }
658                        break;
659                }
660            }
661            if(foundGoodPt==true)
662            {
663                tg.Pixels=pts;
664                tg.LatLongs=ptsGeo;
665            }
666        }
667        catch(Exception exc)
668        {
669            ErrorLogger.LogException("clsUtility", "FilterPoints",
670                    new RendererException("Failed inside FilterPoints", exc));
671
672        }
673    }
674
675    public static ArrayList<POINT2> PixelsToLatLong(ArrayList<POINT2> pts, IPointConversion converter)
676    {
677        int j=0;
678        POINT2 pt=null;
679        POINT2 ptGeo=null;
680        ArrayList<POINT2> ptsGeo=new ArrayList();
681        int n=pts.size();
682        //for(j=0;j<pts.size();j++)
683        for(j=0;j<n;j++)
684        {
685            pt=pts.get(j);
686            ptGeo=PointPixelsToLatLong(pt,converter);
687            ptsGeo.add(ptGeo);
688        }
689        return ptsGeo;
690    }
691
692    protected static ArrayList<POINT2> LatLongToPixels(ArrayList<POINT2> pts, IPointConversion converter)
693    {
694        int j=0;
695        POINT2 pt=null;
696        POINT2 ptPixels=null;
697        ArrayList<POINT2> ptsPixels=new ArrayList();
698        int n=pts.size();
699        //for(j=0;j<pts.size();j++)
700        for(j=0;j<n;j++)
701        {
702            pt=pts.get(j);
703            ptPixels=PointLatLongToPixels(pt,converter);
704            ptsPixels.add(ptPixels);
705        }
706        return ptsPixels;
707    }
708
709    private static POINT2 PointLatLongToPixels(POINT2 ptLatLong,IPointConversion converter)
710    {
711        POINT2 pt2 = new POINT2();
712        try
713        {
714            Point2D pt2d=POINT2ToPoint2D(ptLatLong);            
715            pt2d=converter.GeoToPixels(pt2d);
716            pt2=Point2DToPOINT2(pt2d);
717            pt2.style=ptLatLong.style;
718        } catch (Exception e) {
719            armyc2.c5isr.JavaTacticalRenderer.clsUtility.WriteFile("Error in clsUtility.PointLatLongToPixels");
720        }
721        return pt2;
722    }
723
724    protected static void FilterAXADPoints(TGLight tg, IPointConversion converter) {
725        try {
726            int lineType = tg.get_LineType();
727            switch (lineType) {
728                case TacticalLines.CATK:
729                case TacticalLines.CATKBYFIRE:
730                case TacticalLines.AIRAOA:
731                case TacticalLines.AAAAA:
732                case TacticalLines.SPT:
733                case TacticalLines.MAIN:
734                    break;
735                default:
736                    return;
737            }
738            int j=0;
739            ArrayList<POINT2> pts = new ArrayList();
740            ArrayList<POINT2> ptsGeo = new ArrayList();
741            POINT2 pt0 = tg.Pixels.get(0);
742            POINT2 pt1 = tg.Pixels.get(1);
743
744            Point2D pt=new Point2D.Double(pt1.x,pt1.y);
745            Point2D pt1Geo2d=converter.PixelsToGeo(pt);
746
747            POINT2 pt1geo=new POINT2(pt1Geo2d.getX(),pt1Geo2d.getY());
748            POINT2 ptj=null,ptjGeo=null;
749            POINT2 controlPt=tg.Pixels.get(tg.Pixels.size()-1); //the control point
750            POINT2 pt0Relative=lineutility.PointRelativeToLine(pt0, pt1, pt0, controlPt);
751            double relativeDist=lineutility.CalcDistanceDouble(pt0Relative, controlPt);
752            relativeDist += 5;
753            double pt0pt1dist=lineutility.CalcDistanceDouble(pt0, pt1);
754            boolean foundGoodPoint=false;
755            if(relativeDist>pt0pt1dist)
756            {
757                //first point is too close, begin rebuilding the arrays
758                pts.add(pt0);
759                pt=new Point2D.Double(pt0.x,pt0.y);
760                pt1Geo2d=converter.PixelsToGeo(pt);
761
762                pt1geo=new POINT2(pt1Geo2d.getX(),pt1Geo2d.getY());
763                ptsGeo.add(pt1geo);
764                //create a good first point and add it to the array
765                pt1=lineutility.ExtendAlongLineDouble(pt0, pt1, relativeDist);
766                pts.add(pt1);
767
768                pt=new Point2D.Double(pt1.x,pt1.y);
769                pt1Geo2d=converter.PixelsToGeo(pt);
770                pt1geo=new POINT2(pt1Geo2d.getX(),pt1Geo2d.getY());
771                ptsGeo.add(pt1geo);
772            }
773            else
774            {
775                //the first point is good, there is no need to do anything
776                foundGoodPoint=true;
777                pts=tg.Pixels;
778                ptsGeo=tg.LatLongs;
779            }
780
781            //do not add mores points to the array until we find at least one good point
782            int n=tg.Pixels.size();
783            if(foundGoodPoint==false)
784            {
785                //for(j=2;j<tg.Pixels.size()-1;j++)
786                for(j=2;j<n-1;j++)
787                {
788                    ptj=tg.Pixels.get(j);
789                    ptjGeo=tg.LatLongs.get(j);
790                    if(foundGoodPoint)
791                    {
792                       //then stuff the remainder of the arrays with the original points
793                        pts.add(ptj);
794                        ptsGeo.add(ptjGeo);
795                    }
796                    else    //no good points yet
797                    {
798                        //calculate the distance and continue if it is no good
799                        pt0pt1dist=lineutility.CalcDistanceDouble(pt0, ptj);
800                        if(relativeDist>pt0pt1dist)
801                            continue;
802                        else
803                        {
804                           //found a good point
805                           pts.add(ptj);
806                           ptsGeo.add(ptjGeo);
807                           //set the boolean so that it will stuff the array with the rest of the points
808                           foundGoodPoint=true;
809                        }
810                    }
811                }
812                //finally add the control point to the arrays and set the arrays
813                pts.add(controlPt);
814                //pt1Geo2d=converter.convertPixelsToLonLat(controlPt.x, controlPt.y);
815                pt=new Point2D.Double(controlPt.x, controlPt.y);
816                pt1Geo2d=converter.PixelsToGeo(pt);
817
818                pt1geo=new POINT2(pt1Geo2d.getX(),pt1Geo2d.getY());
819                ptsGeo.add(pt1geo);
820            }   //end if foundGoodPoint is false
821
822            //add all the successive points which are far enough apart
823            POINT2 lastGoodPt=pts.get(1);
824            POINT2 currentPt=null;
825            POINT2 currentPtGeo=null;
826            double dist=0;
827            tg.Pixels=new ArrayList();
828            tg.LatLongs=new ArrayList();
829            for(j=0;j<2;j++)
830            {
831                tg.Pixels.add(pts.get(j));
832                tg.LatLongs.add(ptsGeo.get(j));
833            }
834            n=pts.size();
835            //for(j=2;j<pts.size()-1;j++)
836            for(j=2;j<n-1;j++)
837            {
838                currentPt=pts.get(j);
839                currentPtGeo=ptsGeo.get(j);
840                dist=lineutility.CalcDistanceDouble(currentPt, lastGoodPt);
841                if(dist>5)
842                {
843                    lastGoodPt=currentPt;
844                    tg.Pixels.add(currentPt);
845                    tg.LatLongs.add(currentPtGeo);
846                }
847            }
848            //add the control point
849            tg.Pixels.add(pts.get(pts.size()-1));
850            tg.LatLongs.add(ptsGeo.get(ptsGeo.size()-1));
851        }
852        catch (Exception exc) {
853            ErrorLogger.LogException("clsUtility", "FilterAXADPoints",
854                    new RendererException("Failed inside FilterAXADPoints", exc));
855
856        }
857    }
858    /**
859     *
860     * @param tg
861     */
862    protected static void RemoveDuplicatePoints(TGLight tg)
863    {
864        try
865        {
866            //do not remove autoshape duplicate points
867//            if(isAutoshape(tg))
868//                return;
869            switch (tg.get_LineType()) {
870                case TacticalLines.SC:
871                case TacticalLines.MRR:
872                case TacticalLines.SL:
873                case TacticalLines.TC:
874                case TacticalLines.LLTR:
875                case TacticalLines.AC:
876                case TacticalLines.SAAFR:
877                    break;
878                default:
879                    if(isAutoshape(tg))
880                        return;
881            }
882
883            //we assume tg.H to have colors if it is comma delimited.
884            //only exit if colors are not set
885            switch(tg.get_LineType())   //preserve segment data
886            {
887                case TacticalLines.CATK:
888                case TacticalLines.AIRAOA:
889                case TacticalLines.AAAAA:
890                case TacticalLines.SPT:
891                case TacticalLines.MAIN:
892                case TacticalLines.CATKBYFIRE:  //80
893                    return;
894                case TacticalLines.BOUNDARY:
895                case TacticalLines.MSR:
896                case TacticalLines.ASR:
897                case TacticalLines.ROUTE:
898                    String strH=tg.get_H();
899                    if(strH != null && !strH.isEmpty())
900                    {
901                        String[] strs=strH.split(",");
902                        if(strs.length>1)
903                            return;
904                    }
905                    break;
906                default:
907                    break;
908            }
909            int linetype=tg.get_LineType();
910            if(armyc2.c5isr.JavaTacticalRenderer.clsUtility.IsChange1Area(linetype))
911                return;
912
913            POINT2 ptCurrent=null;
914            POINT2 ptLast=null;
915            Boolean isClosedPolygon= armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(tg.get_LineType());
916            int minSize=2;
917            if(isClosedPolygon)
918                minSize=3;
919            for(int j=1;j<tg.Pixels.size();j++)
920            {
921                ptLast=new POINT2(tg.Pixels.get(j-1));
922                ptCurrent=new POINT2(tg.Pixels.get(j));
923                //if(ptCurrent.x==ptLast.x && ptCurrent.y==ptLast.y)
924                if (Math.abs(ptCurrent.x - ptLast.x)<0.5 && Math.abs(ptCurrent.y - ptLast.y)<0.5)
925                {
926                    if(tg.Pixels.size()>minSize)
927                    {
928                        tg.Pixels.remove(j);
929                        tg.LatLongs.remove(j);
930                        j=1;
931                    }
932                }
933            }
934        }
935        catch(Exception exc)
936        {
937            ErrorLogger.LogException("clsUtility", "RemoveDuplicatePoints",
938                    new RendererException("Failed inside RemoveDuplicatePoints", exc));
939
940        }
941    }
942    protected static POINT2 PointPixelsToLatLong(POINT2 ptPixels,IPointConversion converter)
943    {
944        POINT2 pt2 = new POINT2();
945        try
946        {
947            //Point pt=POINT2ToPoint(ptPixels);
948            Point2D pt=new Point2D.Double(ptPixels.x,ptPixels.y);
949            Point2D pt2d=converter.PixelsToGeo(pt);
950            pt2=Point2DToPOINT2(pt2d);
951            pt2.style=ptPixels.style;
952
953        }
954        catch(Exception exc)
955        {
956            ErrorLogger.LogException("clsUtility" ,"PointPixelsToLatLong",
957                    new RendererException("Could not convert point to geo", exc));
958        }
959        return pt2;
960    }
961    
962    protected static Rectangle2D getMBR(ArrayList<Point2D> clipBounds)
963    {
964        Rectangle2D rect=null;
965        try
966        {
967            int j=0;
968            Point2D pt=null;
969            double xmax=clipBounds.get(0).getX(),xmin=xmax,ymax=clipBounds.get(0).getY(),ymin=ymax;
970            int n=clipBounds.size();
971            //for(j=0;j<clipBounds.size();j++)
972            for(j=0;j<n;j++)
973            {
974                pt=clipBounds.get(j);
975                if(pt.getX()<xmin)
976                    xmin=pt.getX();
977                if(pt.getX()>xmax)
978                    xmax=pt.getX();
979                if(pt.getY()<=ymin)
980                    ymin=pt.getY();
981                if(pt.getY()>ymax)
982                    ymax=pt.getY();
983            }
984            rect=new Rectangle2D.Double(xmin, ymin, xmax-xmin, ymax-ymin);
985        }
986        catch (Exception exc) {
987            ErrorLogger.LogException(_className, "AddBoundaryPointsForLines",
988                    new RendererException("Failed inside AddBoundaryPointsForLines", exc));
989        }
990        return rect;
991    }
992
993    static void GetMBR(ArrayList<Shape2> shapes,
994                              POINT2 ptUl,
995                              POINT2 ptUr,
996                              POINT2 ptLr,
997                              POINT2 ptLl) {
998        try {
999            POINT2 firstPoint = shapes.get(0).getPoints().get(0);
1000            ptUl.x = firstPoint.x;
1001            ptUl.y = firstPoint.y;
1002            ptUr.x = firstPoint.x;
1003            ptUr.y = firstPoint.y;
1004            ptLl.x = firstPoint.x;
1005            ptLl.y = firstPoint.y;
1006            ptLr.x = firstPoint.x;
1007            ptLr.y = firstPoint.y;
1008            for (Shape2 shape: shapes) {
1009                ArrayList<POINT2> points = shape.getPoints();
1010                for (int j = 0; j < points.size(); j++) {
1011                    double x = points.get(j).x;
1012                    double y = points.get(j).y;
1013                    if (x < ptLl.x) {
1014                        ptLl.x = x;
1015                        ptUl.x = x;
1016                    }
1017                    if (x > ptLr.x) {
1018                        ptLr.x = x;
1019                        ptUr.x = x;
1020                    }
1021                    if (y > ptLl.y) {
1022                        ptLl.y = y;
1023                        ptLr.y = y;
1024                    }
1025                    if (y < ptUl.y) {
1026                        ptUl.y = y;
1027                        ptUr.y = y;
1028                    }
1029                }
1030            }
1031
1032        } catch (Exception exc) {
1033            ErrorLogger.LogException(_className, "GetMBR",
1034                    new RendererException("Failed inside GetMBR", exc));
1035        }
1036    }
1037}