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.graphics2d.*;
011import armyc2.c5isr.renderer.utilities.ErrorLogger;
012import armyc2.c5isr.renderer.utilities.RendererException;
013import armyc2.c5isr.JavaLineArray.POINT2;
014import armyc2.c5isr.JavaLineArray.TacticalLines;
015import armyc2.c5isr.JavaLineArray.Shape2;
016import armyc2.c5isr.JavaLineArray.lineutility;
017import armyc2.c5isr.graphics2d.Line2D;
018import armyc2.c5isr.graphics2d.Point2D;
019import armyc2.c5isr.graphics2d.Polygon;
020
021import java.util.HashMap;
022import java.util.Map;
023
024/**
025 * Class to clip polygons
026*
027 */
028public final class clsClipQuad {
029    private static final String _className = "clsClipQuad";
030    /**
031     * Use the new version which takes an array for polygon clip bounds instead of rectangle
032     * @param polygon
033     * @param clipBounds
034     * @return 
035     */
036    private static int AddBoundaryPointsForLines(ArrayList<Point2D> polygon,
037            ArrayList<Point2D> clipBounds) 
038    {
039        int result=0;
040        try
041        {
042            Point2D pt02d=polygon.get(0);
043            Point2D ptLast2d=polygon.get((polygon.size()-1));
044            POINT2 pt0=new POINT2(pt02d.getX(),pt02d.getY());
045            POINT2 ptLast=new POINT2(ptLast2d.getX(),ptLast2d.getY());
046            Point2D nearestPt=new Point2D.Double();
047            Polygon clipArray=new Polygon();
048            int j=0;
049            double minDist=Double.MAX_VALUE;
050            double dist=0;
051            POINT2 sidePt=new POINT2();
052            Boolean addToFront = false, addToEnd = false;     
053            //int n=clipBounds.size();
054            //for(j=0;j<clipBounds.size();j++)
055            for(j=0;j<clipBounds.size();j++)    //was n
056            {
057                clipArray.addPoint((int)clipBounds.get(j).getX(), (int)clipBounds.get(j).getY());
058            }
059
060            double totalX=0,totalY=0;
061            int counter=0;
062            //for(j=0;j<clipBounds.size()-1;j++)
063            for(j=0;j<clipBounds.size()-1;j++)  //was n-1
064            {
065                totalX+=clipBounds.get(j).getX();
066                totalY+=clipBounds.get(j).getY();
067                counter++;
068            }
069            //if clipBounds is not closed add the jth point
070            if( clipBounds.get(0).getX()!=clipBounds.get(j).getX() || 
071                    clipBounds.get(0).getY()!=clipBounds.get(j).getY() )
072            {
073                totalX+=clipBounds.get(j).getX();
074                totalY+=clipBounds.get(j).getY();                    
075                counter++;
076            }
077            double avgX=totalX/counter;
078            double avgY=totalY/counter;
079            POINT2 ptCenter=new POINT2(avgX,avgY);
080            POINT2 ptNear=null;
081            //first point outside the clip bounds
082            if(clipArray.contains(pt02d)==false)
083            {
084                //add nearest segment midpoint to the front
085                //for(j=0;j<clipBounds.size();j++)
086                for(j=0;j<clipBounds.size();j++)    //was n
087                {
088                    sidePt.x=clipBounds.get(j).getX();
089                    sidePt.y=clipBounds.get(j).getY();
090                    dist=lineutility.CalcDistanceDouble(pt0, sidePt);
091                    if(dist<minDist)
092                    {
093                        minDist=dist;
094                        //minDistIndex=j;
095                        nearestPt.setLocation(sidePt.x,sidePt.y);
096                    }
097                }
098                //move nearestPt in a bit to not get clipped
099                ptNear=new POINT2(nearestPt.getX(),nearestPt.getY());
100                ptNear=lineutility.ExtendAlongLineDouble(ptNear, ptCenter, 2);
101                nearestPt.setLocation(ptNear.x, ptNear.y);
102                polygon.add(0, nearestPt);
103                addToFront=true;
104            }
105            //re-initialize variables
106            nearestPt=new Point2D.Double();
107            minDist=Double.MAX_VALUE;
108            //last point outside the clip bounds
109            if(clipArray.contains(ptLast2d)==false)
110            {
111                //add nearest segment midpoint to the front
112                //for(j=0;j<clipBounds.size();j++)
113                for(j=0;j<clipBounds.size();j++)    //was n
114                {
115                    sidePt.x=clipBounds.get(j).getX();
116                    sidePt.y=clipBounds.get(j).getY();
117                    dist=lineutility.CalcDistanceDouble(ptLast, sidePt);
118                    if(dist<minDist)
119                    {
120                        minDist=dist;
121                        //minDistIndex=j;
122                        nearestPt.setLocation(sidePt.x,sidePt.y);
123                    }
124                }            
125                //move nearestPt in a bit to not get clipped
126                ptNear=new POINT2(nearestPt.getX(),nearestPt.getY());
127                ptNear=lineutility.ExtendAlongLineDouble(ptNear, ptCenter, 2);
128                nearestPt.setLocation(ptNear.x, ptNear.y);
129                polygon.add(nearestPt);
130                addToEnd=true;
131            }
132            if (addToFront == false && addToEnd == false) {
133                result = 0;
134            }
135            else if (addToFront == true && addToEnd == false) {
136                result = 1;
137            }
138            else if (addToFront == false && addToEnd == true) {
139                result = 2;
140            }
141            else if (addToFront == true && addToEnd == true) {
142                result = 3;
143            }
144        }
145        catch (Exception exc) 
146        {
147            ErrorLogger.LogException(_className, "AddBoundaryPointsForLines",
148                    new RendererException("Failed inside AddBoundaryPointsForLines", exc));
149        }        
150        return result;
151    }
152    private static Point2D CalcTrueIntersectDouble(double m1,
153                                            double b1,
154                                            double m2,
155                                            double b2,
156                                            int bolVertical1,
157                                            int bolVertical2,
158                                            double X1,  //x intercept if line1 is vertical
159                                            double X2)
160    {
161        Point2D ptIntersect=new Point2D.Double(X1,X2);
162        try
163        {
164            double x=0,y=0;
165
166            if(bolVertical1==0 && bolVertical2==0)      //both lines vertical
167                return ptIntersect;
168            //the following 3 if blocks are the only ways to get an intersection
169            if(bolVertical1==0 && bolVertical2==1)      //line1 vertical, line2 not
170            {
171                ptIntersect.setLocation(X1, m2*X1+b2);
172                return ptIntersect;
173            }
174            if(bolVertical1==1 && bolVertical2==0)      //line2 vertical, line1 not
175            {
176                ptIntersect.setLocation(X2, m1*X2+b1);
177                return ptIntersect;
178            }
179            //if either of the lines is vertical function has already returned
180            //so both m1 and m2 should be valid
181            //should always be using this ocase because the lines are neither vertical
182            //or horizontal and are perpendicular
183            if(m1 != m2)
184            {
185                x=(b2-b1)/(m1-m2);      //cannot blow up
186                y=(m1*x+b1);
187                ptIntersect.setLocation(x, y);
188                return ptIntersect;
189            }
190        }
191        catch(Exception exc)
192        {
193            ErrorLogger.LogException(_className ,"CalcTrueIntersectDouble",
194                    new RendererException("Failed inside CalcTrueIntersectDouble", exc));
195        }
196        return ptIntersect;
197    }
198    /**
199     * Gets theoretical intersection of an edge with the line connecting previous and current points.
200     * @param previous
201     * @param current
202     * @param currentEdge the current edge of the clip area, assumed to not be vertical
203     * @return 
204     */
205    private static Point2D intersectPoint2(Point2D previous, 
206            Point2D current,
207            Line2D currentEdge)
208    {
209        
210        Point2D ptIntersect=null;
211        try
212        {                        
213            Point2D ll=currentEdge.getP1();
214            Point2D ul=currentEdge.getP2();
215            
216            //no vertical client segments
217            //if(current.getX()==previous.getX())            
218            if(Math.abs(current.getX()-previous.getX())<1)            
219                current.setLocation(current.getX()+1, current.getY());                
220            
221            double m1=( ul.getY()-ll.getY() )/( ul.getX()-ll.getX() );
222            double m2=( current.getY()-previous.getY() )/( current.getX()-previous.getX() );
223            double b1=ul.getY()-m1*ul.getX();
224            double b2=current.getY()-m2*current.getX(); 
225            ptIntersect=CalcTrueIntersectDouble(m1,b1,m2,b2,1,1,0,0);                    
226        }
227        catch (Exception exc) {
228            ErrorLogger.LogException(_className, "intersectPoint2",
229                    new RendererException("Failed inside intersectPoint2", exc));
230        }        
231        return ptIntersect;
232    }
233
234    /**
235     * clips array of pts against a side of the clip bounds polygon
236     * assumes clipBounds has no vertical or horizontal segments 
237     * @param pts array of points to clip against the clip bounds
238     * @param index starting index of clipBounds for the side to clip against
239     * @param clipBounds a quadrilateral or a polygon array that is the clipping area
240     * @return the clipped array of points
241     */
242    private static ArrayList<Point2D> clipSide(TGLight tg, ArrayList<Point2D> pts,
243            int index,
244            ArrayList<Point2D> clipBounds) 
245    {
246        ArrayList<Point2D> ptsResult=null;
247        try
248        {
249            Point2D pt1=new Point2D.Double(clipBounds.get(index).getX(),clipBounds.get(index).getY());//first point of clip side
250            Point2D pt2=new Point2D.Double(clipBounds.get(index+1).getX(),clipBounds.get(index+1).getY());//last point of clip side                        
251            Point2D clipBoundsPoint=null;//some point in the clipbounds not on the side
252            Point2D ptClipBoundsIntersect=null;//some point in the clipbounds not on the side
253            double m1=0,m2=0,b1=0,b2=0,b3=0,b4=0;            
254            Point2D ptPreviousIntersect=null,ptCurrentIntersect=null;            
255            int j = 0,clipBoundsQuadrant=-1,previousQuadrant=-1,currentQuadrant=-1;  //quadrants relative to side
256            Point2D current = null, previous = null;
257            Point2D intersectPt = null;
258            Line2D edge;  
259            ptsResult=new ArrayList();            
260            //set some point in the array which is not in the side
261            //this point will be used to define which side of the clipping side the rest of the clipbounds points are on
262            //then it can be used to figure out whether a given point is to be clipped
263            //for this scheme to work it needs to be a convex clipping area
264            if(index==0)
265            {
266                clipBoundsPoint=new Point2D.Double(clipBounds.get(index+2).getX(),clipBounds.get(index+2).getY());
267            }
268            else if(index>1)
269            {
270                clipBoundsPoint=new Point2D.Double(clipBounds.get(index-2).getX(),clipBounds.get(index-2).getY());
271            }
272            else if(index==1)
273            {
274                clipBoundsPoint=new Point2D.Double(clipBounds.get(0).getX(),clipBounds.get(0).getY());
275            }
276                
277            //no vertical segments
278            //if(pt2.getX()==pt1.getX())
279            if(Math.abs(pt2.getX()-pt1.getX())<1)
280                pt2.setLocation(pt2.getX()+1, pt2.getY());
281            //if(pt2.getY()==pt1.getY())
282            if(Math.abs(pt2.getY()-pt1.getY())<1)
283                pt2.setLocation(pt2.getX(), pt2.getY()+1);
284            
285            for (j = 0; j < pts.size(); j++) 
286            {                
287                current = pts.get(j);
288                if (j == 0) 
289                {
290                    previous = pts.get(pts.size() - 1);
291                } 
292                else 
293                {
294                    previous = pts.get(j - 1);
295                }
296
297                m1=(pt2.getY()-pt1.getY())/(pt2.getX()-pt1.getX());
298                m2=-1d/m1;  //the slope of the line perpendicular to m1,b1
299                b1=pt2.getY()-m1*pt2.getX();
300                b2=previous.getY()-m2*previous.getX(); 
301                b3=current.getY()-m2*current.getX(); 
302                b4=clipBoundsPoint.getY()-m2*clipBoundsPoint.getX(); 
303                ptPreviousIntersect=CalcTrueIntersectDouble(m1,b1,m2,b2,1,1,0,0);                    
304                ptCurrentIntersect=CalcTrueIntersectDouble(m1,b1,m2,b3,1,1,0,0);
305                ptClipBoundsIntersect=CalcTrueIntersectDouble(m1,b1,m2,b4,1,1,0,0);
306                clipBoundsQuadrant=lineutility.GetQuadrantDouble(clipBoundsPoint.getX(), clipBoundsPoint.getY(), ptClipBoundsIntersect.getX(), ptClipBoundsIntersect.getY());
307                previousQuadrant=lineutility.GetQuadrantDouble(previous.getX(), previous.getY(), ptPreviousIntersect.getX(), ptPreviousIntersect.getY());
308                currentQuadrant=lineutility.GetQuadrantDouble(current.getX(), current.getY(), ptCurrentIntersect.getX(), ptCurrentIntersect.getY());
309
310                //case: both inside
311                if(previousQuadrant==clipBoundsQuadrant && currentQuadrant==clipBoundsQuadrant)
312                    ptsResult.add(current);                                        
313                else if(previousQuadrant==clipBoundsQuadrant && currentQuadrant!=clipBoundsQuadrant)//previous inside, current outside
314                {
315                    edge = new Line2D.Double(pt1, pt2);
316                    intersectPt = intersectPoint2(previous, current, edge);
317                    if (intersectPt != null) 
318                    {
319                        ptsResult.add(intersectPt);
320                    }
321                    tg.set_WasClipped(true);
322                }
323                else if(previousQuadrant!=clipBoundsQuadrant && currentQuadrant==clipBoundsQuadrant)//current inside, previous outside
324                {
325                    edge = new Line2D.Double(pt1, pt2);
326                    intersectPt = intersectPoint2(previous, current, edge);
327                    if (intersectPt != null) 
328                    {
329                        ptsResult.add(intersectPt);
330                    }
331                    ptsResult.add(current);
332                    tg.set_WasClipped(true);
333                }
334                else if(previousQuadrant!=clipBoundsQuadrant && currentQuadrant!=clipBoundsQuadrant)
335                    continue;
336            }//end for j=0 to pts.size()-1
337        }//end try
338        catch (Exception exc) {
339            ErrorLogger.LogException(_className, "clipSide",
340                    new RendererException("Failed inside clipSide", exc));
341        }    
342        return ptsResult;
343    }
344    /**
345     * for pre-clipped lines which also require fill but need the processed points
346     * to create the fill. This function is called after the clip, so the fill
347     * does not get clipped.
348     * @param tg
349     * @param shapes
350     */
351    protected static void addAbatisFill(TGLight tg,
352            ArrayList<Shape2>shapes)
353    {
354        try
355        {
356            if(tg.Pixels==null ||
357                    tg.Pixels.size()<2 ||
358                    tg.get_FillColor()==null ||
359                    tg.get_FillColor().getAlpha()<2 ||
360                    shapes==null)
361                return;
362
363            int j=0,n=tg.Pixels.size();
364            Shape2 shape=null;
365            TGLight tg2=null;
366            switch(tg.get_LineType())
367            {
368                case TacticalLines.MSDZ:
369                    double dist0=0,dist1=0,dist2=0;
370                    shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
371                    shape.setFillColor(tg.get_FillColor());
372                    if(tg.Pixels != null & tg.Pixels.size()>=300)
373                    {
374                        dist0=Math.abs(tg.Pixels.get(0).x-tg.Pixels.get(50).x);
375                        dist1=Math.abs(tg.Pixels.get(100).x-tg.Pixels.get(150).x);
376                        dist2=Math.abs(tg.Pixels.get(200).x-tg.Pixels.get(250).x);
377                        int start=-1,end=-1;
378                        if(dist0>=dist1 && dist0>=dist2)
379                        {
380                            start=0;
381                            end=99;
382                        }
383                        else if(dist1>=dist0 && dist1>=dist2)
384                        {
385                            start=100;
386                            end=199;
387                        }
388                        else
389                        {
390                            start=200;
391                            end=299;
392                        }
393                        shape.moveTo(tg.Pixels.get(start));
394                        for(j=start;j<=end;j++)
395                            shape.lineTo(tg.Pixels.get(j));
396
397                        //shapes.add(0,shape);
398                    }
399                    break;
400                case TacticalLines.ABATIS:
401                    shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
402                    shape.setFillColor(tg.get_FillColor());
403                    tg2=new TGLight();
404                    tg2.set_LineType(TacticalLines.GENERAL);
405                    tg2.Pixels=new ArrayList();
406                    if(tg.Pixels != null && tg.Pixels.size()>2)
407                    {
408                        tg2.Pixels.add(tg.Pixels.get(n-3));
409                        tg2.Pixels.add(tg.Pixels.get(n-2));
410                        tg2.Pixels.add(tg.Pixels.get(n-1));
411                        tg2.Pixels.add(tg.Pixels.get(n-3));
412
413                        shape.moveTo(tg2.Pixels.get(0));
414                        for(j=1;j<tg2.Pixels.size();j++)
415                            shape.lineTo(tg2.Pixels.get(j));
416
417                        //shapes.add(shape);
418                    }
419                    break;
420                default:
421                    return;
422            }//end switch
423            if(shapes != null)
424                shapes.add(0,shape);
425        }
426        catch (Exception exc) {
427            ErrorLogger.LogException(_className, "addAbatisFill",
428                    new RendererException("Failed inside addAbatisFill", exc));
429        }
430    }
431    /**
432     * for lines with glyphs the fill must be handled (clipped) as a separate shape.
433     * this function needs to be called before the clipping is done to the line
434     * @param tg
435     * @param clipBounds
436     */
437    protected static ArrayList<Shape2> LinesWithFill(TGLight tg,
438            ArrayList<Point2D> clipBounds)
439    {                        
440        ArrayList<Shape2>shapes=null;
441        try
442        {
443            if(tg.get_FillColor()==null || tg.get_FillColor().getAlpha()<=1 ||
444                    tg.Pixels==null || tg.Pixels.isEmpty())
445                return shapes;
446
447            switch(tg.get_LineType())
448            {
449                case TacticalLines.ABATIS:
450                case TacticalLines.SPT:
451                case TacticalLines.MAIN:
452                case TacticalLines.AAAAA:
453                case TacticalLines.AIRAOA:
454                case TacticalLines.CATK:
455                case TacticalLines.CATKBYFIRE:
456                case TacticalLines.CORDONSEARCH:
457                case TacticalLines.CORDONKNOCK:
458                case TacticalLines.SECURE:
459                case TacticalLines.OCCUPY:
460                case TacticalLines.RETAIN:
461                case TacticalLines.ISOLATE:
462                case TacticalLines.CONVOY:
463                case TacticalLines.HCONVOY:
464                    return shapes;
465                case TacticalLines.PAA_RECTANGULAR:
466                case TacticalLines.RECTANGULAR_TARGET:
467                    return null;
468                case TacticalLines.OBSFAREA:
469                case TacticalLines.OBSAREA:
470                case TacticalLines.STRONG:
471                case TacticalLines.ZONE:
472                case TacticalLines.FORT_REVD:
473                case TacticalLines.FORT:
474                case TacticalLines.ENCIRCLE:
475                case TacticalLines.ATDITCHC:
476                case TacticalLines.ATDITCHM:
477                    return fillDMA(tg,clipBounds);
478                default:
479                    break;
480            }
481            if(clsUtility.LinesWithFill(tg.get_LineType())==false)
482                return shapes;
483
484            shapes=new ArrayList();
485            //undo any fillcolor that might have been set for the existing shape
486            //because we are divorcing fill from the line
487            Shape2 shape=null;
488
489            //create a generic area tg from the pixels and clip it
490            TGLight tg2=new TGLight();
491            tg2.set_LineType(TacticalLines.GENERAL);
492            tg2.Pixels=new ArrayList();
493            tg2.Pixels.addAll(tg.Pixels);
494            closeAreaTG(tg2);
495            //tg2.Pixels.add(tg.Pixels.get(0));
496            if(clipBounds != null)
497                ClipPolygon(tg2,clipBounds);
498
499
500            if(tg2.Pixels==null || tg2.Pixels.isEmpty())
501                return null;
502
503            int j=0;
504            shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
505            shape.setFillColor(tg.get_FillColor());
506
507            shape.moveTo(tg2.Pixels.get(0));
508            for(j=1;j<tg2.Pixels.size();j++)
509                shape.lineTo(tg2.Pixels.get(j));
510
511            if(tg.get_FillColor() != null || tg.get_FillColor().getAlpha()>1)
512            {
513                shapes.add(shape);
514            }
515            else
516                return  null;
517        }
518        catch (Exception exc) {
519            ErrorLogger.LogException(_className, "LinesWithFill",
520                    new RendererException("Failed inside LinesWithFill", exc));
521        }
522        return shapes;
523    }
524    /**
525     * closes an area
526     * @param tg
527     */
528    private static void closeAreaTG(TGLight tg)
529    {
530        try
531        {
532            if(tg.Pixels==null || tg.Pixels.isEmpty())
533                return;
534
535            POINT2 pt0=tg.Pixels.get(0);
536            POINT2 ptn=tg.Pixels.get(tg.Pixels.size()-1);
537            if(pt0.x != ptn.x || pt0.y != ptn.y)
538                tg.Pixels.add(pt0);
539            
540        }
541            catch (Exception exc) {
542            ErrorLogger.LogException(_className, "closeAreaTG",
543                    new RendererException("Failed inside closeAreaTG", exc));
544        }
545    }
546    /**
547     * DMA, DMAF fill must be handled separately because of the feint
548     * @param tg
549     * @param clipBounds
550     * @return
551     */
552    protected static ArrayList<Shape2> fillDMA(TGLight tg,
553            ArrayList<Point2D> clipBounds)
554    {
555        ArrayList<Shape2>shapes=new ArrayList();
556        try
557        {
558            switch(tg.get_LineType())
559            {
560                case TacticalLines.OBSFAREA:
561                case TacticalLines.OBSAREA:
562                case TacticalLines.STRONG:
563                case TacticalLines.ZONE:
564                case TacticalLines.FORT_REVD:
565                case TacticalLines.FORT:
566                case TacticalLines.ENCIRCLE:
567                case TacticalLines.ATDITCHC:
568                case TacticalLines.ATDITCHM:
569                    break;
570                default:
571                    return shapes;
572            }
573            Shape2 shape=null;
574
575            //create a generic area tg from the pixels and clip it
576            int j=0;
577            TGLight tg2=new TGLight();
578            tg2.set_LineType(TacticalLines.GENERAL);
579            tg2.Pixels=new ArrayList();
580            //to get the original pixels size
581            int n=0;
582            n=tg.Pixels.size();
583            
584            for(j=0;j<n;j++)
585                tg2.Pixels.add(tg.Pixels.get(j));
586
587            closeAreaTG(tg2);
588
589            if(clipBounds != null)
590                ClipPolygon(tg2,clipBounds);
591
592            if(tg2.Pixels==null || tg2.Pixels.isEmpty())
593                return shapes;
594
595            shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
596            shape.setFillColor(tg.get_FillColor());
597
598            shape.moveTo(tg2.Pixels.get(0));
599            //original pixels do not include feint
600            for(j=1;j<tg2.Pixels.size();j++)
601                shape.lineTo(tg2.Pixels.get(j));
602
603            shapes.add(shape);
604        }
605        catch (Exception exc) {
606            ErrorLogger.LogException(_className, "fillDMA",
607                    new RendererException("Failed inside fillDMA", exc));
608        }
609        return shapes;
610    }
611//    private static Boolean isClosed(ArrayList<POINT2>pts)
612//    {
613//        boolean closed=false;
614//        POINT2 pt0=pts.get(0);
615//        POINT2 ptLast=pts.get(pts.size()-1);
616//        if(pt0.x==ptLast.x && pt0.y==ptLast.y)
617//            closed=true;
618//        return closed;
619//    }
620    /**
621     * 
622     * @param tg
623     * @param clipBounds polygon representing clipping area
624     * @return 
625     */
626    protected static ArrayList<Point2D> ClipPolygon(TGLight tg,
627            ArrayList<Point2D> clipBounds) {
628        ArrayList<Point2D> poly = new ArrayList();
629        try 
630        {            
631            //diagnostic
632            Boolean isClosed = clsUtility.isClosedPolygon(tg.get_LineType());            
633            //Boolean isClosed = isClosed(tg.Pixels);
634            //M. Deutch commented one line 12-27-12
635            //clipBounds=clsUtilityGE.expandPolygon(clipBounds, 20);
636            clipBounds=clsUtilityGE.expandPolygon(clipBounds, 20);
637            //int n=clipBounds.size();
638            ArrayList polygon = clsUtilityCPOF.POINT2toPoint2D(tg.Pixels);            
639            
640            int j=0;
641            Map<String,Object>hashMap=new HashMap<String,Object>();
642            //int hashCode=0;
643            for(j=0;j<polygon.size();j++)            
644                hashMap.put(Integer.toString(j), polygon.get(j));
645            
646            //close the clipbounds if necessary
647            Point2D clipBoundsPtStart=clipBounds.get(0);
648            Point2D clipBoundsPtEnd=clipBounds.get(clipBounds.size()-1);
649            if(clipBoundsPtStart.getX() != clipBoundsPtEnd.getX() ||
650                    clipBoundsPtStart.getY() != clipBoundsPtEnd.getY())
651                clipBounds.add(clipBoundsPtStart);
652                        
653            int addedLinePoints = 0;
654            if (isClosed)             
655                polygon.remove(polygon.size() - 1);             
656            else 
657            {                     
658                addedLinePoints = AddBoundaryPointsForLines(polygon, clipBounds);
659            }
660
661            //for(j=0;j<clipBounds.size()-1;j++)
662            for(j=0;j<clipBounds.size()-1;j++)
663            {
664                if(j==0)
665                    poly=clipSide(tg,polygon,j,clipBounds);
666                else
667                    poly=clipSide(tg,poly,j,clipBounds);
668            }
669            
670            
671            if (isClosed)
672            {
673                if (poly.size() > 0)
674                {
675                    poly.add(poly.get(0));
676                }
677            }
678            else
679            {
680                switch (addedLinePoints)
681                {
682                    case 0: //no points were added, do nothing
683                        break;
684                    case 1: //point was added to the front to make algorithm work, remove segment
685                        if (poly.size() > 0) {
686                            poly.remove(0);
687                        }
688                        if (poly.size() > 0) {
689                            poly.remove(0);
690                        }
691                        break;
692                    case 2: //point was added to the end to make algorithm work, remove segment
693                        if (poly.size() > 0) {
694                            poly.remove(poly.size() - 1);
695                        }
696                        if (poly.size() > 0) {
697                           poly.remove(poly.size() - 1);
698                        }
699                        break;
700                    case 3: //point was added to the front and end to make algorithm work, remove segments
701                        if (poly.size() > 0) {
702                            poly.remove(0);
703                        }
704                        if (poly.size() > 0) {
705                            poly.remove(0);
706                        }
707                        if (poly.size() > 0) {
708                            poly.remove(poly.size() - 1);
709                        }
710                        if (poly.size() > 0) {
711                            poly.remove(poly.size() - 1);
712                        }
713                        break;
714                }
715            }
716            
717            if (isClosed == true)
718            {
719                if (poly.size() > 2)
720                {
721                    tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2Mapped(poly,hashMap);
722                } 
723                else
724                {
725                    tg.Pixels=new ArrayList();
726                }
727
728            } 
729            else
730            {
731                if (poly.size() > 1)
732                {
733                    tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2Mapped(poly,hashMap);
734                } 
735                else
736                {
737                    tg.Pixels=new ArrayList();
738                }
739            }            
740
741        } catch (Exception exc) {
742            ErrorLogger.LogException(_className, "ClipPolygon",
743                    new RendererException("Failed inside ClipPolygon", exc));
744        }
745        return poly;
746    }
747}