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.FRONTAL_ATTACK: 452 case TacticalLines.TURNING_MOVEMENT: 453 case TacticalLines.MOVEMENT_TO_CONTACT: 454 case TacticalLines.MAIN: 455 case TacticalLines.AAAAA: 456 case TacticalLines.AIRAOA: 457 case TacticalLines.CATK: 458 case TacticalLines.CATKBYFIRE: 459 case TacticalLines.CORDONSEARCH: 460 case TacticalLines.CORDONKNOCK: 461 case TacticalLines.DENY: 462 case TacticalLines.SECURE: 463 case TacticalLines.CONTROL: 464 case TacticalLines.LOCATE: 465 case TacticalLines.OCCUPY: 466 case TacticalLines.RETAIN: 467 case TacticalLines.ISOLATE: 468 case TacticalLines.AREA_DEFENSE: 469 case TacticalLines.MOBILE_DEFENSE: 470 case TacticalLines.CONVOY: 471 case TacticalLines.HCONVOY: 472 return shapes; 473 case TacticalLines.PAA_RECTANGULAR: 474 case TacticalLines.RECTANGULAR_TARGET: 475 return null; 476 case TacticalLines.OBSFAREA: 477 case TacticalLines.OBSAREA: 478 case TacticalLines.STRONG: 479 case TacticalLines.ZONE: 480 case TacticalLines.FORT_REVD: 481 case TacticalLines.FORT: 482 case TacticalLines.ENCIRCLE: 483 case TacticalLines.ATDITCHC: 484 case TacticalLines.ATDITCHM: 485 return fillDMA(tg,clipBounds); 486 default: 487 break; 488 } 489 if(clsUtility.LinesWithFill(tg.get_LineType())==false) 490 return shapes; 491 492 shapes=new ArrayList(); 493 //undo any fillcolor that might have been set for the existing shape 494 //because we are divorcing fill from the line 495 Shape2 shape=null; 496 497 //create a generic area tg from the pixels and clip it 498 TGLight tg2=new TGLight(); 499 tg2.set_LineType(TacticalLines.GENERAL); 500 tg2.Pixels=new ArrayList(); 501 tg2.Pixels.addAll(tg.Pixels); 502 closeAreaTG(tg2); 503 //tg2.Pixels.add(tg.Pixels.get(0)); 504 if(clipBounds != null) 505 ClipPolygon(tg2,clipBounds); 506 507 508 if(tg2.Pixels==null || tg2.Pixels.isEmpty()) 509 return null; 510 511 int j=0; 512 shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE); 513 shape.setFillColor(tg.get_FillColor()); 514 515 shape.moveTo(tg2.Pixels.get(0)); 516 for(j=1;j<tg2.Pixels.size();j++) 517 shape.lineTo(tg2.Pixels.get(j)); 518 519 if(tg.get_FillColor() != null || tg.get_FillColor().getAlpha()>1) 520 { 521 shapes.add(shape); 522 } 523 else 524 return null; 525 } 526 catch (Exception exc) { 527 ErrorLogger.LogException(_className, "LinesWithFill", 528 new RendererException("Failed inside LinesWithFill", exc)); 529 } 530 return shapes; 531 } 532 /** 533 * closes an area 534 * @param tg 535 */ 536 private static void closeAreaTG(TGLight tg) 537 { 538 try 539 { 540 if(tg.Pixels==null || tg.Pixels.isEmpty()) 541 return; 542 543 POINT2 pt0=tg.Pixels.get(0); 544 POINT2 ptn=tg.Pixels.get(tg.Pixels.size()-1); 545 if(pt0.x != ptn.x || pt0.y != ptn.y) 546 tg.Pixels.add(pt0); 547 548 } 549 catch (Exception exc) { 550 ErrorLogger.LogException(_className, "closeAreaTG", 551 new RendererException("Failed inside closeAreaTG", exc)); 552 } 553 } 554 /** 555 * DMA, DMAF fill must be handled separately because of the feint 556 * @param tg 557 * @param clipBounds 558 * @return 559 */ 560 protected static ArrayList<Shape2> fillDMA(TGLight tg, 561 ArrayList<Point2D> clipBounds) 562 { 563 ArrayList<Shape2>shapes=new ArrayList(); 564 try 565 { 566 switch(tg.get_LineType()) 567 { 568 case TacticalLines.OBSFAREA: 569 case TacticalLines.OBSAREA: 570 case TacticalLines.STRONG: 571 case TacticalLines.ZONE: 572 case TacticalLines.FORT_REVD: 573 case TacticalLines.FORT: 574 case TacticalLines.ENCIRCLE: 575 case TacticalLines.ATDITCHC: 576 case TacticalLines.ATDITCHM: 577 break; 578 default: 579 return shapes; 580 } 581 Shape2 shape=null; 582 583 //create a generic area tg from the pixels and clip it 584 int j=0; 585 TGLight tg2=new TGLight(); 586 tg2.set_LineType(TacticalLines.GENERAL); 587 tg2.Pixels=new ArrayList(); 588 //to get the original pixels size 589 int n=0; 590 n=tg.Pixels.size(); 591 592 for(j=0;j<n;j++) 593 tg2.Pixels.add(tg.Pixels.get(j)); 594 595 closeAreaTG(tg2); 596 597 if(clipBounds != null) 598 ClipPolygon(tg2,clipBounds); 599 600 if(tg2.Pixels==null || tg2.Pixels.isEmpty()) 601 return shapes; 602 603 shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE); 604 shape.setFillColor(tg.get_FillColor()); 605 606 shape.moveTo(tg2.Pixels.get(0)); 607 //original pixels do not include feint 608 for(j=1;j<tg2.Pixels.size();j++) 609 shape.lineTo(tg2.Pixels.get(j)); 610 611 shapes.add(shape); 612 } 613 catch (Exception exc) { 614 ErrorLogger.LogException(_className, "fillDMA", 615 new RendererException("Failed inside fillDMA", exc)); 616 } 617 return shapes; 618 } 619// private static Boolean isClosed(ArrayList<POINT2>pts) 620// { 621// boolean closed=false; 622// POINT2 pt0=pts.get(0); 623// POINT2 ptLast=pts.get(pts.size()-1); 624// if(pt0.x==ptLast.x && pt0.y==ptLast.y) 625// closed=true; 626// return closed; 627// } 628 /** 629 * 630 * @param tg 631 * @param clipBounds polygon representing clipping area 632 * @return 633 */ 634 protected static ArrayList<Point2D> ClipPolygon(TGLight tg, 635 ArrayList<Point2D> clipBounds) { 636 ArrayList<Point2D> poly = new ArrayList(); 637 try 638 { 639 //diagnostic 640 Boolean isClosed = clsUtility.isClosedPolygon(tg.get_LineType()); 641 //Boolean isClosed = isClosed(tg.Pixels); 642 //M. Deutch commented one line 12-27-12 643 //clipBounds=clsUtilityGE.expandPolygon(clipBounds, 20); 644 clipBounds=clsUtilityGE.expandPolygon(clipBounds, 20); 645 //int n=clipBounds.size(); 646 ArrayList polygon = clsUtilityCPOF.POINT2toPoint2D(tg.Pixels); 647 648 int j=0; 649 Map<String,Object>hashMap=new HashMap<String,Object>(); 650 //int hashCode=0; 651 for(j=0;j<polygon.size();j++) 652 hashMap.put(Integer.toString(j), polygon.get(j)); 653 654 //close the clipbounds if necessary 655 Point2D clipBoundsPtStart=clipBounds.get(0); 656 Point2D clipBoundsPtEnd=clipBounds.get(clipBounds.size()-1); 657 if(clipBoundsPtStart.getX() != clipBoundsPtEnd.getX() || 658 clipBoundsPtStart.getY() != clipBoundsPtEnd.getY()) 659 clipBounds.add(clipBoundsPtStart); 660 661 int addedLinePoints = 0; 662 if (isClosed) 663 polygon.remove(polygon.size() - 1); 664 else 665 { 666 addedLinePoints = AddBoundaryPointsForLines(polygon, clipBounds); 667 } 668 669 //for(j=0;j<clipBounds.size()-1;j++) 670 for(j=0;j<clipBounds.size()-1;j++) 671 { 672 if(j==0) 673 poly=clipSide(tg,polygon,j,clipBounds); 674 else 675 poly=clipSide(tg,poly,j,clipBounds); 676 } 677 678 679 if (isClosed) 680 { 681 if (poly.size() > 0) 682 { 683 poly.add(poly.get(0)); 684 } 685 } 686 else 687 { 688 switch (addedLinePoints) 689 { 690 case 0: //no points were added, do nothing 691 break; 692 case 1: //point was added to the front to make algorithm work, remove segment 693 if (poly.size() > 0) { 694 poly.remove(0); 695 } 696 if (poly.size() > 0) { 697 poly.remove(0); 698 } 699 break; 700 case 2: //point was added to the end to make algorithm work, remove segment 701 if (poly.size() > 0) { 702 poly.remove(poly.size() - 1); 703 } 704 if (poly.size() > 0) { 705 poly.remove(poly.size() - 1); 706 } 707 break; 708 case 3: //point was added to the front and end to make algorithm work, remove segments 709 if (poly.size() > 0) { 710 poly.remove(0); 711 } 712 if (poly.size() > 0) { 713 poly.remove(0); 714 } 715 if (poly.size() > 0) { 716 poly.remove(poly.size() - 1); 717 } 718 if (poly.size() > 0) { 719 poly.remove(poly.size() - 1); 720 } 721 break; 722 } 723 } 724 725 if (isClosed == true) 726 { 727 if (poly.size() > 2) 728 { 729 tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2Mapped(poly,hashMap); 730 } 731 else 732 { 733 tg.Pixels=new ArrayList(); 734 } 735 736 } 737 else 738 { 739 if (poly.size() > 1) 740 { 741 tg.Pixels = clsUtilityCPOF.Point2DtoPOINT2Mapped(poly,hashMap); 742 } 743 else 744 { 745 tg.Pixels=new ArrayList(); 746 } 747 } 748 749 } catch (Exception exc) { 750 ErrorLogger.LogException(_className, "ClipPolygon", 751 new RendererException("Failed inside ClipPolygon", exc)); 752 } 753 return poly; 754 } 755}