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