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.FRONTAL_ATTACK:
645                case TacticalLines.TURNING_MOVEMENT:
646                case TacticalLines.MOVEMENT_TO_CONTACT:
647                case TacticalLines.MAIN:
648                case TacticalLines.AAAAA:
649                case TacticalLines.AIRAOA:
650                case TacticalLines.CATK:
651                case TacticalLines.CATKBYFIRE:
652                case TacticalLines.CORDONSEARCH:
653                case TacticalLines.CORDONKNOCK:
654                case TacticalLines.SECURE:
655                case TacticalLines.OCCUPY:
656                case TacticalLines.RETAIN:
657                case TacticalLines.ISOLATE:
658                case TacticalLines.AREA_DEFENSE:
659                case TacticalLines.MOBILE_DEFENSE:
660                case TacticalLines.CONVOY:
661                case TacticalLines.HCONVOY:
662                    return shapes;
663                case TacticalLines.PAA_RECTANGULAR:
664                case TacticalLines.RECTANGULAR_TARGET:
665                    return null;
666                case TacticalLines.OBSFAREA:
667                case TacticalLines.OBSAREA:
668                case TacticalLines.STRONG:
669                case TacticalLines.ZONE:
670                case TacticalLines.FORT_REVD:
671                case TacticalLines.FORT:
672                case TacticalLines.ENCIRCLE:
673                case TacticalLines.ATDITCHC:
674                case TacticalLines.ATDITCHM:
675                    return fillDMA(tg,clipBounds);
676                default:
677                    break;
678            }
679            if(clsUtility.LinesWithFill(tg.get_LineType())==false)
680                return shapes;
681
682            shapes=new ArrayList();
683            //undo any fillcolor that might have been set for the existing shape
684            //because we are divorcing fill from the line
685            Shape2 shape=null;
686
687            //create a generic area tg from the pixels and clip it
688            TGLight tg2=new TGLight();
689            tg2.set_LineType(TacticalLines.GENERAL);
690            tg2.Pixels=new ArrayList();
691            tg2.Pixels.addAll(tg.Pixels);
692            closeAreaTG(tg2);
693            //tg2.Pixels.add(tg.Pixels.get(0));
694            if(clipBounds != null)
695                ClipPolygon(tg2,clipBounds);
696
697
698            if(tg2.Pixels==null || tg2.Pixels.isEmpty())
699                return null;
700
701            int j=0;
702            //shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
703            shape=new Shape2(Shape2.SHAPE_TYPE_FILL);
704            shape.setFillColor(tg.get_FillColor());
705
706            shape.moveTo(tg2.Pixels.get(0));
707            for(j=1;j<tg2.Pixels.size();j++)
708                shape.lineTo(tg2.Pixels.get(j));
709            
710            if(tg.get_FillColor() != null || tg.get_FillColor().getAlpha()>1)
711            {
712                shapes.add(shape);
713            }
714            else
715                return  null;
716        }
717        catch (Exception exc) {
718            ErrorLogger.LogException(_className, "LinesWithFill",
719                    new RendererException("Failed inside LinesWithFill", exc));
720        }
721        return shapes;
722    }
723    /**
724     * @deprecated
725     * for polygon completely outside the clip area
726     * pass back a small box to be able to continue normal processing
727     * @param clipBounds
728     * @return
729     */
730    private static ArrayList<Point2D> buildBox(Rectangle2D clipBounds) {
731        ArrayList<Point2D> box = new ArrayList();
732        try {
733            {
734                double ulx = 0, uly = 0, lrx = 0, lry = 0;
735                ulx = clipBounds.getMinX() - 200;
736                uly = clipBounds.getMinY() - 200;
737                lrx = clipBounds.getMaxX() + 200;
738                lry = clipBounds.getMaxY() + 200;
739                Point2D lr = new Point2D.Double(ulx, uly);
740                Point2D ll = new Point2D.Double(ulx - 10, uly);
741                Point2D ul = new Point2D.Double(ulx - 10, uly - 10);
742                Point2D ur = new Point2D.Double(ulx, uly - 10);
743                box.add(lr);
744                box.add(ll);
745                box.add(ul);
746                box.add(ur);
747                box.add(lr);
748            }
749        } catch (Exception exc) {
750            ErrorLogger.LogException(_className, "buildBox",
751                    new RendererException("Failed inside buildBox", exc));
752        }
753        return box;
754    }
755    /**
756     * Works for tactical lines and areas
757     * @param tg
758     * @param clipBounds
759     * @return
760     */
761    public static ArrayList<Point2D> ClipPolygon(TGLight tg,
762            Rectangle2D clipBounds) {
763        ArrayList<Point2D> poly = new ArrayList();
764        try {
765            ArrayList polygon = clsUtilityCPOF.POINT2toPoint2D(tg.Pixels);            
766            Boolean isClosed = clsUtility.isClosedPolygon(tg.get_LineType());
767            //create a hashtable to hold the original points
768            Map<String,Object>hashMap=new HashMap<String,Object>();
769            int j=0;
770            for(j=0;j<polygon.size();j++)
771            {
772                hashMap.put(Integer.toString(j), polygon.get(j));
773            }
774            
775            Rectangle2D clipBounds2 = new Rectangle2D.Double(clipBounds.getX() - 50, clipBounds.getY() - 50, clipBounds.getWidth() + 100, clipBounds.getHeight() + 100);
776
777            int addedLinePoints = 0;
778            if (isClosed) {
779                polygon.remove(polygon.size() - 1);
780                isClosed = true;
781            } else {
782                //for tactical lines it always seems to work if the 0th and last points are inside the area
783                //add points on the edge as needed to make that happen
784                addedLinePoints = AddBoundaryPointsForLines(polygon, clipBounds2);
785            }
786            //expand the clip bounds by 10 pixels
787
788            poly = clipRight(tg, polygon, clipBounds2);
789            poly = clipTop(tg, poly, clipBounds2);
790            poly = clipLeft(tg, poly, clipBounds2);
791            poly = clipBottom(tg, poly, clipBounds2);
792
793            if (isClosed)
794            {
795                if (poly.size() > 0)
796                {
797                    poly.add(poly.get(0));
798                }
799            } 
800            else
801            {
802                switch (addedLinePoints)
803                {
804                    case 0: //no points were added, do nothing
805                        break;
806                    case 1: //point was added to the front to make algorithm work, remove segment
807                        if (poly.size() > 0) {
808                            poly.remove(0);
809                        }
810                        if (poly.size() > 0) {
811                            poly.remove(0);
812                        }
813                        break;
814                    case 2: //point was added to the end to make algorithm work, remove segment
815                        if (poly.size() > 0) {
816                            poly.remove(poly.size() - 1);
817                        }
818                        if (poly.size() > 0) {
819                            poly.remove(poly.size() - 1);
820                        }
821                        break;
822                    case 3: //point was added to the front and end to make algorithm work, remove segments
823                        if (poly.size() > 0) {
824                            poly.remove(0);
825                        }
826                        if (poly.size() > 0) {
827                            poly.remove(0);
828                        }
829                        if (poly.size() > 0) {
830                            poly.remove(poly.size() - 1);
831                        }
832                        if (poly.size() > 0) {
833                            poly.remove(poly.size() - 1);
834                        }
835                        break;
836                }
837            }
838            
839            if (isClosed == true)
840            {
841                if (poly.size() > 2)
842                {
843                    //tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2(poly);
844                    tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2Mapped(poly,hashMap);
845                } 
846                else
847                {
848                    //poly = buildBox(clipBounds);
849                    //tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2(poly);
850                    tg.Pixels=new ArrayList();
851                }
852
853            } 
854            else
855            {
856                if (poly.size() > 1)
857                {
858                    tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2Mapped(poly,hashMap);
859                } 
860                else
861                {
862                    tg.Pixels=new ArrayList();
863                }
864            }            
865
866        } catch (Exception exc) {
867            ErrorLogger.LogException(_className, "ClipPolygon",
868                    new RendererException("Failed inside ClipPolygon", exc));
869        }
870        return poly;
871    }
872}