001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package armyc2.c5isr.RenderMultipoints;
006
007import armyc2.c5isr.JavaTacticalRenderer.clsUtility;
008import armyc2.c5isr.JavaTacticalRenderer.TGLight;
009import java.util.ArrayList;
010import armyc2.c5isr.renderer.utilities.ErrorLogger;
011import armyc2.c5isr.renderer.utilities.RendererException;
012import armyc2.c5isr.JavaLineArray.POINT2;
013import armyc2.c5isr.JavaLineArray.TacticalLines;
014import armyc2.c5isr.JavaLineArray.Shape2;
015import java.util.HashMap;
016import java.util.Map;
017import armyc2.c5isr.graphics2d.*;
018import armyc2.c5isr.graphics2d.Line2D;
019import armyc2.c5isr.graphics2d.Point2D;
020import armyc2.c5isr.graphics2d.Rectangle2D;
021
022/**
023 * A class to clip tactical lines and areas
024*
025 */
026public final class clsClipPolygon2 {
027
028    private static final String _className = "clsClipPolygon2";
029    /**
030     * Calculate the point the line intersects an edge of the clipbounds
031     * @param pt0 start point of the line
032     * @param pt1 end point of the line
033     * @param currentEdge
034     * @return
035     */
036    private static Point2D intersectPoint(Point2D pt0,
037                                          Point2D pt1,
038                                          Line2D currentEdge) {
039        Point2D ptIntersect = null;
040        try {
041            Point2D edgePt1 = currentEdge.getP1();
042            Point2D edgePt2 = currentEdge.getP2();
043            double edge_x = 0, edge_y = 0, m = 0;
044            double deltaX = 0, deltaY = 0;
045            //vertical edge
046            if (Math.abs(edgePt1.getX() - edgePt2.getX()) < Math.abs(edgePt1.getY() - edgePt2.getY()))
047            {
048                ptIntersect=new Point2D.Double();
049                edge_x = edgePt1.getX();
050                //if (pt1.getX() == pt0.getX())
051                if (Math.abs(pt1.getX() - pt0.getX())<1)
052                    pt1.setLocation(pt1.getX()+1, pt1.getY());
053
054                m = (pt1.getY() - pt0.getY()) / (pt1.getX() - pt0.getX());
055                deltaX = edge_x - pt0.getX();
056                ptIntersect.setLocation(edge_x, pt0.getY() + m * deltaX);
057            }
058            //horizontal edge
059            else
060            {
061                ptIntersect=new Point2D.Double();
062                edge_y = edgePt1.getY();
063                //if (pt1.getX() == pt0.getX())
064                if (Math.abs(pt1.getX() - pt0.getX())<1)
065                    pt1.setLocation(pt1.getX()+1, pt1.getY());
066
067                m = (pt1.getY() - pt0.getY()) / (pt1.getX() - pt0.getX());
068                deltaY = edge_y - pt0.getY();
069                ptIntersect.setLocation(pt0.getX() + deltaY / m, edge_y);
070            }
071        } catch (Exception exc) {
072            ErrorLogger.LogException(_className, "intersectPoint",
073                    new RendererException("Failed inside intersectPoint", exc));
074        }
075        return ptIntersect;
076    }
077    /**
078     * clip the top
079     * on the line is considered inside
080     * @param pts
081     * @param clipBounds
082     * @return
083     */
084    private static ArrayList<Point2D> clipTop(TGLight tg,ArrayList<Point2D> pts,
085            Rectangle2D clipBounds) {
086        ArrayList<Point2D> ptsResult = new ArrayList();
087        try {
088            double ulx = 0, uly = 0, lrx = 0;// lry = 0;
089            ulx = clipBounds.getMinX();
090            uly = clipBounds.getMinY();
091            Point2D ul = new Point2D.Double(ulx, uly);
092            Point2D ur = new Point2D.Double(lrx, uly);
093
094            int j = 0;
095            Point2D current = null, previous = null;
096            Point2D intersectPt = null;
097            Line2D edge;
098            int n=pts.size();
099            //for (j = 0; j < pts.size(); j++) 
100            for (j = 0; j < n; j++) 
101            {
102                current = pts.get(j);
103                if (j == 0) 
104                {
105                    previous = pts.get(pts.size() - 1);
106                } 
107                else 
108                {
109                    previous = pts.get(j - 1);
110                }
111
112                //both inside
113                if (previous.getY() >= ul.getY() && current.getY() >= ul.getY()) {
114                    ptsResult.add(current);
115                }
116                //previous inside, current outside
117                if (previous.getY() >= ul.getY() && current.getY() < ul.getY()) {
118                    edge = new Line2D.Double(ul, ur);
119                    intersectPt = intersectPoint(previous, current, edge);
120                    if (intersectPt != null) {
121                        ptsResult.add(intersectPt);
122                    }
123                    tg.set_WasClipped(true);
124                }
125                //both outside
126                if (previous.getY() < ul.getY() && current.getY() < ul.getY()) {
127                    continue;
128                }
129
130                //previous outside current inside
131                if (previous.getY() < ul.getY() && current.getY() >= ul.getY()) {
132                    edge = new Line2D.Double(ul, ur);
133                    intersectPt = intersectPoint(previous, current, edge);
134                    if (intersectPt != null) {
135                        ptsResult.add(intersectPt);
136                    }
137                    ptsResult.add(current);
138                    tg.set_WasClipped(true);
139                }
140            }
141        } catch (Exception exc) {
142            ErrorLogger.LogException(_className, "clipTop",
143                    new RendererException("Failed inside clipTop", exc));
144        }
145        return ptsResult;
146    }
147    /**
148     * on the boundary is considered inside
149     * clip the bottom
150     * @param pts
151     * @param clipBounds
152     * @return
153     */
154    private static ArrayList<Point2D> clipBottom(TGLight tg, ArrayList<Point2D> pts,
155            Rectangle2D clipBounds) {
156        ArrayList<Point2D> ptsResult = new ArrayList();
157        try {
158            double ulx = 0, uly = 0, lrx = 0, lry = 0;
159            ulx = clipBounds.getMinX();
160            lrx = clipBounds.getMaxX();
161            lry = clipBounds.getMaxY();
162            Point2D ll = new Point2D.Double(ulx, lry);
163            Point2D lr = new Point2D.Double(lrx, lry);
164
165            int j = 0;
166            Point2D current = null, previous = null;
167            Point2D intersectPt = null;
168            Line2D edge;
169            int n=pts.size();
170            //for (j = 0; j < pts.size(); j++)
171            for (j = 0; j < n; j++)
172            {
173                current = pts.get(j);
174                if (j == 0)
175                {
176                    previous = pts.get(pts.size() - 1);
177                } 
178                else
179                {
180                    previous = pts.get(j - 1);
181                }
182
183                //both inside
184                if (previous.getY() <= lr.getY() && current.getY() <= lr.getY())
185                {
186                    ptsResult.add(current);
187                }
188                //previous inside, current outside
189                if (previous.getY() <= lr.getY() && current.getY() > lr.getY())
190                {
191                    edge = new Line2D.Double(ll, lr);
192                    intersectPt = intersectPoint(previous, current, edge);
193                    if (intersectPt != null)
194                    {
195                        ptsResult.add(intersectPt);
196                    }
197                    tg.set_WasClipped(true);
198                }
199                //both outside
200                if (previous.getY() > lr.getY() && current.getY() > lr.getY())
201                {
202                    continue;
203                }
204
205                //previous outside current inside
206                if (previous.getY() > lr.getY() && current.getY() <= lr.getY()) {
207                    edge = new Line2D.Double(ll, lr);
208                    intersectPt = intersectPoint(previous, current, edge);
209                    if (intersectPt != null) {
210                        ptsResult.add(intersectPt);
211                    }
212
213                    ptsResult.add(current);
214                    tg.set_WasClipped(true);
215                }
216            }
217        } catch (Exception exc) {
218            ErrorLogger.LogException(_className, "clipBottom",
219                    new RendererException("Failed inside clipBottom", exc));
220        }
221        return ptsResult;
222    }
223    /**
224     * on the bounds is considered inside
225     * clip the right side
226     * @param pts
227     * @param clipBounds
228     * @return
229     */
230    private static ArrayList<Point2D> clipRight(TGLight tg,ArrayList<Point2D> pts,
231            Rectangle2D clipBounds) {
232        ArrayList<Point2D> ptsResult = new ArrayList();
233        try {
234            double uly = 0, lrx = 0, lry = 0;
235            uly = clipBounds.getMinY();
236            lrx = clipBounds.getMaxX();
237            lry = clipBounds.getMaxY();
238            Point2D ur = new Point2D.Double(lrx, uly);
239            Point2D lr = new Point2D.Double(lrx, lry);
240            int j = 0;            
241            Point2D current = null, previous = null;
242            Point2D intersectPt = null;
243            Line2D edge;
244            int n=pts.size();
245            //for (j = 0; j < pts.size(); j++) 
246            for (j = 0; j < n; j++) 
247            {
248                current = pts.get(j);
249                if (j == 0) {
250                    previous = pts.get(pts.size() - 1);
251                } else {
252                    previous = pts.get(j - 1);
253                }
254
255                //both inside
256                if (previous.getX() <= lr.getX() && current.getX() <= lr.getX()) {
257                    ptsResult.add(current);
258                }
259                //previous inside, current outside
260                if (previous.getX() <= lr.getX() && current.getX() > lr.getX()) {
261                    edge = new Line2D.Double(ur, lr);
262                    intersectPt = intersectPoint(previous, current, edge);
263                    if (intersectPt != null) {                        
264                        ptsResult.add(intersectPt);                        
265                    }
266                    tg.set_WasClipped(true);
267                }
268                //both outside
269                if (previous.getX() > lr.getX() && current.getX() > lr.getX()) {
270                    continue;
271                }
272
273                //previous outside current inside
274                if (previous.getX() > lr.getX() && current.getX() <= lr.getX()) {
275                    edge = new Line2D.Double(ur, lr);
276                    intersectPt = intersectPoint(previous, current, edge);
277                    if (intersectPt != null) {
278                        ptsResult.add(intersectPt);
279                    }
280
281                    //if(j!=0 || clsUtility.isClosedPolygon(tg.get_LineType())==true)
282                    ptsResult.add(current);
283                    tg.set_WasClipped(true);
284                }
285            }
286        } catch (Exception exc) {
287            ErrorLogger.LogException(_className, "clipRight",
288                    new RendererException("Failed inside clipRight", exc));
289        }
290        return ptsResult;
291    }
292    /**
293     * on the line is considered inside
294     * clip the left side
295     * @param pts
296     * @param clipBounds
297     * @return
298     */
299    private static ArrayList<Point2D> clipLeft(TGLight tg, ArrayList<Point2D> pts,
300            Rectangle2D clipBounds) {
301        ArrayList<Point2D> ptsResult = new ArrayList();
302        try {
303            double ulx = 0, uly = 0, lry = 0;
304            ulx = clipBounds.getMinX();
305            uly = clipBounds.getMinY();
306            lry = clipBounds.getMaxY();
307            Point2D ul = new Point2D.Double(ulx, uly);
308            Point2D ll = new Point2D.Double(ulx, lry);
309
310            int j = 0;
311            Point2D current = null, previous = null;
312            Point2D intersectPt = null;
313            Line2D edge;     
314            int n=pts.size();
315            //for (j = 0; j < pts.size(); j++) 
316            for (j = 0; j < n; j++) 
317            {
318                current = pts.get(j);
319                if (j == 0) 
320                {
321                    previous = pts.get(pts.size() - 1);
322                } 
323                else 
324                {
325                    previous = pts.get(j - 1);
326                }
327
328                //both inside
329                if (previous.getX() >= ll.getX() && current.getX() >= ll.getX()) {
330                    ptsResult.add(current);
331                }
332                //previous inside, current outside
333                if (previous.getX() >= ll.getX() && current.getX() < ll.getX()) {
334                    edge = new Line2D.Double(ul, ll);
335                    intersectPt = intersectPoint(previous, current, edge);
336                    if (intersectPt != null) {
337                        ptsResult.add(intersectPt);
338                    }
339                    tg.set_WasClipped(true);
340                }
341                //both outside
342                if (previous.getX() < ll.getX() && current.getX() < ll.getX()) {
343                    continue;
344                }
345
346                //previous outside current inside
347                if (previous.getX() < ll.getX() && current.getX() >= ll.getX()) {
348                    edge = new Line2D.Double(ul, ll);
349                    intersectPt = intersectPoint(previous, current, edge);
350                    if (intersectPt != null) {
351                        ptsResult.add(intersectPt);
352                    }
353
354                    //if(j!=0 || clsUtility.isClosedPolygon(tg.get_LineType())==true)
355                    ptsResult.add(current);
356                    tg.set_WasClipped(true);
357                }
358            }
359        } catch (Exception exc) {
360            ErrorLogger.LogException(_className, "clipLeft",
361                    new RendererException("Failed inside clipLeft", exc));
362        }
363        return ptsResult;
364    }
365
366    /**
367     * for non-areas add points to the ends as necessary to make the algorithm work
368     * @param polygon
369     * @param clipBounds
370     */
371    private static int AddBoundaryPointsForLines(ArrayList<Point2D> polygon,
372            Rectangle2D clipBounds) {
373        int result = 0;
374        try {
375            double ulx = 0, uly = 0, lrx = 0, lry = 0;
376            ulx = clipBounds.getMinX();
377            uly = clipBounds.getMinY();
378            lrx = clipBounds.getMaxX();
379            lry = clipBounds.getMaxY();
380            //move these inside by 10 pixels so the algoithm will treat them as inside points
381            Point2D ul = new Point2D.Double(ulx + 10, uly + 10);
382            Point2D ur = new Point2D.Double(lrx - 10, uly + 10);
383            Point2D ll = new Point2D.Double(ulx + 10, lry - 10);
384            Point2D lr = new Point2D.Double(lrx - 10, lry - 10);
385
386            Point2D pt0 = polygon.get(0);
387            Point2D ptn = polygon.get(polygon.size() - 1);
388            //double dist0 = 0, dist1 = 0;
389            Boolean addToFront = false, addToEnd = false;
390            //add a point to the begining of the array
391            if (pt0.getY() < uly) //above the top clip
392            {
393                polygon.add(0, ul);
394                addToFront = true;
395            } else if (pt0.getX() < ulx) //outside the left clip
396            {
397                polygon.add(0, ul);
398                addToFront = true;
399            } else if (pt0.getX() > lrx) //outside the right clip
400            {
401                polygon.add(0, lr);
402                addToFront = true;
403            } else if (pt0.getY() > lry) //below the bottom clip
404            {
405                polygon.add(0, lr);
406                addToFront = true;
407            }
408
409            //add a point to the end of the array
410            if (ptn.getY() < uly) //above the top clip
411            {
412                polygon.add(ul);
413                addToEnd = true;
414            } else if (ptn.getX() < ulx) //outside the left clip
415            {
416                polygon.add(ul);
417                addToEnd = true;
418            } else if (ptn.getX() > lrx) //outside the right clip
419            {
420                polygon.add(lr);
421                addToEnd = true;
422            } else if (ptn.getY() > lry) //below the bottom clip
423            {
424                polygon.add(lr);
425                addToEnd = true;
426            }
427
428            if (addToFront == false && addToEnd == false) {
429                result = 0;
430            }
431            if (addToFront == true && addToEnd == false) {
432                result = 1;
433            }
434            if (addToFront == false && addToEnd == true) {
435                result = 2;
436            }
437            if (addToFront == true && addToEnd == true) {
438                result = 3;
439            }
440
441        } catch (Exception exc) {
442            ErrorLogger.LogException(_className, "AddBoundaryPointsForLines",
443                    new RendererException("Failed inside AddBoundaryPointsForLines", exc));
444        }
445        return result;
446    }
447    /**
448     * closes an area
449     * @param tg
450     */
451    private static void closeAreaTG(TGLight tg)
452    {
453        try
454        {
455            if(tg.Pixels==null || tg.Pixels.isEmpty())
456                return;
457
458            POINT2 pt0=tg.Pixels.get(0);
459            POINT2 ptn=tg.Pixels.get(tg.Pixels.size()-1);
460            if(pt0.x != ptn.x || pt0.y != ptn.y)
461                tg.Pixels.add(pt0);
462            
463        }
464            catch (Exception exc) {
465            ErrorLogger.LogException(_className, "closeAreaTG",
466                    new RendererException("Failed inside closeAreaTG", exc));
467        }
468    }
469    /**
470     * DMA, DMAF fill must be handled separately because of the feint
471     * @param tg
472     * @param clipBounds
473     * @return
474     */
475    protected static ArrayList<Shape2> fillDMA(TGLight tg,
476            Rectangle2D clipBounds)
477    {
478        ArrayList<Shape2>shapes=new ArrayList();
479        try
480        {
481            switch(tg.get_LineType())
482            {
483                case TacticalLines.OBSFAREA:
484                case TacticalLines.OBSAREA:
485                case TacticalLines.STRONG:
486                case TacticalLines.ZONE:
487                case TacticalLines.FORT_REVD:
488                case TacticalLines.FORT:
489                case TacticalLines.ENCIRCLE:
490                case TacticalLines.ATDITCHC:
491                case TacticalLines.ATDITCHM:
492                    break;
493                default:
494                    return shapes;
495            }
496            Shape2 shape=null;
497
498            //create a generic area tg from the pixels and clip it
499            int j=0;
500            TGLight tg2=new TGLight();
501            tg2.set_LineType(TacticalLines.GENERAL);
502            tg2.Pixels=new ArrayList();
503            //to get the original pixels size
504            //int n=0;
505            int n=tg.Pixels.size();
506            
507            for(j=0;j<n;j++)
508                tg2.Pixels.add(tg.Pixels.get(j));
509
510            closeAreaTG(tg2);
511
512            if(clipBounds != null)
513                ClipPolygon(tg2,clipBounds);
514
515            if(tg2.Pixels==null || tg2.Pixels.isEmpty())
516                return shapes;
517
518            //shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
519            shape=new Shape2(Shape2.SHAPE_TYPE_FILL);
520            shape.setFillColor(tg.get_FillColor());
521
522            shape.moveTo(tg2.Pixels.get(0));
523            //original pixels do not include feint
524            n=tg2.Pixels.size();
525            //for(j=1;j<tg2.Pixels.size();j++)
526            for(j=1;j<n;j++)
527                shape.lineTo(tg2.Pixels.get(j));
528
529            shapes.add(shape);
530        }
531        catch (Exception exc) {
532            ErrorLogger.LogException(_className, "fillDMA",
533                    new RendererException("Failed inside fillDMA", exc));
534        }
535        return shapes;
536    }
537    /**
538     * for pre-clipped lines which also require fill but need the processed points
539     * to create the fill. This functioni is called after the clip, so the fill
540     * does not get clipped.
541     * @param tg
542     * @param shapes
543     */
544    protected static void addAbatisFill(TGLight tg,
545            ArrayList<Shape2>shapes)
546    {
547        try
548        {
549            if(tg.Pixels==null ||
550                    tg.Pixels.size()<2 ||
551                    tg.get_FillColor()==null ||
552                    tg.get_FillColor().getAlpha()<2 ||
553                    shapes==null)
554                return;
555
556            int j=0,n=tg.Pixels.size();
557            Shape2 shape=null;
558            TGLight tg2=null;
559            switch(tg.get_LineType())
560            {
561                case TacticalLines.MSDZ:
562                    double dist0=0,dist1=0,dist2=0;
563                    shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
564                    shape.setFillColor(tg.get_FillColor());
565                    if(tg.Pixels != null & tg.Pixels.size()>=300)
566                    {
567                        dist0=Math.abs(tg.Pixels.get(0).x-tg.Pixels.get(50).x);
568                        dist1=Math.abs(tg.Pixels.get(100).x-tg.Pixels.get(150).x);
569                        dist2=Math.abs(tg.Pixels.get(200).x-tg.Pixels.get(250).x);
570                        int start=-1,end=-1;
571                        if(dist0>=dist1 && dist0>=dist2)
572                        {
573                            start=0;
574                            end=99;
575                        }
576                        else if(dist1>=dist0 && dist1>=dist2)
577                        {
578                            start=100;
579                            end=199;
580                        }
581                        else
582                        {
583                            start=200;
584                            end=299;
585                        }
586                        shape.moveTo(tg.Pixels.get(start));
587                        for(j=start;j<=end;j++)
588                            shape.lineTo(tg.Pixels.get(j));
589
590                        //shapes.add(0,shape);
591                    }
592                    break;
593                case TacticalLines.ABATIS:
594                    shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
595                    shape.setFillColor(tg.get_FillColor());
596                    tg2=new TGLight();
597                    tg2.set_LineType(TacticalLines.GENERAL);
598                    tg2.Pixels=new ArrayList();
599                    if(tg.Pixels != null && tg.Pixels.size()>2)
600                    {
601                        tg2.Pixels.add(tg.Pixels.get(n-3));
602                        tg2.Pixels.add(tg.Pixels.get(n-2));
603                        tg2.Pixels.add(tg.Pixels.get(n-1));
604                        tg2.Pixels.add(tg.Pixels.get(n-3));
605
606                        shape.moveTo(tg2.Pixels.get(0));
607                        for(j=1;j<tg2.Pixels.size();j++)
608                            shape.lineTo(tg2.Pixels.get(j));
609
610                        //shapes.add(shape);
611                    }
612                    break;
613                default:
614                    return;
615            }//end switch
616            if(shapes != null)
617                shapes.add(0,shape);
618        }
619        catch (Exception exc) {
620            ErrorLogger.LogException(_className, "addAbatisFill",
621                    new RendererException("Failed inside addAbatisFill", exc));
622        }
623    }
624    /**
625     * for lines with glyphs the fill must be handled (clipped) as a separate shape.
626     * this function needs to be called before the clipping is done to the line
627     * @param tg
628     * @param clipBounds
629     */
630    protected static ArrayList<Shape2> LinesWithFill(TGLight tg,
631            Rectangle2D clipBounds)
632    {                        
633        ArrayList<Shape2>shapes=null;
634        try
635        {
636            if(tg.get_FillColor()==null || tg.get_FillColor().getAlpha()<=1 ||
637                    tg.Pixels==null || tg.Pixels.isEmpty())
638                return shapes;
639
640            switch(tg.get_LineType())
641            {
642                case TacticalLines.ABATIS:
643                case TacticalLines.SPT:
644                case TacticalLines.MAIN:
645                case TacticalLines.AAAAA:
646                case TacticalLines.AIRAOA:
647                case TacticalLines.CATK:
648                case TacticalLines.CATKBYFIRE:
649                case TacticalLines.CORDONSEARCH:
650                case TacticalLines.CORDONKNOCK:
651                case TacticalLines.SECURE:
652                case TacticalLines.OCCUPY:
653                case TacticalLines.RETAIN:
654                case TacticalLines.ISOLATE:
655                case TacticalLines.CONVOY:
656                case TacticalLines.HCONVOY:
657                    return shapes;
658                case TacticalLines.PAA_RECTANGULAR:
659                case TacticalLines.RECTANGULAR_TARGET:
660                    return null;
661                case TacticalLines.OBSFAREA:
662                case TacticalLines.OBSAREA:
663                case TacticalLines.STRONG:
664                case TacticalLines.ZONE:
665                case TacticalLines.FORT_REVD:
666                case TacticalLines.FORT:
667                case TacticalLines.ENCIRCLE:
668                case TacticalLines.ATDITCHC:
669                case TacticalLines.ATDITCHM:
670                    return fillDMA(tg,clipBounds);
671                default:
672                    break;
673            }
674            if(clsUtility.LinesWithFill(tg.get_LineType())==false)
675                return shapes;
676
677            shapes=new ArrayList();
678            //undo any fillcolor that might have been set for the existing shape
679            //because we are divorcing fill from the line
680            Shape2 shape=null;
681
682            //create a generic area tg from the pixels and clip it
683            TGLight tg2=new TGLight();
684            tg2.set_LineType(TacticalLines.GENERAL);
685            tg2.Pixels=new ArrayList();
686            tg2.Pixels.addAll(tg.Pixels);
687            closeAreaTG(tg2);
688            //tg2.Pixels.add(tg.Pixels.get(0));
689            if(clipBounds != null)
690                ClipPolygon(tg2,clipBounds);
691
692
693            if(tg2.Pixels==null || tg2.Pixels.isEmpty())
694                return null;
695
696            int j=0;
697            //shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
698            shape=new Shape2(Shape2.SHAPE_TYPE_FILL);
699            shape.setFillColor(tg.get_FillColor());
700
701            shape.moveTo(tg2.Pixels.get(0));
702            for(j=1;j<tg2.Pixels.size();j++)
703                shape.lineTo(tg2.Pixels.get(j));
704            
705            if(tg.get_FillColor() != null || tg.get_FillColor().getAlpha()>1)
706            {
707                shapes.add(shape);
708            }
709            else
710                return  null;
711        }
712        catch (Exception exc) {
713            ErrorLogger.LogException(_className, "LinesWithFill",
714                    new RendererException("Failed inside LinesWithFill", exc));
715        }
716        return shapes;
717    }
718    /**
719     * @deprecated
720     * for polygon completely outside the clip area
721     * pass back a small box to be able to continue normal processing
722     * @param clipBounds
723     * @return
724     */
725    private static ArrayList<Point2D> buildBox(Rectangle2D clipBounds) {
726        ArrayList<Point2D> box = new ArrayList();
727        try {
728            {
729                double ulx = 0, uly = 0, lrx = 0, lry = 0;
730                ulx = clipBounds.getMinX() - 200;
731                uly = clipBounds.getMinY() - 200;
732                lrx = clipBounds.getMaxX() + 200;
733                lry = clipBounds.getMaxY() + 200;
734                Point2D lr = new Point2D.Double(ulx, uly);
735                Point2D ll = new Point2D.Double(ulx - 10, uly);
736                Point2D ul = new Point2D.Double(ulx - 10, uly - 10);
737                Point2D ur = new Point2D.Double(ulx, uly - 10);
738                box.add(lr);
739                box.add(ll);
740                box.add(ul);
741                box.add(ur);
742                box.add(lr);
743            }
744        } catch (Exception exc) {
745            ErrorLogger.LogException(_className, "buildBox",
746                    new RendererException("Failed inside buildBox", exc));
747        }
748        return box;
749    }
750    /**
751     * Works for tactical lines and areas
752     * @param tg
753     * @param clipBounds
754     * @return
755     */
756    public static ArrayList<Point2D> ClipPolygon(TGLight tg,
757            Rectangle2D clipBounds) {
758        ArrayList<Point2D> poly = new ArrayList();
759        try {
760            ArrayList polygon = clsUtilityCPOF.POINT2toPoint2D(tg.Pixels);            
761            Boolean isClosed = clsUtility.isClosedPolygon(tg.get_LineType());
762            //create a hashtable to hold the original points
763            Map<String,Object>hashMap=new HashMap<String,Object>();
764            int j=0;
765            for(j=0;j<polygon.size();j++)
766            {
767                hashMap.put(Integer.toString(j), polygon.get(j));
768            }
769            
770            Rectangle2D clipBounds2 = new Rectangle2D.Double(clipBounds.getX() - 50, clipBounds.getY() - 50, clipBounds.getWidth() + 100, clipBounds.getHeight() + 100);
771
772            int addedLinePoints = 0;
773            if (isClosed) {
774                polygon.remove(polygon.size() - 1);
775                isClosed = true;
776            } else {
777                //for tactical lines it always seems to work if the 0th and last points are inside the area
778                //add points on the edge as needed to make that happen
779                addedLinePoints = AddBoundaryPointsForLines(polygon, clipBounds2);
780            }
781            //expand the clip bounds by 10 pixels
782
783            poly = clipRight(tg, polygon, clipBounds2);
784            poly = clipTop(tg, poly, clipBounds2);
785            poly = clipLeft(tg, poly, clipBounds2);
786            poly = clipBottom(tg, poly, clipBounds2);
787
788            if (isClosed)
789            {
790                if (poly.size() > 0)
791                {
792                    poly.add(poly.get(0));
793                }
794            } 
795            else
796            {
797                switch (addedLinePoints)
798                {
799                    case 0: //no points were added, do nothing
800                        break;
801                    case 1: //point was added to the front to make algorithm work, remove segment
802                        if (poly.size() > 0) {
803                            poly.remove(0);
804                        }
805                        if (poly.size() > 0) {
806                            poly.remove(0);
807                        }
808                        break;
809                    case 2: //point was added to the end to make algorithm work, remove segment
810                        if (poly.size() > 0) {
811                            poly.remove(poly.size() - 1);
812                        }
813                        if (poly.size() > 0) {
814                            poly.remove(poly.size() - 1);
815                        }
816                        break;
817                    case 3: //point was added to the front and end to make algorithm work, remove segments
818                        if (poly.size() > 0) {
819                            poly.remove(0);
820                        }
821                        if (poly.size() > 0) {
822                            poly.remove(0);
823                        }
824                        if (poly.size() > 0) {
825                            poly.remove(poly.size() - 1);
826                        }
827                        if (poly.size() > 0) {
828                            poly.remove(poly.size() - 1);
829                        }
830                        break;
831                }
832            }
833            
834            if (isClosed == true)
835            {
836                if (poly.size() > 2)
837                {
838                    //tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2(poly);
839                    tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2Mapped(poly,hashMap);
840                } 
841                else
842                {
843                    //poly = buildBox(clipBounds);
844                    //tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2(poly);
845                    tg.Pixels=new ArrayList();
846                }
847
848            } 
849            else
850            {
851                if (poly.size() > 1)
852                {
853                    tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2Mapped(poly,hashMap);
854                } 
855                else
856                {
857                    tg.Pixels=new ArrayList();
858                }
859            }            
860
861        } catch (Exception exc) {
862            ErrorLogger.LogException(_className, "ClipPolygon",
863                    new RendererException("Failed inside ClipPolygon", exc));
864        }
865        return poly;
866    }
867}