001/* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005package armyc2.c5isr.JavaLineArray; 006 007import java.util.ArrayList; 008 009import armyc2.c5isr.JavaTacticalRenderer.TGLight; 010import armyc2.c5isr.renderer.utilities.ErrorLogger; 011import armyc2.c5isr.renderer.utilities.RendererException; 012 013import java.io.*; 014import armyc2.c5isr.graphics2d.*; 015import armyc2.c5isr.renderer.utilities.IPointConversion; 016import armyc2.c5isr.JavaTacticalRenderer.mdlGeodesic; 017import armyc2.c5isr.graphics2d.GeneralPath; 018import armyc2.c5isr.graphics2d.PathIterator; 019import armyc2.c5isr.graphics2d.Point; 020import armyc2.c5isr.graphics2d.Point2D; 021import armyc2.c5isr.graphics2d.Shape; 022 023/** 024 * A class to provide the utility functions required for calculating the line 025 * points. 026 * 027 */ 028public final class lineutility { 029 030 private static final String _className = "lineutility"; 031 public static final int extend_left = 0; 032 public static final int extend_right = 1; 033 public static final int extend_above = 2; 034 public static final int extend_below = 3; 035 036 /** 037 * Resizes the array to the length speicifed, called by the Channels class. 038 * 039 * @param pLinePoints the array to resize 040 * @param length the length to which to resize the array. 041 * @return the resized array 042 */ 043 protected static POINT2[] ResizeArray(POINT2[] pLinePoints, int length) { 044 POINT2[] array = new POINT2[length]; 045 try { 046 if (pLinePoints.length <= length) { 047 return pLinePoints; 048 } 049 050 int j = 0; 051 for (j = 0; j < length; j++) { 052 array[j] = new POINT2(pLinePoints[j]); 053 } 054 } catch (Exception exc) { 055 ErrorLogger.LogException(_className, "ResizeArray", 056 new RendererException("Failed inside ResizeArray", exc)); 057 } 058 return array; 059 } 060 061 /** 062 * post-segments a line segment into 50 pixel intervals 063 * 064 * @param pt0 065 * @param pt1 066 * @param shape 067 */ 068 protected static void SegmentLineShape(POINT2 pt0, POINT2 pt1, Shape2 shape) { 069 try { 070 if (pt0 == null || pt1 == null) { 071 return; 072 } 073 074 int j = 0, n = 0; 075 double dist = CalcDistanceDouble(pt0, pt1); 076 n = (int) (dist / 25d); 077 POINT2 pt = null; 078 shape.lineTo(pt0); 079 for (j = 1; j <= n; j++) { 080 pt = lineutility.ExtendAlongLineDouble(pt0, pt1, 25); 081 shape.lineTo(pt); 082 } 083 shape.lineTo(pt1); 084 } catch (Exception exc) { 085 ErrorLogger.LogException(_className, "SegmentLineShape", 086 new RendererException("Failed inside SegmentLineShape", exc)); 087 } 088 } 089 090 /** 091 * Calculates the middle segment for the Direction of Attack Aviation symbol 092 * 093 * @param pLinePoints the point array 094 * @param vblSaveCounter the size of the point array 095 * @return the middle segment 096 */ 097 public static int GetDirAtkAirMiddleSegment(POINT2[] pLinePoints, 098 int vblSaveCounter) { 099 int middleSegment = -1; 100 try { 101 double d = 0; 102 int k = 0; 103 for (k = vblSaveCounter - 1; k > 0; k--) { 104 d += lineutility.CalcDistanceDouble(pLinePoints[k], pLinePoints[k - 1]); 105 if (d > 60) { 106 break; 107 } 108 } 109 if (d > 60) { 110 middleSegment = k; 111 } else { 112 if (vblSaveCounter <= 3) { 113 middleSegment = 1; 114 } else { 115 middleSegment = 2; 116 } 117 } 118 } catch (Exception exc) { 119 ErrorLogger.LogException(_className, "GetDirAtkAirMiddleSegment", 120 new RendererException("Failed inside GetDirAtkAirMiddleSegment", exc)); 121 } 122 return middleSegment; 123 } 124 125 /** 126 * Computes the angle in radians between two points 127 * 128 * @param pt0 the first point 129 * @param pt1 the last point 130 * 131 * @return the angle in radians 132 */ 133 protected static double CalcSegmentAngleDouble(POINT2 pt0, 134 POINT2 pt1) { 135 double dAngle = 0; 136 try { 137 //declarations 138 int nTemp = 0; 139 ref<double[]> m = new ref(); 140 //end declarations 141 142 nTemp = CalcTrueSlopeDouble(pt0, pt1, m); 143 if (nTemp == 0) { 144 dAngle = Math.PI / 2; 145 } else { 146 dAngle = Math.atan(m.value[0]); 147 } 148 149 } catch (Exception exc) { 150 ErrorLogger.LogException(_className, "CalcSegmentAngleDouble", 151 new RendererException("Failed inside CalcSegmentAngleDouble", exc)); 152 } 153 return dAngle; 154 } 155 156 /** 157 * POINT2 in previous applications has been a struct that did not require 158 * initialization. 159 * 160 * @param pts array of points to instantiate. 161 */ 162 protected static void InitializePOINT2Array(POINT2[] pts) { 163 //int j=0; 164 if (pts == null || pts.length == 0) { 165 return; 166 } 167 int n=pts.length; 168 //for (int j = 0; j < pts.length; j++) 169 for (int j = 0; j < n; j++) 170 { 171 pts[j] = new POINT2(); 172 } 173 } 174 175 /** 176 * Calculates the center point of an area using the first vblCounter points 177 * in the array. 178 * 179 * @param pLinePoints the client points 180 * @param vblCounter the number of points in the array to use 181 * 182 * @return the center point 183 */ 184 protected static POINT2 CalcCenterPointDouble(POINT2[] pLinePoints, 185 int vblCounter) { 186 POINT2 CenterLinePoint = new POINT2(pLinePoints[0]); 187 try { 188 //declarations 189 int j = 0; 190 double dMinX = pLinePoints[0].x, 191 dMinY = pLinePoints[0].y, 192 dMaxX = pLinePoints[0].x, 193 dMaxY = pLinePoints[0].y; 194 195 //end declarations 196 dMinX = pLinePoints[0].x; 197 dMinY = pLinePoints[0].y; 198 dMaxX = pLinePoints[0].x; 199 dMaxY = pLinePoints[0].y; 200 201 for (j = 0; j < vblCounter; j++) { 202 if (pLinePoints[j].x < dMinX) { 203 dMinX = pLinePoints[j].x; 204 } 205 206 if (pLinePoints[j].y < dMinY) { 207 dMinY = pLinePoints[j].y; 208 } 209 210 if (pLinePoints[j].x > dMaxX) { 211 dMaxX = pLinePoints[j].x; 212 } 213 214 if (pLinePoints[j].y > dMaxY) { 215 dMaxY = pLinePoints[j].y; 216 } 217 218 } //end for 219 220 CenterLinePoint.x = (dMinX + dMaxX) / 2; 221 CenterLinePoint.y = (dMinY + dMaxY) / 2; 222 } catch (Error exc) { 223 ErrorLogger.LogException(_className, "CalcCenterPointDouble", 224 new RendererException("Failed inside CalcCenterPointDouble", exc)); 225 } 226 return CenterLinePoint; 227 } 228 229 /** 230 * Called by renderer Modifier2 class after ArrayList.ToArray was called, 231 * which produces an array of objects. 232 * 233 * @param pLinePoints 234 * @param vblCounter 235 * @return 236 */ 237 public static POINT2 CalcCenterPointDouble2(Object[] pLinePoints, 238 int vblCounter) { 239 POINT2 pt0 = (POINT2) pLinePoints[0]; 240 POINT2 CenterLinePoint = new POINT2(); 241 try { 242 //declarations 243 int j = 0; 244 double dMinX = pt0.x, 245 dMinY = pt0.y, 246 dMaxX = pt0.x, 247 dMaxY = pt0.y; 248 249 //end declarations 250 dMinX = pt0.x; 251 dMinY = pt0.y; 252 dMaxX = pt0.x; 253 dMaxY = pt0.y; 254 255 POINT2 pt; 256 257 for (j = 0; j < vblCounter; j++) { 258 pt = (POINT2) pLinePoints[j]; 259 if (pt.x < dMinX) { 260 dMinX = pt.x; 261 } 262 263 if (pt.y < dMinY) { 264 dMinY = pt.y; 265 } 266 267 if (pt.x > dMaxX) { 268 dMaxX = pt.x; 269 } 270 271 if (pt.y > dMaxY) { 272 dMaxY = pt.y; 273 } 274 275 } //end for 276 277 CenterLinePoint.x = (dMinX + dMaxX) / 2; 278 CenterLinePoint.y = (dMinY + dMaxY) / 2; 279 } catch (Error exc) { 280 ErrorLogger.LogException(_className, "CalcCenterPointDouble2", 281 new RendererException("Failed inside CalcCenterPointDouble2", exc)); 282 } 283 return CenterLinePoint; 284 } 285 286 /** 287 * Calculates the distance in pixels between two points 288 * 289 * @param p1 the first point 290 * @param p2 the last point 291 * 292 * @return the distance between p1 and p2 in pixels 293 */ 294 public static double CalcDistanceDouble(POINT2 p1, 295 POINT2 p2) { 296 double returnValue = 0; 297 try { 298 returnValue = Math.sqrt((p1.x - p2.x) 299 * (p1.x - p2.x) 300 + (p1.y - p2.y) 301 * (p1.y - p2.y)); 302 303 //sanity check 304 //return x or y distance if returnValue is 0 or infinity 305 double xdist = Math.abs(p1.x - p2.x); 306 double ydist = Math.abs(p1.y - p2.y); 307 double max = xdist; 308 if (ydist > xdist) { 309 max = ydist; 310 } 311 312 if (returnValue == 0 || Double.isInfinite(returnValue)) { 313 if (max > 0) { 314 returnValue = max; 315 } 316 } 317 } catch (Exception exc) { 318 ErrorLogger.LogException(_className, "CalcDistanceDouble", 319 new RendererException("Failed inside CalcDistanceDouble", exc)); 320 } 321 return returnValue; 322 } 323 324 /** 325 * Calculates the distance in pixels between two points 326 * 327 * @param p1 the first point 328 * @param p2 the last point 329 * 330 * @return the distance between p1 and p2 in pixels 331 */ 332 public static double CalcDistanceDouble(Point2D p1, 333 Point2D p2) { 334 double returnValue = 0; 335 try { 336 returnValue = Math.sqrt((p1.getX() - p2.getX()) 337 * (p1.getX() - p2.getX()) 338 + (p1.getY() - p2.getY()) 339 * (p1.getY() - p2.getY())); 340 341 //sanity check 342 //return x or y distance if returnValue is 0 or infinity 343 double xdist = Math.abs(p1.getX() - p2.getX()); 344 double ydist = Math.abs(p1.getY() - p2.getY()); 345 double max = xdist; 346 if (ydist > xdist) { 347 max = ydist; 348 } 349 350 if (returnValue == 0 || Double.isInfinite(returnValue)) { 351 if (max > 0) { 352 returnValue = max; 353 } 354 } 355 } catch (Exception exc) { 356 ErrorLogger.LogException(_className, "CalcDistanceDouble", 357 new RendererException("Failed inside CalcDistanceDouble", exc)); 358 } 359 return returnValue; 360 } 361 362 /** 363 * Computes the slope of a line 364 * 365 * @param firstLinePoint the first line point 366 * @param lastLinePoint the last line point 367 * @param slope OUT - object with member to hold the slope of the line 368 * 369 * @return 1 if successful, else return 0 370 */ 371 protected static int CalcTrueSlopeDouble(POINT2 firstLinePoint, 372 POINT2 lastLinePoint, 373 ref<double[]> slope)//ref is a double 374 { 375 int result = 1; 376 try { 377 if (slope.value == null) { 378 slope.value = new double[1]; 379 } 380 381 double deltaX = 0, deltaY = 0; 382 deltaX = firstLinePoint.x - lastLinePoint.x; 383 //if (deltaX == 0) 384 if (Math.abs(deltaX) < 1) 385 { 386 //deltaX = 1; 387 if(deltaX>=0) 388 deltaX=1; 389 else 390 deltaX=-1; 391 result = 1; 392 } 393 deltaY = firstLinePoint.y - lastLinePoint.y; 394 395 slope.value[0] = deltaY / deltaX; //cannot blow up 396 } catch (Error exc) { 397 ErrorLogger.LogException(_className, "CalcTrueSlopeDouble", 398 new RendererException("Failed inside CalcTrueSlopeDouble", exc)); 399 } 400 return result; 401 } 402 403 public static void WriteFile(String str) { 404 try { 405 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("Test.txt")); 406 bufferedWriter.write(str); 407 bufferedWriter.close(); 408 bufferedWriter = null; 409 } catch (Exception exc) { 410 ErrorLogger.LogException(_className, "WriteFile", 411 new RendererException("Failed inside WriteFile", exc)); 412 } 413 } 414 415 /** 416 * reverses the first vblCounter points 417 * 418 * @param pLowerLinePoints OUT - points to reverse 419 * @param vblCounter 420 */ 421 protected static void ReversePointsDouble2(POINT2[] pLowerLinePoints, 422 int vblCounter) { 423 try { 424 POINT2[] pResultPoints = new POINT2[vblCounter]; 425 int k = 0; 426 for (k = 0; k < vblCounter; k++) { 427 pResultPoints[k] = new POINT2(pLowerLinePoints[vblCounter - k - 1]); 428 } 429 for (k = 0; k < vblCounter; k++) { 430 pLowerLinePoints[k] = new POINT2(pResultPoints[k]); 431 } 432 pResultPoints = null; 433 } catch (Exception exc) { 434 ErrorLogger.LogException(_className, "ReversePointsDouble2", 435 new RendererException("Failed inside ReversePointsDouble2", exc)); 436 } 437 } 438 439 public static boolean CalcTrueSlopeDoubleForRoutes(POINT2 firstLinePoint, 440 POINT2 lastLinePoint, 441 ref<double[]> slope) { 442 try { 443 double deltaX = 0, deltaY = 0; 444 deltaX = (double) (firstLinePoint.x) - (double) (lastLinePoint.x); 445 if (Math.abs(deltaX) < 2) //was 2,infinite slope 446 { 447 return (false); 448 } 449 450 deltaY = (double) (firstLinePoint.y) - (double) (lastLinePoint.y); 451 if (slope.value == null) { 452 slope.value = new double[1]; 453 } 454 455 slope.value[0] = deltaY / deltaX; 456 } catch (Exception exc) { 457 ErrorLogger.LogException(_className, "CalcTrueSlopeDoubleForRoutes", 458 new RendererException("Failed inside CalcTrueSlopeDoubleForRoutes", exc)); 459 } 460 return true; 461 } 462 463 /** 464 * Computes the slope of a line 465 * 466 * @param firstLinePoint the first line point 467 * @param lastLinePoint the last line point 468 * @param slope OUT - object with member to hold the slope of the line 469 * 470 * @return true if successful 471 */ 472 public static boolean CalcTrueSlopeDouble2(POINT2 firstLinePoint, 473 POINT2 lastLinePoint, 474 ref<double[]> slope) { 475 Boolean result = true; 476 try { 477 double deltaX = 0, deltaY = 0; 478 deltaX = (double) (firstLinePoint.x) - (double) (lastLinePoint.x); 479 //if (deltaX == 0) 480 if (Math.abs(deltaX) < 1) 481 { 482 //deltaX = 1; 483 if(deltaX>=0) 484 deltaX=1; 485 else 486 deltaX=-1; 487 result = false; 488 } 489 490 deltaY = (double) (firstLinePoint.y) - (double) (lastLinePoint.y); 491 if (slope.value == null) { 492 slope.value = new double[1]; 493 } 494 495 slope.value[0] = deltaY / deltaX; 496 } catch (Exception exc) { 497 ErrorLogger.LogException(_className, "CalcTrueSlopeDouble2", 498 new RendererException("Failed inside CalcTrueSlopeDouble2", exc)); 499 } 500 return result; 501 } 502 503 /** 504 * Calculates the slopes and y intercepts in pixels for the line from pt1 to 505 * pt2 and a parallel line a vertical distance from the line 506 * 507 * @param nDistance the distance in pixels 508 * @param linePoint1 first point on the line 509 * @param linePoint2 last point on the line 510 * @param pdResult OUT - array to hold m, b for both lines 511 * 512 * @return 1 if the lines are not vertical, else return 0 513 */ 514 protected static int CalcTrueLinesDouble(long nDistance, 515 POINT2 linePoint1, 516 POINT2 linePoint2, 517 ref<double[]> pdResult) //for vertical line e.g. if line equation is x=7 518 { 519 try { 520 //declarations 521 int nTemp = 0; 522 double b = 0; 523 double delta = 0; 524 ref<double[]> m = new ref(); 525 //end declarations 526 nTemp = CalcTrueSlopeDouble(linePoint1, linePoint2, m); 527 pdResult.value = new double[6]; 528 //Fill the result array with the line parameters 529 if (nTemp == 0) //vertical lines 530 { 531 pdResult.value[3] = linePoint1.x + (double) nDistance; //the lower line eqn, e.g. x=7 532 pdResult.value[5] = linePoint1.x - (double) nDistance; //the upper line eqn, 533 return 0; 534 } else { 535 b = linePoint2.y - m.value[0] * linePoint2.x; 536 delta = Math.sqrt(m.value[0] * m.value[0] * ((double) (nDistance) * (double) (nDistance)) 537 + ((double) (nDistance) * (double) (nDistance))); 538 pdResult.value[0] = m.value[0]; //original line eq'n: y = mx + b 539 pdResult.value[1] = b; 540 pdResult.value[2] = m.value[0]; //lower line eq'n: y = mx + (b+dDistance) 541 pdResult.value[3] = b + delta; 542 pdResult.value[4] = m.value[0]; //upper line eq'n: y = mx + (b-dDistance) 543 pdResult.value[5] = b - delta; 544 } 545 } catch (Exception exc) { 546 ErrorLogger.LogException(_className, "CalcTrueLinesDouble", 547 new RendererException("Failed inside CalcTrueLinesDouble", exc)); 548 } 549 return 1; 550 } 551 552 /** 553 * Calculates the intersection of two lines. 554 * 555 * @param m1 slope of first line 556 * @param b1 Y intercept of first line 557 * @param m2 slope of second line 558 * @param b2 Y intercept of second line 559 * @param bolVertical1 0 if first line is vertical, else 1 560 * @param bolVertical2 0 if second line is vertical, else 1 561 * @param X1 X intercept if first line is vertical 562 * @param X2 X intercept if 2nd line is vertical. 563 * 564 * @return intersection point 565 */ 566 public static POINT2 CalcTrueIntersectDouble2(double m1, 567 double b1, 568 double m2, 569 double b2, 570 int bolVertical1, 571 int bolVertical2, 572 double X1, //x intercept if line1 is vertical 573 double X2) { 574 POINT2 ptIntersect = new POINT2(); 575 try { 576 //declarations 577 double x = 0, y = 0; 578 //end declarations 579 580 //initialize ptIntersect 581 ptIntersect.x = X1; 582 ptIntersect.y = X2; 583 if (bolVertical1 == 0 && bolVertical2 == 0) //both lines vertical 584 { 585 return ptIntersect; 586 } 587 //the following 3 if blocks are the only ways to get an intersection 588 if (bolVertical1 == 0 && bolVertical2 == 1) //line1 vertical, line2 not 589 { 590 ptIntersect.x = X1; 591 ptIntersect.y = m2 * X1 + b2; 592 return ptIntersect; 593 } 594 if (bolVertical1 == 1 && bolVertical2 == 0) //line2 vertical, line1 not 595 { 596 ptIntersect.x = X2; 597 ptIntersect.y = m1 * X2 + b1; 598 return ptIntersect; 599 } 600 //if either of the lines is vertical function has already returned 601 //so both m1 and m2 should be valid 602 if (m1 != m2) { 603 x = (b2 - b1) / (m1 - m2); //cannot blow up 604 y = (m1 * x + b1); 605 ptIntersect.x = x; 606 ptIntersect.y = y; 607 return ptIntersect; 608 } 609 } catch (Exception exc) { 610 ErrorLogger.LogException(_className, "CalcTrueIntersectDouble2", 611 new RendererException("Failed inside CalcTrueIntersectDouble2", exc)); 612 } 613 return ptIntersect; 614 } 615 616 /** 617 * Calculates an offset point for channel types which require arrows. 618 * 619 * @param startLinePoint the first point 620 * @param endLinePoint the last point 621 * @param nOffset the offset in pixels 622 * 623 * @return the offset point 624 */ 625 protected static POINT2 GetOffsetPointDouble(POINT2 startLinePoint, 626 POINT2 endLinePoint, 627 long nOffset) { 628 POINT2 tempLinePoint = new POINT2(startLinePoint); 629 try { 630 //declarations 631 double dx = endLinePoint.x - startLinePoint.x, 632 dy = endLinePoint.y - startLinePoint.y, 633 dOffset = (double) nOffset, 634 dHypotenuse = 0, 635 dAngle = 0; 636 637 //end declarations 638 if (dx == 0) { 639 if (dy > 0) { 640 tempLinePoint.x = endLinePoint.x; 641 tempLinePoint.y = endLinePoint.y + dOffset; 642 } else { 643 tempLinePoint.x = endLinePoint.x; 644 tempLinePoint.y = endLinePoint.y - dOffset; 645 } 646 return tempLinePoint; 647 } 648 if (dy == 0) { 649 if (dx > 0) { 650 tempLinePoint.x = endLinePoint.x + dOffset; 651 tempLinePoint.y = endLinePoint.y; 652 } else { 653 tempLinePoint.x = endLinePoint.x - dOffset; 654 tempLinePoint.y = endLinePoint.y; 655 } 656 return tempLinePoint; 657 } 658 659 if (dy == 0) { 660 dAngle = 0; 661 } else { 662 dAngle = Math.atan(dx / dy) + Math.PI / 2;//1.570795; 663 } 664 dHypotenuse = (double) nOffset; 665 if (endLinePoint.x > startLinePoint.x) { 666 tempLinePoint.x = endLinePoint.x + dHypotenuse * Math.abs(Math.cos(dAngle)); 667 } else { 668 tempLinePoint.x = endLinePoint.x - dHypotenuse * Math.abs(Math.cos(dAngle)); 669 } 670 if (endLinePoint.y > startLinePoint.y) { 671 tempLinePoint.y = endLinePoint.y + dHypotenuse * Math.abs(Math.sin(dAngle)); 672 } else { 673 tempLinePoint.y = endLinePoint.y - dHypotenuse * Math.abs(Math.sin(dAngle)); 674 } 675 676 } catch (Exception exc) { 677 ErrorLogger.LogException(_className, "GetOffsetPointDouble", 678 new RendererException("Failed inside GetOffsetPointDouble", exc)); 679 } 680 return (tempLinePoint); 681 } 682 683 /** 684 * Used for DMAF 685 * 686 * @param pLinePoints the client points 687 * @return ArrayList of X points 688 */ 689 protected static ArrayList LineOfXPoints(TGLight tg, POINT2[] pLinePoints) { 690 ArrayList xPoints = new ArrayList(); 691 try { 692 int j = 0, k = 0; 693 double dist = 0; 694 int iterations = 0; 695 POINT2 frontPt = null, backPt = null; 696 POINT2 extendFrontAbove = null, extendFrontBelow = null; 697 POINT2 extendBackAbove = null, extendBackBelow = null; 698 POINT2 xPoint1 = null, xPoint2 = null; 699 int n=pLinePoints.length; 700 final double xSize = arraysupport.getScaledSize(5, tg.get_LineThickness(), tg.get_patternScale()); 701 final double dIncrement = xSize * 4; 702 //for (j = 0; j < pLinePoints.length - 1; j++) 703 for (j = 0; j < n - 1; j++) 704 { 705 dist = CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]); 706 iterations = (int) ((dist - xSize) / dIncrement); 707 if (dist - iterations * dIncrement > dIncrement / 2) { 708 iterations += 1; 709 } 710 711 for (k = 0; k < iterations; k++) { 712 frontPt = ExtendAlongLineDouble(pLinePoints[j], pLinePoints[j + 1], k * dIncrement - xSize); 713 backPt = ExtendAlongLineDouble(pLinePoints[j], pLinePoints[j + 1], k * dIncrement + xSize); 714 extendFrontAbove = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], frontPt, 2, xSize); 715 extendFrontBelow = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], frontPt, 3, xSize); 716 extendBackAbove = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], backPt, 2, xSize); 717 extendBackBelow = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], backPt, 3, xSize); 718 xPoints.add(extendFrontAbove); 719 extendBackBelow.style = 5; 720 xPoints.add(extendBackBelow); 721 xPoints.add(extendBackAbove); 722 extendFrontBelow.style = 5; 723 xPoints.add(extendFrontBelow); 724 } 725 } 726 } catch (Exception exc) { 727 ErrorLogger.LogException(_className, "LineOfXPoints", 728 new RendererException("Failed inside LineOfXPoints", exc)); 729 } 730 return xPoints; 731 } 732 733 /** 734 * Computes the distance in pixels of pt3 to the line from pt1 to pt2. 735 * 736 * @param pt1 first line point 737 * @param pt2 last line point 738 * @param pt3 point distance to compute 739 * @return distance to pt3 740 */ 741 public static double CalcDistanceToLineDouble(POINT2 pt1, 742 POINT2 pt2, 743 POINT2 pt3) { 744 double dResult = 0; 745 try { 746 //declarations 747 double m1 = 1, b = 0, b1 = 0; 748 POINT2 ptIntersect = new POINT2(pt1); 749 int bolVertical = 0; 750 ref<double[]> m = new ref(); 751 //end declarations 752 753 bolVertical = CalcTrueSlopeDouble(pt1, pt2, m); 754 755 //get line y intercepts 756 if (bolVertical != 0 && m.value[0] != 0) { 757 m1 = -1 / m.value[0]; 758 b = pt1.y - m.value[0] * pt1.x; 759 b1 = pt3.y - m1 * pt3.x; 760 ptIntersect = CalcTrueIntersectDouble2(m.value[0], b, m1, b1, 1, 1, ptIntersect.x, ptIntersect.y); 761 } 762 if (bolVertical != 0 && m.value[0] == 0) //horizontal line 763 { 764 ptIntersect.y = pt1.y; 765 ptIntersect.x = pt3.x; 766 } 767 if (bolVertical == 0) //vertical line 768 { 769 ptIntersect.y = pt3.y; 770 ptIntersect.x = pt1.x; 771 } 772 773 dResult = CalcDistanceDouble(pt3, ptIntersect); 774 } catch (Exception exc) { 775 //System.out.println(e.getMessage()); 776 ErrorLogger.LogException(_className, "CaclDistanceToLineDouble", 777 new RendererException("Failed inside CalcDistanceToLineDouble", exc)); 778 } 779 return dResult; 780 } 781 782 /** 783 * Calculates a point along a line. Returns the past point if the distance 784 * is 0. 785 * 786 * @param pt1 first line point 787 * @param pt2 last line point 788 * @param dist extension distance in pixels from the beginning of the line 789 * 790 * @return the extension point 791 */ 792 public static POINT2 ExtendLineDouble(POINT2 pt1, 793 POINT2 pt2, 794 double dist) { 795 POINT2 pt3 = new POINT2(); 796 try { 797 double dOriginalDistance = CalcDistanceDouble(pt1, pt2); 798 if (dOriginalDistance == 0 || dist == 0) { 799 return pt2; 800 } 801 802 pt3.x = (dOriginalDistance + dist) / dOriginalDistance * (pt2.x - pt1.x) + pt1.x; 803 pt3.y = (dOriginalDistance + dist) / dOriginalDistance * (pt2.y - pt1.y) + pt1.y; 804 } catch (Exception exc) { 805 //System.out.println(e.getMessage()); 806 ErrorLogger.LogException(_className, "ExtendLineDouble", 807 new RendererException("Failed inside ExtendLineDouble", exc)); 808 } 809 return pt3; 810 } 811 812 /** 813 * Extends a point along a line. If dist is 0 returns last point. 814 * 815 * @param pt1 first point on the line 816 * @param pt2 last point on the line 817 * @param dist the distance in pixels from pt1 818 * 819 * @return the extended point 820 */ 821 public static POINT2 ExtendAlongLineDouble(POINT2 pt1, POINT2 pt2, double dist) { 822 POINT2 pt3 = new POINT2(); 823 try { 824 double dOriginalDistance = CalcDistanceDouble(pt1, pt2); 825 if (dOriginalDistance == 0 || dist == 0) { 826 return pt2; 827 } 828 829 pt3.x = ((dist / dOriginalDistance) * (pt2.x - pt1.x) + pt1.x); 830 pt3.y = ((dist / dOriginalDistance) * (pt2.y - pt1.y) + pt1.y); 831 } catch (Exception exc) { 832 //System.out.println(e.getMessage()); 833 ErrorLogger.LogException(_className, "ExtendAlongLineDouble", 834 new RendererException("Failed inside ExtendAlongLineDouble", exc)); 835 } 836 return pt3; 837 } 838 839 public static POINT2 ExtendAlongLineDouble2(POINT2 pt1, POINT2 pt2, double dist) { 840 POINT2 pt3 = new POINT2(); 841 try { 842 double dOriginalDistance = CalcDistanceDouble(pt1, pt2); 843 if (dOriginalDistance == 0 || dist == 0) { 844 return pt1; 845 } 846 847 pt3.x = (dist / dOriginalDistance * (pt2.x - pt1.x) + pt1.x); 848 pt3.y = (dist / dOriginalDistance * (pt2.y - pt1.y) + pt1.y); 849 } catch (Exception exc) { 850 //System.out.println(e.getMessage()); 851 ErrorLogger.LogException(_className, "ExtendAlongLineDouble2", 852 new RendererException("Failed inside ExtendAlongLineDouble2", exc)); 853 } 854 return pt3; 855 } 856 857 public static Point2D ExtendAlongLineDouble2(Point2D pt1, Point2D pt2, double dist) { 858 try { 859 double dOriginalDistance = CalcDistanceDouble(pt1, pt2); 860 if (dOriginalDistance == 0 || dist == 0) { 861 return new Point2D.Double(pt1.getX(), pt1.getY()); 862 } 863 864 double x = (dist / dOriginalDistance * (pt2.getX() - pt1.getX()) + pt1.getX()); 865 double y = (dist / dOriginalDistance * (pt2.getY() - pt1.getY()) + pt1.getY()); 866 return new Point2D.Double(x, y); 867 } catch (Exception exc) { 868 ErrorLogger.LogException(_className, "ExtendAlongLineDouble2", 869 new RendererException("Failed inside ExtendAlongLineDouble2", exc)); 870 } 871 return new Point2D.Double(0, 0); 872 } 873 874 public static POINT2 ExtendAlongLineDouble(POINT2 pt1, POINT2 pt2, double dist, int styl) { 875 POINT2 pt3 = new POINT2(); 876 try { 877 double dOriginalDistance = CalcDistanceDouble(pt1, pt2); 878 if (dOriginalDistance == 0 || dist == 0) { 879 return pt2; 880 } 881 882 pt3.x = (dist / dOriginalDistance * (pt2.x - pt1.x) + pt1.x); 883 pt3.y = (dist / dOriginalDistance * (pt2.y - pt1.y) + pt1.y); 884 pt3.style = styl; 885 } catch (Exception exc) { 886 //System.out.println(e.getMessage()); 887 ErrorLogger.LogException(_className, "ExtendAlongLineDouble", 888 new RendererException("Failed inside ExtendAlongLineDouble", exc)); 889 } 890 return pt3; 891 } 892 893 /** 894 * Extends a point above a line 895 * 896 * @param pt1 first line point 897 * @param pt2 last line point 898 * @param pt3 point at which to extend 899 * @param d distance in pixels to extend above the line 900 * @param X OUT - extended point x value 901 * @param Y OUT - extended point y value 902 * @param direction direction to extend the line 903 * 904 * @return 1 if successful, else return 0 905 */ 906 protected static int ExtendLineAbove(POINT2 pt1, 907 POINT2 pt2, 908 POINT2 pt3, 909 double d, 910 ref<double[]> X, 911 ref<double[]> Y, 912 int direction) { 913 try { 914 ref<double[]> m = new ref(); 915 double dx = 0, dy = 0; 916 int bolVertical = 0; 917 918 X.value = new double[1]; 919 Y.value = new double[1]; 920 921 bolVertical = CalcTrueSlopeDouble(pt1, pt2, m); 922 if (bolVertical == 0) { 923 return 0; //cannot extend above a vertical line 924 } 925 if (m.value[0] == 0) { 926 X.value[0] = pt3.x; 927 if (direction == 0) //extend above the line 928 { 929 Y.value[0] = pt3.y - Math.abs(d); 930 } else //extend below the line 931 { 932 Y.value[0] = pt3.y + Math.abs(d); 933 } 934 return 1; 935 } 936 //the line is neither vertical nor horizontal 937 //else function would already have returned 938 if (direction == 0) //extend above the line 939 { 940 dy = -Math.abs(d / (m.value[0] * Math.sqrt(1 + 1 / (m.value[0] * m.value[0])))); 941 } else //extend below the line 942 { 943 dy = Math.abs(d / (m.value[0] * Math.sqrt(1 + 1 / (m.value[0] * m.value[0])))); 944 } 945 946 dx = -m.value[0] * dy; 947 X.value[0] = pt3.x + dx; 948 Y.value[0] = pt3.y + dy; 949 } catch (Exception exc) { 950 //System.out.println(e.getMessage()); 951 ErrorLogger.LogException(_className, "ExtendLineAbove", 952 new RendererException("Failed inside ExtendLineAbove", exc)); 953 } 954 return 1; 955 } 956 957 /** 958 * Extends a point to the left of a line 959 * 960 * @param pt1 first line point 961 * @param pt2 last line point 962 * @param pt3 point at which to extend 963 * @param d distance in pixels to extend above the line 964 * @param X OUT - extended point x value 965 * @param Y OUT - extended point y value 966 * @param direction direction to extend the line 967 * 968 * @return 1 if successful, else return 0 969 */ 970 protected static int ExtendLineLeft(POINT2 pt1, 971 POINT2 pt2, 972 POINT2 pt3, 973 double d, 974 ref<double[]> X, 975 ref<double[]> Y, 976 int direction) { 977 try { 978 ref<double[]> m = new ref(); 979 double dx = 0, dy = 0; 980 int bolVertical = 0; 981 982 X.value = new double[1]; 983 Y.value = new double[1]; 984 985 bolVertical = CalcTrueSlopeDouble(pt1, pt2, m); 986 if (bolVertical != 0 && m.value[0] == 0) { 987 return 0; //cannot left of horiz line 988 } 989 if (bolVertical == 0) //vertical line 990 { 991 Y.value[0] = pt3.y; 992 if (direction == 0) //extend left of the line 993 { 994 X.value[0] = pt3.x - Math.abs(d); 995 } else //extend right of the line 996 { 997 X.value[0] = pt3.x + Math.abs(d); 998 } 999 1000 return 1; 1001 } 1002 //the line is neither vertical nor horizontal 1003 //else function would already have returned 1004 if (direction == 0) //extend left of the line 1005 { 1006 dx = -Math.abs(d / Math.sqrt(1 + 1 / (m.value[0] * m.value[0]))); 1007 } else //extend right of the line 1008 { 1009 dx = Math.abs(d / Math.sqrt(1 + 1 / (m.value[0] * m.value[0]))); 1010 } 1011 1012 dy = -(1 / m.value[0]) * dx; 1013 1014 X.value[0] = pt3.x + dx; 1015 Y.value[0] = pt3.y + dy; 1016 } catch (Exception exc) { 1017 //System.out.println(e.getMessage()); 1018 ErrorLogger.LogException(_className, "ExtendLineLeft", 1019 new RendererException("Failed inside ExtendLineLeft", exc)); 1020 } 1021 return 1; 1022 } 1023 1024 /** 1025 * Calculates the direction of a point relative to a line 1026 * 1027 * @param pt0 first point fo the line 1028 * @param pt1 last point of the line 1029 * @param ptRelative relative point 1030 * @return 0 if left, 1 if right, 2 if above, 3 if below 1031 */ 1032 protected static int CalcDirectionFromLine(POINT2 pt0, 1033 POINT2 pt1, 1034 POINT2 ptRelative) { 1035 int result = -1; 1036 try { 1037 double m2 = 0, b1 = 0, b2 = 0; 1038 ref<double[]> m1 = new ref(); 1039 POINT2 ptIntersect = new POINT2(); 1040 //int direction=-1; 1041 //handle vertical line 1042 if (pt0.x == pt1.x) { 1043 if (ptRelative.x < pt0.x) { 1044 return 0; 1045 } else { 1046 return 1; 1047 } 1048 } 1049 //handle horizontal line so that we do not have slope = 0. 1050 if (pt0.y == pt1.y) { 1051 if (ptRelative.y < pt0.y) { 1052 return 2; 1053 } else { 1054 return 3; 1055 } 1056 } 1057 CalcTrueSlopeDouble(pt0, pt1, m1); 1058 m2 = -1 / m1.value[0]; //slope for the perpendicular line from the line to ptRelative 1059 //b=mx-y line equation for line 1060 b1 = pt0.y - m1.value[0] * pt0.x; 1061 //b=mx-y line equation for perpendicular line which contains ptRelative 1062 b2 = ptRelative.y - m2 * ptRelative.x; 1063 ptIntersect = CalcTrueIntersectDouble2(m1.value[0], b1, m2, b2, 1, 1, 0, 0); 1064 //compare the intersection point with ptRelative to get the direction, 1065 //i.e. the direction from the line is the same as the direction 1066 //from the interseciton point. 1067 if (m1.value[0] > 1) //line is steep, use left/right 1068 { 1069 if (ptRelative.x < ptIntersect.x) { 1070 return 0; 1071 } else { 1072 return 1; 1073 } 1074 } else //line is not steep, use above/below 1075 { 1076 if (ptRelative.y < ptIntersect.y) { 1077 return 2; 1078 } else { 1079 return 3; 1080 } 1081 } 1082 //should not reach this point 1083 //return direction; 1084 } catch (Exception e) { 1085 System.out.println(e.getMessage()); 1086 } 1087 return result; 1088 } 1089 1090 /** 1091 * Returns a point extended perpendicularly from a line at a given direction 1092 * 1093 * @param pt1 first line point 1094 * @param pt2 last line point 1095 * @param pt0 on line from which to extend 1096 * @param direction the direction to extend: above, below, left, right 1097 * @param d the length to extend in pixels 1098 * 1099 */ 1100 public static POINT2 ExtendDirectedLine(POINT2 pt1, 1101 POINT2 pt2, 1102 POINT2 pt0, 1103 int direction, 1104 double d) { 1105 POINT2 ptResult = new POINT2(); 1106 try { 1107 ref<double[]> X = new ref(), Y = new ref(); 1108 ptResult = new POINT2(pt0); 1109 switch (direction) { 1110 case 0: //extend left 1111 ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0); 1112 break; 1113 case 1: //extend right 1114 ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1); 1115 break; 1116 case 2: //extend above 1117 ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0); 1118 break; 1119 case 3: //extend below 1120 ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1); 1121 break; 1122 default: 1123 break; 1124 } 1125 ptResult.x = X.value[0]; 1126 ptResult.y = Y.value[0]; 1127 } catch (Exception exc) { 1128 //System.out.println(e.getMessage()); 1129 ErrorLogger.LogException(_className, "ExtendDirectedLine", 1130 new RendererException("Failed inside ExtendDirectedLine", exc)); 1131 } 1132 return ptResult; 1133 } 1134 1135 /** 1136 * @deprecated Returns a point extended perpendicularly from a line at a 1137 * given direction same as original function except it accounts for vertical 1138 * lines and negative d values 1139 * 1140 * @param pt1 first line point 1141 * @param pt2 last line point 1142 * @param pt0 on line from which to extend 1143 * @param direction the direction to extend: above, below, left, right 1144 * @param d the length to extend in pixels 1145 * 1146 */ 1147 public static POINT2 ExtendDirectedLineText(POINT2 pt1, 1148 POINT2 pt2, 1149 POINT2 pt0, 1150 int direction, 1151 double d) { 1152 POINT2 ptResult = new POINT2(); 1153 try { 1154 ref<double[]> X = new ref(), Y = new ref(); 1155 ptResult = new POINT2(pt0); 1156 if (d < 0) { 1157 direction = reverseDirection(direction); 1158 d = Math.abs(d); 1159 } 1160 if (pt1.y == pt2.y)//horizontal segment 1161 { 1162 switch (direction) { 1163 case 0://left means above 1164 direction = extend_above; 1165 break; 1166 case 1://right means below 1167 direction = extend_below; 1168 break; 1169 default: 1170 break; 1171 } 1172 } 1173 if (pt1.x == pt2.x)//vertical segment 1174 { 1175 switch (direction) { 1176 case 2://above means left 1177 direction = extend_left; 1178 break; 1179 case 3://below means right 1180 direction = extend_right; 1181 break; 1182 default: 1183 break; 1184 } 1185 } 1186 switch (direction) { 1187 case 0: //extend left 1188 ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0); 1189 break; 1190 case 1: //extend right 1191 ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1); 1192 break; 1193 case 2: //extend above 1194 ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0); 1195 break; 1196 case 3: //extend below 1197 ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1); 1198 break; 1199 default: 1200 break; 1201 } 1202 ptResult.x = X.value[0]; 1203 ptResult.y = Y.value[0]; 1204 } catch (Exception exc) { 1205 //System.out.println(e.getMessage()); 1206 ErrorLogger.LogException(_className, "ExtendDirectedLine", 1207 new RendererException("Failed inside ExtendDirectedLine", exc)); 1208 } 1209 return ptResult; 1210 } 1211 1212 /** 1213 * Returns a point extended perpendicularly from a line at a given direction 1214 * 1215 * @param pt1 first line point 1216 * @param pt2 last line point 1217 * @param pt0 on line from which to extend 1218 * @param direction the direction to extend: above, below, left, right 1219 * @param d the length to extend in pixels 1220 * @param style the style to assign the return point 1221 * 1222 */ 1223 public static POINT2 ExtendDirectedLine(POINT2 pt1, 1224 POINT2 pt2, 1225 POINT2 pt0, 1226 int direction, 1227 double d, 1228 int style) { 1229 POINT2 ptResult = new POINT2(pt0); 1230 try { 1231 ref<double[]> X = new ref(), Y = new ref(); 1232 //int bolResult=0; 1233 //handle parallel, perpendicular cases 1234 if (pt1.x == pt2.x) { 1235 if (direction == 2) { 1236 direction = 0; 1237 } 1238 if (direction == 3) { 1239 direction = 1; 1240 } 1241 } 1242 if (pt1.y == pt2.y) { 1243 if (direction == 0) { 1244 direction = 2; 1245 } 1246 if (direction == 1) { 1247 direction = 3; 1248 } 1249 } 1250 switch (direction) { 1251 case 0: //extend left 1252 ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0); 1253 break; 1254 case 1: //extend right 1255 ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1); 1256 break; 1257 case 2: //extend above 1258 ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0); 1259 break; 1260 case 3: //extend below 1261 ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1); 1262 break; 1263 } 1264 ptResult.x = X.value[0]; 1265 ptResult.y = Y.value[0]; 1266 ptResult.style = style; 1267 } catch (Exception exc) { 1268 ErrorLogger.LogException(_className, "ExtendDirectedLine", 1269 new RendererException("Failed inside ExtendDirectedLine", exc)); 1270 } 1271 return ptResult; 1272 } 1273 1274 /** 1275 * Calculates a point along a line 1276 * 1277 * @param pt1 first line point 1278 * @param pt2 last line point 1279 * @param dist extension distance in pixels from the beginning of the line 1280 * @param styl the line style to assign the point 1281 * 1282 * @return the extension point 1283 */ 1284 public static POINT2 ExtendLine2Double(POINT2 pt1, 1285 POINT2 pt2, 1286 double dist, 1287 int styl) { 1288 POINT2 pt3 = new POINT2(); 1289 try { 1290 double dOriginalDistance = CalcDistanceDouble(pt1, pt2); 1291 1292 pt3.x = pt2.x; 1293 pt3.y = pt2.y; 1294 if (dOriginalDistance > 0) { 1295 pt3.x = ((dOriginalDistance + dist) / dOriginalDistance * (pt2.x - pt1.x) + pt1.x); 1296 pt3.y = ((dOriginalDistance + dist) / dOriginalDistance * (pt2.y - pt1.y) + pt1.y); 1297 pt3.style = styl; 1298 } 1299 } catch (Exception exc) { 1300 ErrorLogger.LogException(_className, "ExtendLine2Double", 1301 new RendererException("Failed inside ExtendLine2Double", exc)); 1302 } 1303 return pt3; 1304 } 1305 1306 /** 1307 * Extends a point at an angle from a line. 1308 * 1309 * @param pt0 the first line point 1310 * @param pt1 the second line point 1311 * @param pt2 point on line from which to extend 1312 * @param alpha angle of extension in degrees 1313 * @param d the distance in pixels to extend 1314 * 1315 * @return the extension point 1316 */ 1317 public static POINT2 ExtendAngledLine(POINT2 pt0, 1318 POINT2 pt1, 1319 POINT2 pt2, 1320 double alpha, 1321 double d) { 1322 POINT2 pt = new POINT2(); 1323 try { 1324 //first get the angle psi between pt0 and pt1 1325 double psi = Math.atan((pt1.y - pt0.y) / (pt1.x - pt0.x)); 1326 //convert alpha to radians 1327 double alpha1 = Math.PI * alpha / 180; 1328 1329 //theta is the angle of extension from the x axis 1330 double theta = psi + alpha1; 1331 //dx is the x extension from pt2 1332 double dx = d * Math.cos(theta); 1333 //dy is the y extension form pt2 1334 double dy = d * Math.sin(theta); 1335 pt.x = pt2.x + dx; 1336 pt.y = pt2.y + dy; 1337 } catch (Exception exc) { 1338 ErrorLogger.LogException(_className, "ExtendAngledLine", 1339 new RendererException("Failed inside ExtendAngledLine", exc)); 1340 } 1341 return pt; 1342 } 1343 1344 /** 1345 * Returns an integer indicating the quadrant for the direction of the line 1346 * from pt1 to pt2 1347 * 1348 * @param pt1 first line point 1349 * @param pt2 second line point 1350 * 1351 * @return the quadrant 1352 */ 1353 public static int GetQuadrantDouble(POINT2 pt1, 1354 POINT2 pt2) { 1355 int nQuadrant = 1; 1356 try { 1357 if (pt2.x >= pt1.x && pt2.y <= pt1.y) { 1358 nQuadrant = 1; 1359 } 1360 if (pt2.x >= pt1.x && pt2.y >= pt1.y) { 1361 nQuadrant = 2; 1362 } 1363 if (pt2.x <= pt1.x && pt2.y >= pt1.y) { 1364 nQuadrant = 3; 1365 } 1366 if (pt2.x <= pt1.x && pt2.y <= pt1.y) { 1367 nQuadrant = 4; 1368 } 1369 1370 } catch (Exception exc) { 1371 ErrorLogger.LogException(_className, "GetQuadrantDouble", 1372 new RendererException("Failed inside GetQuadrantDouble", exc)); 1373 } 1374 return nQuadrant; 1375 } 1376 1377 public static int GetQuadrantDouble(double x1, double y1, 1378 double x2, double y2) { 1379 int nQuadrant = 1; 1380 try { 1381// if(pt2.x>=pt1.x && pt2.y<=pt1.y) 1382// nQuadrant=1; 1383// if(pt2.x>=pt1.x && pt2.y>=pt1.y) 1384// nQuadrant=2; 1385// if(pt2.x<=pt1.x && pt2.y>=pt1.y) 1386// nQuadrant=3; 1387// if(pt2.x<=pt1.x && pt2.y<=pt1.y) 1388// nQuadrant=4; 1389 1390 if (x2 >= x1 && y2 <= y1) { 1391 nQuadrant = 1; 1392 } 1393 if (x2 >= x1 && y2 >= y1) { 1394 nQuadrant = 2; 1395 } 1396 if (x2 <= x1 && y2 >= y1) { 1397 nQuadrant = 3; 1398 } 1399 if (x2 <= x1 && y2 <= y1) { 1400 nQuadrant = 4; 1401 } 1402 } catch (Exception exc) { 1403 ErrorLogger.LogException(_className, "GetQuadrantDouble", 1404 new RendererException("Failed inside GetQuadrantDouble", exc)); 1405 } 1406 return nQuadrant; 1407 } 1408 1409 1410 /** 1411 * 1412 * @param start beginning of arc 1413 * @param end end of arc 1414 * @param center center point of circle 1415 * @param numSegments how many lines to use to make the curve 1416 * @return ArrayList<POINT2> of points that make the arc 1417 */ 1418 public static ArrayList<POINT2> GetArcPointsDouble(POINT2 start, POINT2 end, POINT2 center, int numSegments) { 1419 ArrayList<POINT2> points = new ArrayList<>(); 1420 1421 // 1. Calculate vectors from center to start/end points 1422 double dxStart = start.x - center.x; 1423 double dyStart = start.y - center.y; 1424 double dxEnd = end.x - center.x; 1425 double dyEnd = end.y - center.y; 1426 1427 // 2. Determine radius and initial/final angles 1428 double radius = Math.sqrt(dxStart * dxStart + dyStart * dyStart); 1429 double angleStart = Math.atan2(dyStart, dxStart); 1430 double angleEnd = Math.atan2(dyEnd, dxEnd); 1431 1432 // 3. Calculate the shortest sweep angle 1433 double sweep = angleEnd - angleStart; 1434 while (sweep > Math.PI) sweep -= 2 * Math.PI; 1435 while (sweep < -Math.PI) sweep += 2 * Math.PI; 1436 1437 // 4. Generate points for each segment 1438 points.add(start); // Start with the actual start point 1439 for (int i = 1; i <= numSegments; i++) { 1440 double currentAngle = angleStart + (sweep * i / numSegments); 1441 double x = center.x + radius * Math.cos(currentAngle); 1442 double y = center.y + radius * Math.sin(currentAngle); 1443 points.add(new POINT2(x, y)); 1444 } 1445 1446 return points; 1447 } 1448 1449 /** 1450 * Returns the smallest x and y pixel values from an array of points 1451 * 1452 * @param ptsSeize array of points from which to find minimum vaules 1453 * @param vblCounter the number of points to test in the array 1454 * @param x OUT - an object with a member to hold the xminimum 1455 * @param y OUT - an object with a member to hold the y minimum value 1456 * 1457 */ 1458 public static void GetPixelsMin(POINT2[] ptsSeize, 1459 int vblCounter, 1460 ref<double[]> x, 1461 ref<double[]> y) { 1462 try { 1463 double xmin = Double.POSITIVE_INFINITY; 1464 double ymin = Double.POSITIVE_INFINITY; 1465 int j = 0; 1466 1467 for (j = 0; j < vblCounter; j++) { 1468 if (ptsSeize[j].x < xmin) { 1469 xmin = ptsSeize[j].x; 1470 } 1471 if (ptsSeize[j].y < ymin) { 1472 ymin = ptsSeize[j].y; 1473 } 1474 } 1475 x.value = new double[1]; 1476 y.value = new double[1]; 1477 x.value[0] = xmin; 1478 y.value[0] = ymin; 1479 } catch (Exception exc) { 1480 ErrorLogger.LogException(_className, "GetPixelsMin", 1481 new RendererException("Failed inside GetPixelsMin", exc)); 1482 } 1483 } 1484 1485 /** 1486 * Returns the largest x and y pixel values from an array of points 1487 * 1488 * @param ptsSeize array of points from which to find maximum values 1489 * @param vblCounter the number of points to test in the array 1490 * @param x OUT - an object with a member to hold the x maximum value 1491 * @param y OUT - an object with a member to hold the y maximum value 1492 * 1493 */ 1494 public static void GetPixelsMax(POINT2[] ptsSeize, 1495 int vblCounter, 1496 ref<double[]> x, 1497 ref<double[]> y) { 1498 try { 1499 double xmax = Double.NEGATIVE_INFINITY; 1500 double ymax = Double.NEGATIVE_INFINITY; 1501 int j = 0; 1502 1503 for (j = 0; j < vblCounter; j++) { 1504 if (ptsSeize[j].x > xmax) { 1505 xmax = ptsSeize[j].x; 1506 } 1507 if (ptsSeize[j].y > ymax) { 1508 ymax = ptsSeize[j].y; 1509 } 1510 } 1511 x.value = new double[1]; 1512 y.value = new double[1]; 1513 x.value[0] = xmax; 1514 y.value[0] = ymax; 1515 } catch (Exception exc) { 1516 ErrorLogger.LogException(_className, "GetPixelsMax", 1517 new RendererException("Failed inside GetPixelsMax", exc)); 1518 } 1519 } 1520 1521 /** 1522 * Returns center point for a clockwise arc to connect pts 1 and 2. Also 1523 * returns an extended point on the line between pt1 and the new center 1524 * Caller passes a POINT1 array of size 2 for ptsSeize, passes pt1 and pt2 1525 * in ptsSeize Returns the radius of the 90 degree arc between C (arc 1526 * center) and pt1 1527 * 1528 * @param ptsSeize OUT - two point array also used for the returned two 1529 * points 1530 * 1531 * @return the radius 1532 */ 1533 protected static double CalcClockwiseCenterDouble(POINT2[] ptsSeize) { 1534 double dRadius = 0; 1535 try { 1536 //declarations 1537 POINT2 pt1 = new POINT2(ptsSeize[0]); 1538 POINT2 pt2 = new POINT2(ptsSeize[1]); 1539 POINT2 C = new POINT2(pt1), midPt = new POINT2(pt1); //the center to calculate 1540 POINT2 E = new POINT2(pt1); //the extended point to calculate 1541 POINT2 ptYIntercept = new POINT2(pt1); 1542 int nQuadrant = 1; 1543 double b = 0, b1 = 0, b2 = 0, dLength = 0; 1544 ref<double[]> m = new ref(); 1545 int bolVertical = 0; 1546 ref<double[]> offsetX = new ref(), offsetY = new ref(); 1547 POINT2[] ptsTemp = new POINT2[2]; 1548 //end declarations 1549 1550 //must offset the points if necessary because there will be calculations 1551 //extending from the Y Intercept 1552 ptsTemp[0] = new POINT2(pt1); 1553 ptsTemp[1] = new POINT2(pt2); 1554 GetPixelsMin(ptsTemp, 2, offsetX, offsetY); 1555 if (offsetX.value[0] < 0) { 1556 offsetX.value[0] = offsetX.value[0] - 100; 1557 } else { 1558 offsetX.value[0] = 0; 1559 } 1560 //end section 1561 1562 midPt.x = (pt1.x + pt2.x) / 2; 1563 midPt.y = (pt1.y + pt2.y) / 2; 1564 dLength = CalcDistanceDouble(pt1, pt2); 1565 dRadius = dLength / Math.sqrt(2); 1566 nQuadrant = GetQuadrantDouble(pt1, pt2); 1567 1568 bolVertical = CalcTrueSlopeDouble(pt1, pt2, m); 1569 if (bolVertical != 0 && m.value[0] != 0) //line not vertical or horizontal 1570 { 1571 b = pt1.y - m.value[0] * pt1.x; 1572 //y intercept of line perpendicular to midPt of pt,p2 1573 b1 = midPt.y + (1 / m.value[0]) * midPt.x; 1574 //we want to shift the Y axis to the left by offsetX 1575 //so we get the new Y intercept at x=offsetX 1576 b2 = (-1 / m.value[0]) * offsetX.value[0] + b1; 1577 ptYIntercept.x = offsetX.value[0]; 1578 ptYIntercept.y = b2; 1579 switch (nQuadrant) { 1580 case 1: 1581 case 4: 1582 C = ExtendLineDouble(ptYIntercept, midPt, dLength / 2); 1583 break; 1584 case 2: 1585 case 3: 1586 C = ExtendLineDouble(ptYIntercept, midPt, -dLength / 2); 1587 break; 1588 default: 1589 break; 1590 } 1591 } 1592 if (bolVertical != 0 && m.value[0] == 0) //horizontal line 1593 { 1594 C.x = midPt.x; 1595 if (pt1.x < pt2.x) { 1596 C.y = midPt.y + dLength / 2; 1597 } else { 1598 C.y = midPt.y - dLength / 2; 1599 } 1600 } 1601 if (bolVertical == 0) //vertical line 1602 { 1603 ptYIntercept.x = offsetX.value[0]; 1604 ptYIntercept.y = midPt.y; 1605 switch (nQuadrant) { 1606 case 1: 1607 case 4: 1608 C = ExtendLineDouble(ptYIntercept, midPt, dLength / 2); 1609 break; 1610 case 2: 1611 case 3: 1612 C = ExtendLineDouble(ptYIntercept, midPt, -dLength / 2); 1613 break; 1614 default: 1615 break; 1616 } 1617 } 1618 1619 E = ExtendLineDouble(C, pt1, 50); 1620 ptsSeize[0] = new POINT2(C); 1621 ptsSeize[1] = new POINT2(E); 1622 1623 ptsTemp = null; 1624 } catch (Exception exc) { 1625 ErrorLogger.LogException(_className, "CalcClockwiseCenterDouble", 1626 new RendererException("Failed inside CalcClockwiseCenterDouble", exc)); 1627 } 1628 return dRadius; 1629 } 1630 1631 /** 1632 * Computes the points for an arrowhead based on a line segment 1633 * 1634 * @param startLinePoint segment start point 1635 * @param endLinePoint segment end point 1636 * @param nBiSector bisecotr in pixels 1637 * @param nBase base size in pixels 1638 * @param pResultLinePoints OUT - the arrowhead points 1639 * @param styl the line style to assign the last aroowhead point 1640 */ 1641 protected static void GetArrowHead4Double(POINT2 startLinePoint, 1642 POINT2 endLinePoint, 1643 int nBiSector, 1644 int nBase, 1645 POINT2[] pResultLinePoints, 1646 int styl) { 1647 try { 1648 //declarations 1649 int j = 0; 1650 double dy = (double) (endLinePoint.y - startLinePoint.y), 1651 dx = (double) (endLinePoint.x - startLinePoint.x), 1652 dSign = 1.0, 1653 AHBY = 0, 1654 AHBX = 0, 1655 AHBLY = 0, 1656 AHBLX = 0, 1657 AHBRY = 0, 1658 AHBRX = 0, 1659 dAngle = 0, 1660 dHypotenuse = 0; 1661 1662 POINT2 tempLinePoint = new POINT2(startLinePoint); 1663 //end declarations 1664 1665 if (dy == 0) { 1666 if (dx > 0) { 1667 dAngle = Math.PI; 1668 } else { 1669 dAngle = 0; 1670 } 1671 } else { 1672 dAngle = Math.atan(dx / dy) + Math.PI / 2; 1673 } 1674 1675 tempLinePoint.style = 0;//PS_SOLID; 1676 1677 if (dx <= 0.0 && dy <= 0.0) { 1678 dSign = -1.0; 1679 } 1680 if (dx >= 0.0 && dy <= 0.0) { 1681 dSign = -1.0; 1682 } 1683 if (dx <= 0.0 && dy >= 0.0) { 1684 dSign = 1.0; 1685 } 1686 if (dx >= 0.0 && dy >= 0.0) { 1687 dSign = 1.0; 1688 } 1689 1690 dHypotenuse = dSign * (double) nBiSector; 1691 1692 //Find x, y for Arrow Head nBase startLinePoint POINT1 1693 AHBX = (double) endLinePoint.x + dHypotenuse * Math.cos(dAngle); 1694 AHBY = (double) endLinePoint.y - dHypotenuse * Math.sin(dAngle); 1695 1696 //Half of the arrow head's length will be 10 units 1697 dHypotenuse = dSign * (double) (nBase / 2.0); 1698 1699 //Find x, y of Arrow Head nBase Left side end POINT1 1700 AHBLX = AHBX - dHypotenuse * Math.sin(dAngle); 1701 AHBLY = AHBY - dHypotenuse * Math.cos(dAngle); 1702 1703 //Find x, y of Arrow Head nBase Right side end POINT1 1704 AHBRX = AHBX + dHypotenuse * Math.sin(dAngle); 1705 AHBRY = AHBY + dHypotenuse * Math.cos(dAngle); 1706 1707 //replacement, just trying to return the POINT1s 1708 tempLinePoint.x = (int) AHBLX; 1709 tempLinePoint.y = (int) AHBLY; 1710 pResultLinePoints[0] = new POINT2(tempLinePoint); 1711 pResultLinePoints[1] = new POINT2(endLinePoint); 1712 tempLinePoint.x = (int) AHBRX; 1713 tempLinePoint.y = (int) AHBRY; 1714 pResultLinePoints[2] = new POINT2(tempLinePoint); 1715 switch (styl) { 1716 case 0: 1717 for (j = 0; j < 2; j++) { 1718 pResultLinePoints[j].style = 0; 1719 } 1720 pResultLinePoints[2].style = 5; 1721 break; 1722 case 9: 1723 for (j = 0; j < 2; j++) { 1724 pResultLinePoints[j].style = 9; 1725 } 1726 pResultLinePoints[2].style = 10; 1727 break; 1728 case 18: 1729 for (j = 0; j < 2; j++) { 1730 pResultLinePoints[j].style = 18; 1731 } 1732 pResultLinePoints[2].style = 5; 1733 break; 1734 default: 1735 for (j = 0; j < 2; j++) { 1736 pResultLinePoints[j].style = styl; 1737 } 1738 pResultLinePoints[2].style = 5; 1739 break; 1740 } 1741 } catch (Exception exc) { 1742 ErrorLogger.LogException(_className, "GetArrowhead4Double", 1743 new RendererException("Failed inside GetArrowhead4Double", exc)); 1744 } 1745 } 1746 1747 /** 1748 * Returns the midpoint between two points. 1749 * 1750 * @param pt0 the first point 1751 * @param pt1 the second point 1752 * @param styl the style to assign the mid point 1753 * 1754 * @return the mid point 1755 */ 1756 public static POINT2 MidPointDouble(POINT2 pt0, 1757 POINT2 pt1, 1758 int styl) { 1759 POINT2 ptResult = new POINT2(pt0); 1760 try { 1761 ptResult.x = (pt0.x + pt1.x) / 2; 1762 ptResult.y = (pt0.y + pt1.y) / 2; 1763 ptResult.style = styl; 1764 } catch (Exception exc) { 1765 ErrorLogger.LogException(_className, "MidPointDouble", 1766 new RendererException("Failed inside MidPointDouble", exc)); 1767 } 1768 return ptResult; 1769 } 1770 1771 /** 1772 * Rotates an the first vblCounter points in the array about its first point 1773 * 1774 * @param pLinePoints OUT - the points to rotate 1775 * @param vblCounter the number of points to rotate 1776 * @param lAngle the angle in degrees to rotate 1777 * 1778 * @return pLinePoints 1779 */ 1780 protected static POINT2[] RotateGeometryDoubleOrigin(POINT2[] pLinePoints, 1781 int vblCounter, 1782 int lAngle) { 1783 try { 1784 //declarations 1785 int j = 0; 1786 double dRotate = 0, 1787 dTheta = 0, 1788 dGamma = 0, 1789 x = 0, 1790 y = 0; 1791 //end declarations 1792 1793 if (lAngle != 0) { 1794 POINT2 pdCenter = new POINT2(); 1795 dRotate = (double) lAngle * Math.PI / 180d; 1796 //pdCenter = CalcCenterPointDouble(pLinePoints,vblCounter); 1797 pdCenter = new POINT2(pLinePoints[0]); 1798 1799 for (j = 0; j < vblCounter; j++) { 1800 dGamma = Math.PI + Math.atan((pLinePoints[j].y - pdCenter.y) 1801 / (pLinePoints[j].x - pdCenter.x)); 1802 1803 if (pLinePoints[j].x >= pdCenter.x) { 1804 dGamma = dGamma + Math.PI; 1805 } 1806 1807 dTheta = dRotate + dGamma; 1808 y = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.sin(dTheta); 1809 x = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.cos(dTheta); 1810 pLinePoints[j].y = pdCenter.y + y; 1811 pLinePoints[j].x = pdCenter.x + x; 1812 } //end for 1813 1814 return pLinePoints; 1815 } //end if 1816 } catch (Exception exc) { 1817 ErrorLogger.LogException(_className, "RotateGeometryDoubleOrigin", 1818 new RendererException("Failed inside RotateGeometryDoubleOrigin", exc)); 1819 } 1820 return pLinePoints; 1821 } // end function 1822 1823 /** 1824 * Returns a point a distance d pixels perpendicular to the pt0-pt1 line and 1825 * going toward pt2 1826 * 1827 * @param pt0 the first line point 1828 * @param pt1 the second line point 1829 * @param pt2 the relative line point 1830 * @param d the distance in pixels 1831 * @param styl the linestyle to assign the computed point 1832 * 1833 * @return the extended point 1834 */ 1835 public static POINT2 ExtendTrueLinePerpDouble(POINT2 pt0, 1836 POINT2 pt1, 1837 POINT2 pt2, 1838 double d, 1839 int styl) { 1840 POINT2 ptResult = new POINT2(pt0); 1841 try { 1842 POINT2 ptYIntercept = new POINT2(pt0); 1843 ref<double[]> m = new ref(); 1844 double b = 0, b1 = 0; //b is the normal Y intercept (at 0) 1845 int nTemp = 0; //b1 is the y intercept at offsetX 1846 1847 //must obtain x minimum to get the y-intercept to the left of 1848 //the left-most point 1849 ref<double[]> offsetX = new ref(), offsetY = new ref(); 1850 POINT2[] pts = new POINT2[3]; 1851 pts[0] = new POINT2(pt0); 1852 pts[1] = new POINT2(pt1); 1853 pts[2] = new POINT2(pt2); 1854 GetPixelsMin(pts, 3, offsetX, offsetY); 1855 1856 if (offsetX.value[0] <= 0) //was < 0 1857 { 1858 offsetX.value[0] = offsetX.value[0] - 100; 1859 } else { 1860 offsetX.value[0] = 0; 1861 } 1862 //end section 1863 1864 nTemp = CalcTrueSlopeDouble(pt0, pt1, m); 1865 switch (nTemp) { 1866 case 0: //vertical line 1867 if (pt0.y < pt1.y) { 1868 ptResult.x = pt2.x - d; 1869 ptResult.y = pt2.y; 1870 } else { 1871 ptResult.x = pt2.x + d; 1872 ptResult.y = pt2.y; 1873 } 1874 break; 1875 default: //non-vertical line 1876 if (m.value[0] == 0) { 1877 ptResult.x = pt2.x; 1878 ptResult.y = pt2.y + d; 1879 } else { 1880 b = (double) pt2.y + (1 / m.value[0]) * (double) pt2.x; 1881 //we need the y-intercept at the -offset 1882 b1 = (-1 / m.value[0]) * offsetX.value[0] + b; 1883 ptYIntercept.x = offsetX.value[0]; 1884 ptYIntercept.y = b1; 1885 ptResult = ExtendLineDouble(ptYIntercept, pt2, d); 1886 } 1887 break; 1888 } 1889 ptResult.style = styl; 1890 pts = null; 1891 } catch (Exception exc) { 1892 ErrorLogger.LogException(_className, "ExtendTrueLinePerpDouble", 1893 new RendererException("Failed inside ExtendTrueLinePerpDouble", exc)); 1894 } 1895 return ptResult; 1896 } 1897 1898 /** 1899 * Calculates the intersection of 2 lines pelative to a point. if one of the 1900 * lines is vertical use a distance dWidth above or below the line. pass 1901 * bolVertical1 = 1, or bolVertical2 = 1 if either line segment is vertical, 1902 * else pass 0. return the unique intersection in X,Y pointers. p2 is the 1903 * point that connects the 2 line segments to which the intersecting lines 1904 * are related, i.e. the intersecting lines are a distance dWidth pixels 1905 * above or below p2. uses dWidth and lOrient for cases in which at least 1906 * one of the lines is vertical. for normal lines this function assumes the 1907 * caller has passed the m, b for the appropriate upper or lower lines to 1908 * get the desired intgercept. this function is used for calculating the 1909 * upper and lower channel lines for channel types. For lOrient: see 1910 * comments in Channels.ConnectTrueDouble2 1911 * 1912 * @param m1 slope of the first line 1913 * @param b1 intercept of the first line 1914 * @param m2 slope of the second line 1915 * @param b2 y intercept of the second line 1916 * @param p2 point that connects the 2 line segments to which the 1917 * intersecting lines are related 1918 * @param bolVerticalSlope1 1 if first segment is vertical, else 0 1919 * @param bolVerticalSlope2 1 if second line segment is vertical, else 0 1920 * @param dWidth the distance of the intersecting lines from p2 in pixels 1921 * @param lOrient the orientation of the intersecting lines relative to the 1922 * segments connecting p2 1923 * @param X OUT - object holds the x value of the intersection point 1924 * @param Y OUT - object holds the y value of the intersection point 1925 */ 1926 protected static int CalcTrueIntersectDouble(double m1, 1927 double b1, 1928 double m2, 1929 double b2, 1930 POINT2 p2, //can use for vertical lines 1931 int bolVerticalSlope1, 1932 int bolVerticalSlope2, 1933 double dWidth, //use for vertical lines, use + for upper line, - for lower line 1934 int lOrient, 1935 ref<double[]> X, //intersection x value 1936 ref<double[]> Y) //intersection y value 1937 { 1938 1939 try { 1940 //case both lines are vertical 1941 double dWidth2 = Math.abs(dWidth); 1942 double b = 0; 1943 double dx = 0, dy = 0, m = 0; 1944 X.value = new double[1]; 1945 Y.value = new double[1]; 1946 1947 //cannot get out of having to do this 1948 //the problem is caused by inexact slopes which are created by 1949 //clsLineUtility.DisplayIntersectPixels. This occurs when setting 1950 //pt2 or pt3 with X or Y on the boundary +/-maxPixels 1951 //if you try to walk out until you get exactly the same slope 1952 //it can be thousands of pixels, so you have to accept an arbitrary 1953 //and, unfortuantely, inexact slope 1954 if (m1 != m2 && Math.abs(m1 - m2) <= Double.MIN_VALUE) { 1955 m1 = m2; 1956 } 1957 if (b1 != b2 && Math.abs(b1 - b2) <= Double.MIN_VALUE) { 1958 b1 = b2; 1959 } 1960 1961 //M. Deutch 10-24-11 1962 if (b1 == b2 && m1 + b1 == m2 + b2) { 1963 m1 = m2; 1964 } 1965 1966 if (bolVerticalSlope1 == 0 && bolVerticalSlope2 == 0) //both lines vertical 1967 { 1968 switch (lOrient) { 1969 case 0: 1970 X.value[0] = p2.x - dWidth2; 1971 Y.value[0] = p2.y; 1972 break; 1973 case 3: 1974 X.value[0] = p2.x + dWidth2; 1975 Y.value[0] = p2.y; 1976 break; 1977 default: //can never occur 1978 X.value[0] = p2.x; 1979 Y.value[0] = p2.y; 1980 break; 1981 } 1982 return 1; 1983 } 1984 if (bolVerticalSlope1 == 0 && bolVerticalSlope2 != 0) //line1 vertical, line2 is not 1985 { //there is a unique intersection 1986 switch (lOrient) { 1987 case 0: //Line1 above segment1 1988 case 1: 1989 X.value[0] = p2.x - dWidth2; 1990 Y.value[0] = m2 * X.value[0] + b2; 1991 break; 1992 case 2: //Line1 below segment1 1993 case 3: 1994 X.value[0] = p2.x + dWidth2; 1995 Y.value[0] = m2 * X.value[0] + b2; 1996 break; 1997 default: //can not occur 1998 X.value[0] = p2.x; 1999 Y.value[0] = p2.y; 2000 break; 2001 } 2002 return 1; 2003 } 2004 if (bolVerticalSlope2 == 0 && bolVerticalSlope1 != 0) //line2 vertical, line1 is not 2005 { //there is a unique intersection 2006 switch (lOrient) { 2007 case 0: //Line1 above segment2 2008 case 2: 2009 X.value[0] = p2.x - dWidth2; 2010 Y.value[0] = m1 * (X.value[0]) + b1; 2011 break; 2012 case 1: //Line1 below segment2 2013 case 3: 2014 X.value[0] = p2.x + dWidth2; 2015 Y.value[0] = m1 * (X.value[0]) + b1; 2016 break; 2017 default: //can not occur 2018 X.value[0] = p2.x; 2019 Y.value[0] = p2.y; 2020 break; 2021 } 2022 return 1; 2023 }//end if 2024 2025 //must deal with this case separately because normal lines use m1-m2 as a denominator 2026 //but we've handled all the vertical cases above so can assume it's not vertical 2027 //if the b's are different then one is an upper line, the other is a lower, no intersection 2028 //m and b will be used to build the perpendicular line thru p2 which we will use to 2029 //build the intersection, so must assume slopes are not 0, handle separately 2030 if (m1 == m2 && m1 != 0) { 2031 if (b1 == b2) //then the intercept is the point joining the 2 segments 2032 { 2033 //build the perpendicular line 2034 m = -1 / m1; 2035 b = p2.y - m * p2.x; 2036 X.value[0] = (b2 - b) / (m - m2); //intersect the lines (cannot blow up, m = m2 not possible) 2037 Y.value[0] = (m1 * (X.value[0]) + b1); 2038 return 1; 2039 } else //can not occur 2040 { 2041 X.value[0] = p2.x; 2042 Y.value[0] = p2.y; 2043 return 1; 2044 } 2045 } 2046 //slope is zero 2047 if (m1 == m2 && m1 == 0) { 2048 switch (lOrient) { 2049 case 0: //Line1 above the line 2050 case 1: //should never happen 2051 X.value[0] = p2.x; 2052 Y.value[0] = p2.y - dWidth2; 2053 break; 2054 case 3: //Line1 below the line 2055 case 2: //should never happen 2056 X.value[0] = p2.x; 2057 Y.value[0] = p2.y + dWidth2; 2058 break; 2059 default: //can not occur 2060 X.value[0] = p2.x; 2061 Y.value[0] = p2.y; 2062 break; 2063 } 2064 return 1; 2065 } 2066 2067 if (m1 == m2 && b1 == b2 && bolVerticalSlope1 != 0 && bolVerticalSlope2 != 0) { 2068 switch (lOrient) { 2069 case 0: //Line1 is above the line 2070 if (m1 < 0) { 2071 dy = m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is negative 2072 dx = dy / m1; //dx is negative 2073 X.value[0] = p2.x + dx; 2074 Y.value[0] = p2.y + dy; 2075 } 2076 if (m1 > 0) //slope is positive 2077 { 2078 dy = -m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is negative 2079 dx = -dy / m1; //dx is positive 2080 X.value[0] = p2.x + dx; 2081 Y.value[0] = p2.y + dy; 2082 } 2083 break; 2084 case 3: //Line1 is below the line 2085 if (m1 <= 0) { 2086 dy = -m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is positive 2087 dx = dy / m1; //dx is positive 2088 X.value[0] = p2.x + dx; 2089 Y.value[0] = p2.y + dy; 2090 } else { 2091 dy = m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is positive 2092 dx = -dy / m1; //dx is negative 2093 X.value[0] = p2.x + dx; 2094 Y.value[0] = p2.y + dy; 2095 } 2096 break; 2097 default: 2098 X.value[0] = p2.x; 2099 Y.value[0] = p2.y; 2100 break; 2101 } 2102 return 1; 2103 }//end if 2104 2105 //a normal line. no vertical or identical slopes 2106 //if m1=m2 function will not reach this point 2107 X.value[0] = (b2 - b1) / (m1 - m2); //intersect the lines 2108 Y.value[0] = (m1 * (X.value[0]) + b1); 2109 return 1; 2110 }//end try 2111 catch (Exception exc) { 2112 X.value[0] = p2.x; 2113 Y.value[0] = p2.y; 2114 ErrorLogger.LogException(_className, "CalcTrueIntersectDouble", 2115 new RendererException("Failed inside ExtendTrueIntersectDouble", exc)); 2116 } 2117 return 1; 2118 } 2119 2120 /** 2121 * Returns the distance in pixels from x1,y1 to x2,y2 2122 * 2123 * @param x1 first point x location in pixels 2124 * @param y1 first point y location in pixels 2125 * @param x2 second point x location in pixels 2126 * @param y2 second point y location in pixels 2127 * 2128 * @return the distance 2129 */ 2130 protected static double CalcDistance2(long x1, 2131 long y1, 2132 long x2, 2133 long y2) { 2134 double dResult = 0; 2135 try { 2136 dResult = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); 2137 2138 //sanity check 2139 //return x or y distance if return value is 0 or infinity 2140 double xdist = Math.abs(x1 - x2); 2141 double ydist = Math.abs(y1 - y2); 2142 double max = xdist; 2143 if (ydist > xdist) { 2144 max = ydist; 2145 } 2146 if (dResult == 0 || Double.isInfinite(dResult)) { 2147 if (max > 0) { 2148 dResult = max; 2149 } 2150 } 2151 } catch (Exception exc) { 2152 ErrorLogger.LogException(_className, "CalcDistance2", 2153 new RendererException("Failed inside CalcDistance2", exc)); 2154 } 2155 return dResult; 2156 } 2157 /** 2158 * gets the middle line for Rev B air corridors AC, LLTR, MRR, UAV 2159 * Middle line is handled separately now because the line may have been segmented 2160 * @param pLinePoints 2161 * @return 2162 */ 2163 protected static POINT2[] GetSAAFRMiddleLine(POINT2[] pLinePoints) { 2164 POINT2[] pts = null; 2165 try { 2166 int j = 0, count = 0; 2167 for (j = 0; j < pLinePoints.length-1; j++) { 2168 if (pLinePoints[j].style > 0) { 2169 count++; 2170 } 2171 } 2172 pts = new POINT2[count*2]; 2173 count=0; 2174 double dMRR=0; 2175 POINT2 firstSegPt=null,lastSegPt=null,pt0=null,pt1=null; 2176 for (j = 0; j < pLinePoints.length; j++) { 2177 if(pLinePoints[j].style>=0 || j==pLinePoints.length-1) 2178 { 2179 if(lastSegPt != null) 2180 { 2181 firstSegPt=new POINT2(lastSegPt); 2182 lastSegPt=new POINT2(pLinePoints[j]); 2183 dMRR=firstSegPt.style; 2184 pt0 = ExtendLine2Double(lastSegPt, firstSegPt, -dMRR, 0); 2185 pt1 = ExtendLine2Double(firstSegPt, lastSegPt, -dMRR, 5); 2186 pts[count++]=pt0; 2187 pts[count++]=pt1; 2188 } 2189 else 2190 { 2191 lastSegPt=new POINT2(pLinePoints[j]); 2192 } 2193 } 2194 } 2195 } catch (Exception exc) { 2196 ErrorLogger.LogException(_className, "GetSAAFRMiddleLine", 2197 new RendererException("Failed inside GetSAAFRMiddleLine", exc)); 2198 } 2199 return pts; 2200 } 2201 /** 2202 * Computes the points for a SAAFR segment 2203 * 2204 * @param pLinePoints OUT - the client points also used for the returned 2205 * points 2206 * @param lineType the line type 2207 * @param dMRR the symbol width 2208 */ 2209 protected static void GetSAAFRSegment(POINT2[] pLinePoints, 2210 int lineType, 2211 double dMRR) { 2212 try { 2213 POINT2 pt0 = new POINT2(); 2214 POINT2 pt1 = new POINT2(); 2215 POINT2 pt2 = new POINT2(); 2216 POINT2 pt3 = new POINT2(); 2217 POINT2 pt4 = new POINT2(); 2218 POINT2 pt5 = new POINT2(); 2219 ref<double[]> m = new ref(); 2220 int bolVertical = CalcTrueSlopeDouble(pLinePoints[0], pLinePoints[1], m); 2221 //shortened line 2222 //pt1=ExtendLine2Double(pLinePoints[0],pLinePoints[1],-dMRR/2,5); 2223 //pt0=ExtendLine2Double(pLinePoints[1],pLinePoints[0],-dMRR/2,0); 2224 pt1 = ExtendLine2Double(pLinePoints[0], pLinePoints[1], -dMRR, 5); 2225 pt0 = ExtendLine2Double(pLinePoints[1], pLinePoints[0], -dMRR, 0); 2226 if (bolVertical != 0 && m.value[0] < 1) { 2227 //upper line 2228 pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 2, dMRR); 2229 pt2.style = 0; 2230 pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 2, dMRR); 2231 pt3.style = 5; 2232 //lower line 2233 pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 3, dMRR); 2234 pt4.style = 0; 2235 pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 3, dMRR); 2236 pt5.style = 5; 2237 } //if( (bolVertical!=0 && m>1) || bolVertical==0) 2238 else { 2239 //left line 2240 pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 0, dMRR); 2241 pt2.style = 0; 2242 pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 0, dMRR); 2243 pt3.style = 5; 2244 //right line 2245 pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 1, dMRR); 2246 pt4.style = 0; 2247 pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 1, dMRR); 2248 pt5.style = 5; 2249 } 2250 //load the line points 2251 pLinePoints[0] = new POINT2(pt0); 2252 pLinePoints[1] = new POINT2(pt1); 2253 pLinePoints[2] = new POINT2(pt2); 2254 pLinePoints[3] = new POINT2(pt3); 2255 pLinePoints[4] = new POINT2(pt4); 2256 pLinePoints[5] = new POINT2(pt5); 2257 pLinePoints[5].style = 5; 2258 pLinePoints[0].style = 5; 2259 } catch (Exception exc) { 2260 ErrorLogger.LogException(_className, "GetSAAFRSegment", 2261 new RendererException("Failed inside GetSAAFRSegment", exc)); 2262 } 2263 } 2264 /** 2265 * Called by arraysupport for SAAFR and AC fill shapes 2266 * @param pLinePoints 2267 * @param dMRR 2268 */ 2269 protected static void GetSAAFRFillSegment(POINT2[] pLinePoints, 2270 double dMRR) { 2271 try { 2272 POINT2 pt2 = new POINT2(); 2273 POINT2 pt3 = new POINT2(); 2274 POINT2 pt4 = new POINT2(); 2275 POINT2 pt5 = new POINT2(); 2276 ref<double[]> m = new ref(); 2277 int bolVertical = CalcTrueSlopeDouble(pLinePoints[0], pLinePoints[1], m); 2278 if (bolVertical != 0 && m.value[0] < 1) { 2279 //upper line 2280 pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 2, dMRR); 2281 pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 2, dMRR); 2282 //lower line 2283 pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 3, dMRR); 2284 pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 3, dMRR); 2285 } //if( (bolVertical!=0 && m>1) || bolVertical==0) 2286 else { 2287 //left line 2288 pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 0, dMRR); 2289 pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 0, dMRR); 2290 //right line 2291 pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 1, dMRR); 2292 pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 1, dMRR); 2293 } 2294 //load the line points 2295 pLinePoints[0] = new POINT2(pt2); 2296 pLinePoints[1] = new POINT2(pt3); 2297 pLinePoints[2] = new POINT2(pt5); 2298 pLinePoints[3] = new POINT2(pt4); 2299 } catch (Exception exc) { 2300 ErrorLogger.LogException(_className, "GetSAAFRFillSegment", 2301 new RendererException("Failed inside GetSAAFRFillSegment", exc)); 2302 } 2303 //return; 2304 } 2305 /** 2306 * Computes an arc. 2307 * 2308 * @param pResultLinePoints OUT - contains center and start point and holds 2309 * the result arc points 2310 * @param vblCounter the number of client points 2311 * @param dRadius the arc radius in pixels 2312 * @param linetype the linetype determines start andgle and end angle for 2313 * the arc 2314 * 2315 */ 2316 protected static POINT2[] ArcArrayDouble(POINT2[] pResultLinePoints, 2317 int vblCounter, 2318 double dRadius, 2319 int linetype, 2320 IPointConversion converter) { 2321 try { 2322 //declarations 2323 double startangle = 0, //start of pArcLinePoints 2324 endangle = 0, //end of the pArcLinePoints 2325 increment = 0, 2326 //m = 0, 2327 length = 0, //length of a to e 2328 M = 0; 2329 2330 int j, numarcpts = 0, bolVertical = 0; 2331 ref<double[]> m = new ref(); 2332 //C is the center of the pArcLinePoints derived from a and e 2333 POINT2 C = new POINT2(pResultLinePoints[0]), 2334 a = new POINT2(pResultLinePoints[1]), 2335 e = new POINT2(pResultLinePoints[0]); 2336 2337 POINT2[] pArcLinePoints = null; 2338 //end declarations 2339 2340 bolVertical = CalcTrueSlopeDouble(a, e, m); 2341 if (bolVertical != 0) { 2342 M = Math.atan(m.value[0]); 2343 } else { 2344 if (a.y < e.y) { 2345 M = -Math.PI / 2; 2346 } else { 2347 M = Math.PI / 2; 2348 } 2349 } 2350 if(converter != null) 2351 { 2352 Point2D pt02d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y); 2353 Point2D pt12d=new Point2D.Double(pResultLinePoints[1].x,pResultLinePoints[1].y); 2354 //boolean reverseM=false; 2355 pt02d=converter.PixelsToGeo(pt02d); 2356 pt12d=converter.PixelsToGeo(pt12d); 2357 //M=mdlGeodesic.GetAzimuth(pt02d,pt12d); 2358 M= mdlGeodesic.GetAzimuth(new POINT2(pt02d.getX(),pt02d.getY()),new POINT2(pt12d.getX(),pt12d.getY() ) ); 2359 M*=(Math.PI/180); 2360 if(M<0) 2361 M+=Math.PI; 2362 } 2363 length = CalcDistanceDouble(a, e); 2364 if(converter != null) 2365 { 2366 Point2D pt02d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y); 2367 Point2D pt12d=new Point2D.Double(pResultLinePoints[1].x,pResultLinePoints[1].y); 2368 pt02d=converter.PixelsToGeo(pt02d); 2369 pt12d=converter.PixelsToGeo(pt12d); 2370 //length=mdlGeodesic.geodesic_distance(pt02d,pt12d,null,null); 2371 length=mdlGeodesic.geodesic_distance(new POINT2(pt02d.getX(),pt02d.getY()),new POINT2(pt12d.getX(),pt12d.getY()),null,null); 2372 } 2373 switch (linetype) { 2374 case TacticalLines.CLUSTER: 2375 startangle = M - 90 * Math.PI / 180.0; 2376 endangle = startangle + 2 * 90 * Math.PI / 180.0; 2377 break; 2378 case TacticalLines.ISOLATE: 2379 case TacticalLines.CORDONKNOCK: 2380 case TacticalLines.CORDONSEARCH: 2381 case TacticalLines.DENY: 2382 case TacticalLines.AREA_DEFENSE: 2383 startangle = M; 2384 endangle = startangle + 330 * Math.PI / 180; 2385 break; 2386 case TacticalLines.TURN_REVD: 2387 case TacticalLines.TURN: 2388 startangle = M; 2389 endangle = startangle + 90 * Math.PI / 180; 2390 break; 2391 case TacticalLines.OCCUPY: 2392 case TacticalLines.RETAIN: 2393 case TacticalLines.SECURE: 2394 case TacticalLines.CONTROL: 2395 case TacticalLines.LOCATE: 2396 startangle = M; 2397 //if(CELineArrayGlobals.Change1==false) 2398 endangle = startangle + 338 * Math.PI / 180; 2399 //else 2400 // endangle=startangle+330*pi/180; 2401 break; 2402 default: 2403 startangle = 0; 2404 endangle = 2 * Math.PI; 2405 break; 2406 } 2407 2408 if (a.x < e.x) { 2409 switch (linetype) { 2410 case TacticalLines.ISOLATE: 2411 case TacticalLines.CORDONKNOCK: 2412 case TacticalLines.CORDONSEARCH: 2413 case TacticalLines.DENY: 2414 case TacticalLines.AREA_DEFENSE: 2415 startangle = M - Math.PI; 2416 endangle = startangle + 330 * Math.PI / 180; 2417 break; 2418 case TacticalLines.OCCUPY: 2419 case TacticalLines.RETAIN: 2420 case TacticalLines.SECURE: 2421 case TacticalLines.CONTROL: 2422 case TacticalLines.LOCATE: 2423 startangle = M - Math.PI; 2424 //if(CELineArrayGlobals.Change1==false) 2425 endangle = startangle + 338 * Math.PI / 180; 2426 //else 2427 // endangle=startangle+330*pi/180; 2428 break; 2429 case TacticalLines.TURN_REVD: 2430 case TacticalLines.TURN: 2431 startangle = M - Math.PI; 2432 endangle = startangle + 90 * Math.PI / 180; 2433 break; 2434 case TacticalLines.CLUSTER: 2435 startangle = M - Math.PI + 90 * Math.PI / 180.0; 2436 endangle = startangle - 2 * 90 * Math.PI / 180.0; 2437 break; 2438 default: 2439 break; 2440 } 2441 } 2442 2443 numarcpts = 26; 2444 pArcLinePoints = new POINT2[numarcpts]; 2445 InitializePOINT2Array(pArcLinePoints); 2446 increment = (endangle - startangle) / (numarcpts - 1); 2447 if(dRadius != 0 && length != 0) 2448 { 2449 C.x = (int) ((double) e.x - (dRadius / length) 2450 * ((double) a.x - (double) e.x)); 2451 C.y = (int) ((double) e.y - (dRadius / length) 2452 * ((double) a.y - (double) e.y)); 2453 } 2454 else 2455 { 2456 C.x=e.x; 2457 C.y=e.y; 2458 } 2459 if (converter != null) 2460 { 2461 Point2D C2d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y); 2462 C2d=converter.PixelsToGeo(C2d); 2463 double az=0; 2464 Point2D ptGeo2d=null; 2465 POINT2 ptGeo=null; 2466 POINT2 ptPixels=null; 2467 for (j = 0; j < numarcpts; j++) { 2468 az=startangle*180/Math.PI+j*increment*180/Math.PI; 2469 //ptGeo=mdlGeodesic.geodesic_coordinate(C2d,length,az); 2470 ptGeo=mdlGeodesic.geodesic_coordinate(new POINT2(C2d.getX(),C2d.getY()),length,az); 2471 ptGeo2d=new Point2D.Double(ptGeo.x,ptGeo.y); 2472 ptGeo2d=converter.GeoToPixels(ptGeo2d); 2473 ptPixels=new POINT2(ptGeo2d.getX(),ptGeo2d.getY()); 2474 pArcLinePoints[j].x = ptPixels.x; 2475 pArcLinePoints[j].y = ptPixels.y; 2476 } 2477 } 2478 else 2479 { 2480 for (j = 0; j < numarcpts; j++) { 2481 //pArcLinePoints[j]=pResultLinePoints[0]; //initialize 2482 pArcLinePoints[j].x = (int) (dRadius * Math.cos(startangle + j * increment)); 2483 pArcLinePoints[j].y = (int) (dRadius * Math.sin(startangle + j * increment)); 2484 } 2485 2486 for (j = 0; j < numarcpts; j++) { 2487 pArcLinePoints[j].x += C.x; 2488 pArcLinePoints[j].y += C.y; 2489 } 2490 } 2491 for (j = 0; j < numarcpts; j++) { 2492 pResultLinePoints[j] = new POINT2(pArcLinePoints[j]); 2493 } 2494 pArcLinePoints = null; 2495 } catch (Exception exc) { 2496 ErrorLogger.LogException(_className, "ArcArrayDouble", 2497 new RendererException("Failed inside ArcArrayDouble", exc)); 2498 } 2499 return pResultLinePoints; 2500 } 2501 /** 2502 * Gets geodesic circle using the converter 2503 * @param Center in pixels 2504 * @param pt1 a point on the radius in pixels 2505 * @param numpts number of points to return 2506 * @param CirclePoints the result points 2507 * @param converter 2508 */ 2509 protected static void CalcCircleDouble2(POINT2 Center, 2510 POINT2 pt1, 2511 int numpts, 2512 POINT2[] CirclePoints, 2513 IPointConversion converter) { 2514 try { 2515 int j = 0; 2516 double increment = (Math.PI * 2) / (numpts - 1); 2517 Point2D ptCenter2d=new Point2D.Double(Center.x,Center.y); 2518 ptCenter2d=converter.PixelsToGeo(ptCenter2d); 2519 Point2D pt12d=new Point2D.Double(pt1.x,pt1.y); 2520 pt12d=converter.PixelsToGeo(pt12d); 2521 Center=new POINT2(ptCenter2d.getX(),ptCenter2d.getY()); 2522 pt1=new POINT2(pt12d.getX(),pt12d.getY()); 2523 double dist=mdlGeodesic.geodesic_distance(Center, pt1, null, null); 2524 2525 //double dSegmentAngle = 2 * Math.PI / numpts; 2526 double az=0; 2527 double startangle=0,endAngle=Math.PI*2; 2528 POINT2 ptGeo=null,ptPixels=null; 2529 Point2D ptGeo2d=null; 2530 for (j = 0; j < numpts - 1; j++) { 2531 az=startangle*180/Math.PI+j*increment*180/Math.PI; 2532 //ptGeo=mdlGeodesic.geodesic_coordinate(C2d,length,az); 2533 ptGeo=mdlGeodesic.geodesic_coordinate(Center,dist,az); 2534 ptGeo2d=new Point2D.Double(ptGeo.x,ptGeo.y); 2535 ptGeo2d=converter.GeoToPixels(ptGeo2d); 2536 ptPixels=new POINT2(ptGeo2d.getX(),ptGeo2d.getY()); 2537 CirclePoints[j].x = ptPixels.x; 2538 CirclePoints[j].y = ptPixels.y; 2539 } 2540 CirclePoints[numpts - 1] = new POINT2(CirclePoints[0]); 2541 2542 } catch (Exception exc) { 2543 ErrorLogger.LogException(_className, "CalcCircleDouble2", 2544 new RendererException("Failed inside CalcCircleDouble2", exc)); 2545 } 2546 return; 2547 } 2548 /** 2549 * Computes the points for a circle. Assumes CirclePoints has been allocated 2550 * with size numpts. 2551 * 2552 * @param Center the cicle center 2553 * @param radius the circle radius in pixels 2554 * @param numpts the number of circle points 2555 * @param CirclePoints - OUT - array of circle points 2556 * @param styl the style to set the last circle point 2557 */ 2558 protected static void CalcCircleDouble(POINT2 Center, 2559 double radius, 2560 int numpts, 2561 POINT2[] CirclePoints, 2562 int styl) { 2563 try { 2564 int j = 0; 2565 double dSegmentAngle = 2 * Math.PI / (numpts - 1); 2566 double x = 0, y = 0; 2567 for (j = 0; j < numpts - 1; j++) { 2568 x = Center.x + (radius * Math.cos((double) j * dSegmentAngle)); 2569 y = Center.y + (radius * Math.sin((double) j * dSegmentAngle)); 2570 CirclePoints[j] = new POINT2(x, y); 2571 CirclePoints[j].style = styl; 2572 } 2573 CirclePoints[numpts - 1] = new POINT2(CirclePoints[0]); 2574 2575 switch (styl) { 2576 case 0: 2577 CirclePoints[numpts - 1].style = 0; 2578 break; 2579 case 9: 2580 CirclePoints[numpts - 1].style = 10; 2581 break; 2582 case 11: 2583 CirclePoints[numpts - 1].style = 12; 2584 break; 2585 default: 2586 CirclePoints[numpts - 1].style = 5; 2587 break; 2588 } 2589 } catch (Exception exc) { 2590 ErrorLogger.LogException(_className, "CalcCircleDouble", 2591 new RendererException("Failed inside CalcCircleDouble", exc)); 2592 } 2593 } 2594 2595 protected static Shape2 CalcCircleShape(POINT2 Center, 2596 double radius, 2597 int numpts, 2598 POINT2[] CirclePoints, 2599 int styl) { 2600 Shape2 shape; 2601 if (styl == 9) { 2602 shape = new Shape2(Shape2.SHAPE_TYPE_FILL); 2603 } else { 2604 shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE); 2605 } 2606 2607 shape.set_Style(styl); 2608 try { 2609 int j = 0; 2610 CalcCircleDouble(Center, radius, numpts, CirclePoints, styl); 2611 shape.moveTo(CirclePoints[0]); 2612 for (j = 1; j < numpts; j++) { 2613 shape.lineTo(CirclePoints[j]); 2614 } 2615 } catch (Exception exc) { 2616 ErrorLogger.LogException(_className, "CalcCircleShape", 2617 new RendererException("Failed inside CalcCircleShape", exc)); 2618 } 2619 return shape; 2620 } 2621 2622 private static void GetSquallCurve(POINT2 StartPt, 2623 POINT2 EndPt, 2624 POINT2[] pSquallPts, 2625 int sign, 2626 double amplitude, 2627 int quantity) { 2628 try { 2629 double dist = CalcDistanceDouble(StartPt, EndPt); 2630 POINT2 ptTemp = new POINT2(); 2631 int j = 0; 2632 //end declarations 2633 2634 //get points along the horizontal segment between StartPt and EndPt2; 2635 for (j = 0; j < quantity; j++) { 2636 ptTemp = ExtendLineDouble(EndPt, StartPt, -dist * (double) j / (double) quantity); 2637 pSquallPts[j].x = ptTemp.x; 2638 //calculate the sin value along the x axis 2639 pSquallPts[j].y = ptTemp.y + amplitude * sign * Math.sin((double) j * 180 / (double) quantity * Math.PI / 180); 2640 } 2641 } catch (Exception exc) { 2642 ErrorLogger.LogException(_className, "GetSquallShape", 2643 new RendererException("Failed inside GeSquallShape", exc)); 2644 } 2645 } 2646 //caller needs to instantiate sign.value 2647 /** 2648 * Gets the squall curves for a line segment Assumes pSquallPts has been 2649 * allocated the proper number of points. 2650 * 2651 * @param StartPt segment start point 2652 * @param EndPt segment end point 2653 * @param pSquallPts OUT - the squall points 2654 * @param sign OUT - an object with a member to hold the starting curve sign 2655 * for the segment. 2656 * @param amplitude the sin curve amplitutde 2657 * @param quantity the number of points for each sin curve 2658 * @param length the desired length of the curve along the segment for each 2659 * sin curve 2660 * 2661 * @return segment squall points count 2662 */ 2663 protected static int GetSquallSegment(POINT2 StartPt, 2664 POINT2 EndPt, 2665 POINT2[] pSquallPts, 2666 ref<int[]> sign, 2667 double amplitude, 2668 int quantity, 2669 double length) { 2670 int counter = 0; 2671 try { 2672 POINT2 StartCurvePt, EndCurvePt; //use these for the curve points 2673 POINT2[] pSquallPts2 = new POINT2[quantity]; 2674 double dist = CalcDistanceDouble(StartPt, EndPt); 2675 int numCurves = (int) (dist / (double) length); 2676 int j = 0, k = 0; 2677 POINT2 EndPt2 = new POINT2(); 2678 double angle = Math.atan((StartPt.y - EndPt.y) / (StartPt.x - EndPt.x)); 2679 int lAngle = (int) ((180 / Math.PI) * angle); 2680 InitializePOINT2Array(pSquallPts2); 2681 //define EndPt2 to be the point dist from StartPt along the x axis 2682 if (StartPt.x < EndPt.x) { 2683 EndPt2.x = StartPt.x + dist; 2684 } else { 2685 EndPt2.x = StartPt.x - dist; 2686 } 2687 2688 EndPt2.y = StartPt.y; 2689 2690 EndCurvePt = StartPt; 2691 for (j = 0; j < numCurves; j++) { 2692 StartCurvePt = ExtendLineDouble(EndPt2, StartPt, -(double) (j * length)); 2693 EndCurvePt = ExtendLineDouble(EndPt2, StartPt, -(double) ((j + 1) * length)); 2694 2695 //get the curve points 2696 GetSquallCurve(StartCurvePt, EndCurvePt, pSquallPts2, sign.value[0], amplitude, quantity); 2697 2698 //fill the segment points with the curve points 2699 for (k = 0; k < quantity; k++) { 2700 //pSquallPts[counter].x=pSquallPts2[k].x; 2701 //pSquallPts[counter].y=pSquallPts2[k].y; 2702 pSquallPts[counter] = new POINT2(pSquallPts2[k]); 2703 counter++; 2704 } 2705 //reverse the sign 2706 2707 sign.value[0] = -sign.value[0]; 2708 } 2709 if (numCurves == 0) { 2710 pSquallPts[counter] = new POINT2(StartPt); 2711 counter++; 2712 pSquallPts[counter] = new POINT2(EndPt); 2713 counter++; 2714 } 2715 //the points are along the x axis. Rotate them about the first point as the origin 2716 RotateGeometryDoubleOrigin(pSquallPts, counter, lAngle); 2717 pSquallPts2 = null; 2718 } catch (Exception exc) { 2719 ErrorLogger.LogException(_className, "GetSquallSegment", 2720 new RendererException("Failed inside GetSquallSegment", exc)); 2721 } 2722 return counter; 2723 } 2724 2725 //temporarily using 2000 pixels 2726 private static int PointInBounds(POINT2 pt) { 2727 try { 2728 //double maxPixels=CELineArrayGlobals.MaxPixels2; 2729 double maxPixels = 100000;//was 2000 2730 if (Math.abs(pt.x) <= maxPixels && Math.abs(pt.y) <= maxPixels) { 2731 return 1; 2732 } else { 2733 return 0; 2734 } 2735 } catch (Exception exc) { 2736 ErrorLogger.LogException(_className, "PointInBounds", 2737 new RendererException("Failed inside PointInBounds", exc)); 2738 } 2739 return 1; 2740 } 2741 2742 /** 2743 * @param pt 2744 * @param ul 2745 * @param lr 2746 * @return 2747 */ 2748 private static int PointInBounds2(POINT2 pt, POINT2 ul, POINT2 lr) { 2749 try { 2750 double maxX = lr.x, minX = ul.x, maxY = lr.y, minY = ul.y; 2751 if (pt.x <= maxX && pt.x >= minX && pt.y <= maxY && pt.y >= minY) { 2752 return 1; 2753 } else { 2754 return 0; 2755 } 2756 } catch (Exception exc) { 2757 ErrorLogger.LogException(_className, "PointInBounds2", 2758 new RendererException("Failed inside PointInBounds2", exc)); 2759 } 2760 return 1; 2761 } 2762 2763 /** 2764 * Analyzes if line from pt0 to pt 1 intersects a side and returns the 2765 * intersection or null assumes pt0 to pt1 is not vertical. the caller will 2766 * replace pt0 with the intersection point if it is not null 2767 * 2768 * @param pt0 2769 * @param pt1 2770 * @param sidePt0 vertical or horizontal side first point 2771 * @param sidePt1 2772 * @return null if it does not intersect the side 2773 */ 2774 private static POINT2 intersectSegment(POINT2 pt0, POINT2 pt1, POINT2 sidePt0, POINT2 sidePt1) { 2775 POINT2 pt = null; 2776 try { 2777 if (pt0.x == pt1.x) { 2778 return null; 2779 } 2780 double m = (pt1.y - pt0.y) / (pt1.x - pt0.x); 2781 double dx = 0, dy = 0, x = 0, y = 0; 2782 POINT2 upper = null, lower = null, left = null, right = null; 2783 Boolean bolVertical = false; 2784 //the side is either vertical or horizontal 2785 if (sidePt0.x == sidePt1.x) //vertical side 2786 { 2787 bolVertical = true; 2788 if (sidePt0.y < sidePt1.y) { 2789 upper = sidePt0; 2790 lower = sidePt1; 2791 } else { 2792 upper = sidePt1; 2793 lower = sidePt0; 2794 } 2795 } else //horizontal side 2796 { 2797 if (sidePt0.x < sidePt1.x) { 2798 left = sidePt0; 2799 right = sidePt1; 2800 } else { 2801 left = sidePt1; 2802 right = sidePt0; 2803 } 2804 } 2805 //travel in the direction from pt0 to pt1 to find the pt0 intersect 2806 if (bolVertical) { //the side to intersect is vertical 2807 dx = upper.x - pt0.x; 2808 dy = m * dx; 2809 x = upper.x; 2810 y = pt0.y + dy; 2811 //the potential intersection point 2812 pt = new POINT2(x, y); 2813 2814 if (pt0.x <= pt.x && pt.x <= pt1.x) //left to right 2815 { 2816 if (upper.y <= pt.y && pt.y <= lower.y) { 2817 return pt; 2818 } 2819 } else if (pt0.x >= pt.x && pt.x >= pt1.x) //right to left 2820 { 2821 if (upper.y <= pt.y && pt.y <= lower.y) { 2822 return pt; 2823 } 2824 } 2825 } else //horizontal side 2826 { 2827 dy = left.y - pt0.y; 2828 dx = dy / m; 2829 x = pt0.x + dx; 2830 y = left.y; 2831 //the potential intersection point 2832 pt = new POINT2(x, y); 2833 2834 if (pt0.y <= pt.y && pt.y <= pt1.y) { 2835 if (left.x <= pt.x && pt.x <= right.x) { 2836 return pt; 2837 } 2838 } else if (pt0.y >= pt.y && pt.y >= pt1.y) { 2839 if (left.x <= pt.x && pt.x <= right.x) { 2840 return pt; 2841 } 2842 } 2843 } 2844 } catch (Exception exc) { 2845 ErrorLogger.LogException(_className, "intersectSegment", 2846 new RendererException("Failed inside intersectSegment", exc)); 2847 } 2848 return null; 2849 } 2850 2851 /** 2852 * side 1 ----- | | side 0 | | side 2 | | ------ side 3 bounds one segment 2853 * for autoshapes that need it: bydif, fordif, fix, mnfldfix if null is 2854 * returned the client should conect the original line points (i.e. no 2855 * jaggies) 2856 * 2857 * @param pt0 2858 * @param pt1 2859 * @param ul 2860 * @param lr 2861 * @return bounded segment or null 2862 */ 2863 public static POINT2[] BoundOneSegment(POINT2 pt0, POINT2 pt1, POINT2 ul, POINT2 lr) { 2864 POINT2[] line = new POINT2[2]; 2865 try { 2866 if (pt0.y < ul.y && pt1.y < ul.y) { 2867 return null; 2868 } 2869 if (pt0.y > lr.y && pt1.y > lr.y) { 2870 return null; 2871 } 2872 if (pt0.x < ul.x && pt1.x < ul.x) { 2873 return null; 2874 } 2875 if (pt0.x > lr.x && pt1.x > lr.x) { 2876 return null; 2877 } 2878 2879 Boolean bolVertical = false; 2880 InitializePOINT2Array(line); 2881 if (pt0.x == pt1.x) { 2882 bolVertical = true; 2883 } 2884 2885 if (bolVertical) { 2886 line[0] = new POINT2(pt0); 2887 if (line[0].y < ul.y) { 2888 line[0].y = ul.y; 2889 } 2890 if (line[0].y > lr.y) { 2891 line[0].y = lr.y; 2892 } 2893 2894 line[1] = new POINT2(pt1); 2895 if (line[1].y < ul.y) { 2896 line[1].y = ul.y; 2897 } 2898 if (line[1].y > lr.y) { 2899 line[1].y = lr.y; 2900 } 2901 2902 return line; 2903 } 2904 2905 double dx = 0, dy = 0, x = 0, y = 0; 2906 double m = (pt1.y - pt0.y) / (pt1.x - pt0.x); 2907 Boolean side0Intersect = false, 2908 side1Intersect = false, 2909 side2Intersect = false, 2910 side3Intersect = false; 2911 //travel in the direction from pt0 to pt1 to find pt0 intersect 2912 POINT2 ur = new POINT2(lr.x, ul.y); 2913 POINT2 ll = new POINT2(ul.x, lr.y); 2914 2915 POINT2 pt0Intersect = null; 2916 if (PointInBounds2(pt0, ul, lr) == 1) { 2917 pt0Intersect = pt0; 2918 } 2919 if (pt0Intersect == null) { 2920 pt0Intersect = intersectSegment(pt0, pt1, ll, ul); //interesect side 0 2921 side0Intersect = true; 2922 } 2923 if (pt0Intersect == null) { 2924 pt0Intersect = intersectSegment(pt0, pt1, ul, ur); //interesect side 1 2925 side1Intersect = true; 2926 } 2927 if (pt0Intersect == null) { 2928 pt0Intersect = intersectSegment(pt0, pt1, ur, lr); //interesect side 2 2929 side2Intersect = true; 2930 } 2931 if (pt0Intersect == null) { 2932 pt0Intersect = intersectSegment(pt0, pt1, ll, lr); //interesect side 3 2933 side3Intersect = true; 2934 } 2935 2936 //travel in the direction from pt1 to pt0 to find pt1 intersect 2937 POINT2 pt1Intersect = null; 2938 if (PointInBounds2(pt1, ul, lr) == 1) { 2939 pt1Intersect = pt1; 2940 } 2941 if (pt1Intersect == null && side0Intersect == false) { 2942 pt1Intersect = intersectSegment(pt1, pt0, ll, ul); //interesect side 0 2943 } 2944 if (pt1Intersect == null && side1Intersect == false) { 2945 pt1Intersect = intersectSegment(pt1, pt0, ul, ur); //interesect side 1 2946 } 2947 if (pt1Intersect == null && side2Intersect == false) { 2948 pt1Intersect = intersectSegment(pt1, pt0, ur, lr); //interesect side 2 2949 } 2950 if (pt1Intersect == null && side3Intersect == false) { 2951 pt1Intersect = intersectSegment(pt1, pt0, ll, lr); //interesect side 3 2952 } 2953 2954 if (pt0Intersect != null && pt1Intersect != null) { 2955 line[0] = pt0Intersect; 2956 line[1] = pt1Intersect; 2957 //return line; 2958 } else { 2959 line = null; 2960 } 2961 } catch (Exception exc) { 2962 ErrorLogger.LogException(_className, "BoundOneSegment", 2963 new RendererException("Failed inside BoundOneSegment", exc)); 2964 } 2965 return line; 2966 } 2967 2968 private static int DisplayIntersectPixels(POINT2 pt0, 2969 POINT2 pt1, 2970 ref<double[]> pt2x, 2971 ref<double[]> pt2y, 2972 ref<double[]> pt3x, 2973 ref<double[]> pt3y) //POINT2 ul, 2974 //POINT2 lr) 2975 { 2976 int nResult = -1; 2977 try { 2978 //declarations 2979 double X = 0, Y = 0; 2980 ref<double[]> m = new ref(); 2981 //double maxPixels=CELineArrayGlobals.MaxPixels2; 2982 double maxPixels = 2000; 2983 //double maxX=lr.x,minX=ul.x,maxY=lr.y,minY=ul.y; 2984 2985 int bol0Inside = 0, bol1Inside = 0; 2986 int bolVertical = CalcTrueSlopeDouble(pt0, pt1, m); 2987 double b = pt0.y - m.value[0] * pt0.x; //the y intercept for the segment line 2988 POINT2 pt2, pt3; 2989 //end declarations 2990 2991 pt2x.value = new double[1]; 2992 pt2y.value = new double[1]; 2993 pt3x.value = new double[1]; 2994 pt3y.value = new double[1]; 2995 pt2 = new POINT2(pt0); 2996 pt3 = new POINT2(pt1); 2997 2998 //diagnostic 2999 if (pt0.x <= maxPixels && pt0.x >= -maxPixels 3000 && pt0.y <= maxPixels && pt0.y >= -maxPixels) { 3001 bol0Inside = 1; 3002 } 3003 if (pt1.x <= maxPixels && pt1.x >= -maxPixels 3004 && pt1.y <= maxPixels && pt1.y >= -maxPixels) { 3005 bol1Inside = 1; 3006 } 3007 //if both points are inside the area then use the whole segment 3008 if (bol0Inside == 1 && bol1Inside == 1) { 3009 return 0; 3010 } 3011 //if at leat one of the points is inside the area then use some of the segment 3012 if (bol0Inside == 1 || bol1Inside == 1) { 3013 nResult = 1; 3014 } 3015 3016 //segment is not vertical 3017 if (bolVertical != 0) { 3018 //analysis for side 0, get the intersection for either point if it exists 3019 //diagnostic 3020 X = -maxPixels; 3021 //X=minX; 3022 3023 Y = m.value[0] * X + b; 3024 if (pt0.x < -maxPixels && -maxPixels < pt1.x) //pt0 is outside the area 3025 { 3026 if (-maxPixels <= Y && Y <= maxPixels) //intersection is on side 0 3027 //if(minY<=Y && Y<=maxY) //intersection is on side 0 3028 { 3029 pt2.x = X; 3030 pt2.y = Y; 3031 nResult = 1; //use at least some of the pixels 3032 } 3033 } 3034 if (pt1.x < -maxPixels && -maxPixels < pt0.x) //pt1 is outside the area 3035 //if(pt1.x<minX && minX<pt0.x) //pt1 is outside the area 3036 { 3037 if (-maxPixels <= Y && Y <= maxPixels) //intersection is on side 0 3038 { 3039 pt3.x = X; 3040 pt3.y = Y; 3041 nResult = 1; //use at least some of the pixels 3042 } 3043 } 3044 3045 //analysis for side 1, get the intersection for either point if it exists 3046 Y = -maxPixels; 3047 if (m.value[0] != 0) { 3048 X = (Y - b) / m.value[0]; 3049 if (pt0.y < -maxPixels && -maxPixels < pt1.y) //pt0 is outside the area 3050 { 3051 if (-maxPixels <= X && X <= maxPixels) //intersection is on side 1 3052 { 3053 pt2.x = X; 3054 pt2.y = Y; 3055 nResult = 1; //use at least some of the pixels 3056 } 3057 } 3058 if (pt1.y <= -maxPixels && -maxPixels <= pt0.y) //pt1 is outside the area 3059 { 3060 if (-maxPixels < X && X < maxPixels) //intersection is on the boundary 3061 { 3062 pt3.x = X; 3063 pt3.y = Y; 3064 nResult = 1; //use at least some of the pixels 3065 } 3066 } 3067 } 3068 //analysis for side 2, get the intersection for either point if it exists 3069 X = maxPixels; 3070 Y = m.value[0] * X + b; 3071 if (pt0.x < maxPixels && maxPixels < pt1.x) //pt1 is outside the area 3072 { 3073 if (-maxPixels <= Y && Y <= maxPixels) //intersection is on the boundary 3074 { 3075 pt3.x = X; 3076 pt3.y = Y; 3077 nResult = 1; //use at least some of the pixels 3078 } 3079 } 3080 if (pt1.x < maxPixels && maxPixels < pt0.x) //pt0 is outside the area 3081 { 3082 if (-maxPixels <= Y && Y <= maxPixels) //intersection is on the boundary 3083 { 3084 pt2.x = X; 3085 pt2.y = Y; 3086 nResult = 1; //use at least some of the pixels 3087 } 3088 } 3089 3090 //analysis for side 3, get the intersection for either point if it exists 3091 Y = maxPixels; 3092 if (m.value[0] != 0) { 3093 X = (Y - b) / m.value[0]; 3094 if (pt0.y < maxPixels && maxPixels < pt1.y) //pt1 is outside the area 3095 { 3096 if (-maxPixels <= X && X <= maxPixels) //intersection is on the boundary 3097 { 3098 pt3.x = X; 3099 pt3.y = Y; 3100 nResult = 1; //use at least some of the pixels 3101 } 3102 } 3103 if (pt1.y < maxPixels && maxPixels < pt0.y) //pt0 is outside the area 3104 { 3105 if (-maxPixels <= X && X <= maxPixels) //intersection is on the boundary 3106 { 3107 pt2.x = X; 3108 pt2.y = Y; 3109 nResult = 1; //use at least some of the pixels 3110 } 3111 } 3112 } 3113 } 3114 3115 //segment is vertical 3116 if (bolVertical == 0) { 3117 //analysis for side 1 3118 X = pt0.x; 3119 Y = -maxPixels; 3120 if (-maxPixels < pt0.x && pt0.x < maxPixels) { 3121 if (pt0.y <= -maxPixels && -maxPixels <= pt1.y) //pt0 outside the area 3122 { 3123 pt2.x = X; 3124 pt2.y = Y; 3125 nResult = 1; //use at least some of the pixels 3126 } 3127 if (pt1.y <= -maxPixels && -maxPixels <= pt0.y) //pt1 outside the area 3128 { 3129 pt3.x = X; 3130 pt3.y = Y; 3131 nResult = 1; //use at least some of the pixels 3132 } 3133 } 3134 3135 //analysis for side 3 3136 X = pt0.x; 3137 Y = maxPixels; 3138 if (-maxPixels < pt0.x && pt0.x < maxPixels) { 3139 if (pt0.y <= maxPixels && maxPixels <= pt1.y) //pt1 outside the area 3140 { 3141 pt3.x = X; 3142 pt3.y = Y; 3143 nResult = 1; //use at least some of the pixels 3144 } 3145 if (pt1.y <= maxPixels && maxPixels <= pt0.y) //pt0 outside the area 3146 { 3147 pt2.x = X; 3148 pt2.y = Y; 3149 nResult = 1; //use at least some of the pixels 3150 } 3151 } 3152 } 3153 3154 pt2x.value[0] = pt2.x; 3155 pt2y.value[0] = pt2.y; 3156 pt3x.value[0] = pt3.x; 3157 pt3y.value[0] = pt3.y; 3158 } catch (Exception exc) { 3159 ErrorLogger.LogException(_className, "DisplayIntersectPixels", 3160 new RendererException("Failed inside DisplayIntersectPixels", exc)); 3161 } 3162 return nResult; 3163 } 3164 /** 3165 * Computes Ditch spikes for the ATDITCH line types. This function uses 3166 * linestyles provided by the caller to skip segments. 3167 * 3168 * @param pLinePoints OUT - the client points also used for the return 3169 * points 3170 * @param nOldCounter the number of client points 3171 * @param bWayIs the parallel line to use (0) for inner or outer spikes 3172 * 3173 * @return the symbol point count 3174 */ 3175 protected static int GetDitchSpikeDouble(TGLight tg, POINT2[] pLinePoints, 3176 int nOldCounter, 3177 int bWayIs) { 3178 int nSpikeCounter = 0; 3179 try { 3180 //declarations 3181 int linetype = tg.get_LineType(); 3182 int nNumberOfSegments = 0, 3183 lCircleCounter = 0, 3184 bolVertical = 0, 3185 nTemp = 0, 3186 i, 3187 j; 3188 double dPrinter = 1.0; 3189 double dIntLocation1x = 0, 3190 dIntLocation2x = 0, 3191 dIntLocation1y = 0, 3192 dIntLocation2y = 0, 3193 r = 0, 3194 s = 0, 3195 use = 0, 3196 length = 0, 3197 k = 0, 3198 bint = 0; 3199 ref<double[]> pdAnswer = new ref();//new double[6]; 3200 ref<double[]> m = new ref(); 3201 3202 POINT2 UpperLinePoint = new POINT2(pLinePoints[0]), 3203 Lower1LinePoint = new POINT2(pLinePoints[0]), 3204 Lower2LinePoint = new POINT2(pLinePoints[0]), 3205 a = new POINT2(pLinePoints[0]), 3206 b = new POINT2(pLinePoints[0]); 3207 POINT2[] pCirclePoints = new POINT2[pLinePoints.length]; 3208 POINT2 averagePoint = new POINT2(); 3209 POINT2 lastAveragePoint = new POINT2(); 3210 POINT2[] pTempLinePoints = null; 3211 //end declarations 3212 3213 pTempLinePoints = new POINT2[nOldCounter]; 3214 for (j = 0; j < nOldCounter; j++) { 3215 pTempLinePoints[j] = new POINT2(pLinePoints[j]); 3216 } 3217 3218 ArrayList<POINT2> basePoints = new ArrayList(); 3219 3220 InitializePOINT2Array(pCirclePoints); 3221 nSpikeCounter = nOldCounter; 3222 double spikeLength = arraysupport.getScaledSize(12, tg.get_LineThickness(), tg.get_patternScale()); 3223 double spikeHeight = spikeLength * 1.25; 3224 double minLength = 2 * spikeLength; 3225 for (i = 0; i < nOldCounter - 1; i++) { 3226 if (linetype == TacticalLines.ATDITCHM && i == 0) { 3227 double radius = arraysupport.getScaledSize(4, tg.get_LineThickness(), tg.get_patternScale()); 3228 minLength = spikeLength * 2.5 + radius * 2; 3229 } 3230 3231 nTemp = CalcTrueLinesDouble((long) (spikeHeight * dPrinter), pLinePoints[i], pLinePoints[i + 1], pdAnswer); 3232 r = pdAnswer.value[3]; 3233 s = pdAnswer.value[5]; 3234 length = CalcDistanceDouble(pLinePoints[i], pLinePoints[i + 1]); 3235 bolVertical = CalcTrueSlopeDouble(pLinePoints[i], pLinePoints[i + 1], m); 3236 nNumberOfSegments = (int) ((length - 1) / (spikeLength * dPrinter)); 3237 3238 if (length > minLength * dPrinter) { //minLength was 24 3239 if (bWayIs != 0) { 3240 if (pLinePoints[i].x <= pLinePoints[i + 1].x) { 3241 use = r; 3242 } 3243 if (pLinePoints[i].x >= pLinePoints[i + 1].x) { 3244 use = s; 3245 } 3246 } //end if 3247 else { 3248 if (pLinePoints[i].x <= pLinePoints[i + 1].x) { 3249 use = s; 3250 } 3251 if (pLinePoints[i].x >= pLinePoints[i + 1].x) { 3252 use = r; 3253 } 3254 } //end else 3255 3256 for (j = 1; j <= nNumberOfSegments; j++) { 3257 k = (double) j; 3258 a = new POINT2(pLinePoints[i]); 3259 b = new POINT2(pLinePoints[i + 1]); 3260 3261 if (j > 1) { 3262 dIntLocation1x = dIntLocation2x; 3263 } else { 3264 dIntLocation1x 3265 = (double) pLinePoints[i].x + ((k * spikeLength - spikeLength / 2) * dPrinter / length) 3266 * (double) (pLinePoints[i + 1].x - pLinePoints[i].x); 3267 } 3268 3269 if (j > 1) //added M. Deutch 2-23-99 3270 { 3271 dIntLocation1y = dIntLocation2y; 3272 } else { 3273 dIntLocation1y 3274 = (double) pLinePoints[i].y + ((k * spikeLength - spikeLength / 2) * dPrinter / length) 3275 * (double) (pLinePoints[i + 1].y - pLinePoints[i].y); 3276 } 3277 3278 dIntLocation2x = (double) pLinePoints[i].x 3279 + ((k * spikeLength + spikeLength / 2) * dPrinter / length) 3280 * (double) (pLinePoints[i + 1].x 3281 - pLinePoints[i].x); 3282 3283 dIntLocation2y = (double) pLinePoints[i].y 3284 + ((k * spikeLength + spikeLength / 2) * dPrinter / length) 3285 * (double) (pLinePoints[i + 1].y 3286 - pLinePoints[i].y); 3287 3288 if (m.value[0] != 0 && bolVertical != 0) { 3289 bint = (dIntLocation1y + dIntLocation2y) / 2.0 3290 + (1 / m.value[0]) * (dIntLocation1x + dIntLocation2x) / 2.0; 3291 //independent of direction 3292 UpperLinePoint = CalcTrueIntersectDouble2(m.value[0], use, -1 / m.value[0], bint, 1, 1, pLinePoints[0].x, pLinePoints[0].y); 3293 } 3294 3295 if (bolVertical == 0) //vertical segment 3296 { 3297 if (dIntLocation1y < dIntLocation2y) { 3298 UpperLinePoint.y = (int) dIntLocation1y + (int) (length / nNumberOfSegments / 2); 3299 } else { 3300 UpperLinePoint.y = (int) dIntLocation1y - (int) (length / nNumberOfSegments / 2); 3301 } 3302 if (pLinePoints[i].y < pLinePoints[i + 1].y) { 3303 UpperLinePoint.x = (int) dIntLocation1x + (int) (length / nNumberOfSegments); 3304 } else { 3305 UpperLinePoint.x = (int) dIntLocation1x - (int) (length / nNumberOfSegments); 3306 } 3307 } 3308 if (m.value[0] == 0 && bolVertical != 0) { 3309 if (dIntLocation1x < dIntLocation2x) { 3310 UpperLinePoint.x = (int) dIntLocation1x + (int) (length / nNumberOfSegments / 2); 3311 } else { 3312 UpperLinePoint.x = (int) dIntLocation1x - (int) (length / nNumberOfSegments / 2); 3313 } 3314 if (pLinePoints[i + 1].x < pLinePoints[i].x) { 3315 UpperLinePoint.y = (int) dIntLocation1y + (int) (length / nNumberOfSegments); 3316 } else { 3317 UpperLinePoint.y = (int) dIntLocation1y - (int) (length / nNumberOfSegments); 3318 } 3319 } 3320 //end section 3321 3322 Lower1LinePoint.x = dIntLocation1x; 3323 Lower1LinePoint.y = dIntLocation1y; 3324 Lower2LinePoint.x = dIntLocation2x; 3325 Lower2LinePoint.y = dIntLocation2y; 3326 3327 pLinePoints[nSpikeCounter] = new POINT2(Lower1LinePoint); 3328 if (linetype == TacticalLines.ATDITCHC || linetype == TacticalLines.ATDITCHM) { 3329 pLinePoints[nSpikeCounter].style = 9; 3330 } 3331 if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13 3332 { 3333 pLinePoints[nSpikeCounter].style = 5; 3334 } 3335 3336 nSpikeCounter++; 3337 3338 pLinePoints[nSpikeCounter] = new POINT2(UpperLinePoint); 3339 if (linetype == (long) TacticalLines.ATDITCHC || linetype == (long) TacticalLines.ATDITCHM) { 3340 pLinePoints[nSpikeCounter].style = 9; 3341 } 3342 if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13 3343 { 3344 pLinePoints[nSpikeCounter].style = 5; 3345 } 3346 3347 nSpikeCounter++; 3348 3349 pLinePoints[nSpikeCounter] = new POINT2(Lower2LinePoint); 3350 if (linetype == (long) TacticalLines.ATDITCHC || linetype == (long) TacticalLines.ATDITCHM) { 3351 pLinePoints[nSpikeCounter].style = 10; 3352 } 3353 if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13 3354 { 3355 pLinePoints[nSpikeCounter].style = 5; 3356 } 3357 3358 nSpikeCounter++; 3359 3360 if (linetype == TacticalLines.ATDITCHM) { 3361 if (j % 2 == 0) { 3362 averagePoint = lineutility.MidPointDouble(Lower1LinePoint, Lower2LinePoint, 0); 3363 averagePoint = lineutility.MidPointDouble(averagePoint, UpperLinePoint, 0); 3364 } else if (j == 1) { 3365 averagePoint = lineutility.ExtendLineDouble(Lower2LinePoint, Lower1LinePoint, 5); 3366 averagePoint = lineutility.MidPointDouble(averagePoint, UpperLinePoint, 0); 3367 } 3368 } 3369 //end section 3370 if (j > 1 && j < nNumberOfSegments) { 3371 basePoints.add(new POINT2(Lower1LinePoint)); 3372 //if(j==nNumberOfSegments-1) 3373 // basePoints.get(basePoints.size()-1).style=5; 3374 } else if (j == 1) { 3375 basePoints.add(new POINT2(pLinePoints[i])); 3376 } else if (j == nNumberOfSegments) { 3377 basePoints.add(new POINT2(pLinePoints[i + 1])); 3378 basePoints.get(basePoints.size() - 1).style = 5; 3379 } 3380 if (linetype == TacticalLines.ATDITCHM && j > 1) { 3381 if (j % 2 == 0) { 3382 pCirclePoints[lCircleCounter] = lineutility.MidPointDouble(averagePoint, lastAveragePoint, 20); 3383 lCircleCounter++; 3384 } 3385 //end section 3386 } 3387 if (j < nNumberOfSegments && linetype == TacticalLines.ATDITCHM) { 3388 if (j == 1 || j % 2 == 0) { 3389 //LastUpperLinePoint = new POINT2(UpperLinePoint); 3390 lastAveragePoint = new POINT2(averagePoint); 3391 } 3392 //end section 3393 } 3394 }//end for j<numberOfsegments 3395 } //end if length big enough 3396 else { 3397 //diagnostic 3398 pLinePoints[nSpikeCounter].x = pLinePoints[i].x; 3399 pLinePoints[nSpikeCounter].y = pLinePoints[i].y; 3400 pLinePoints[nSpikeCounter].style = 0; 3401 nSpikeCounter++; 3402 pLinePoints[nSpikeCounter].x = pLinePoints[i + 1].x; 3403 pLinePoints[nSpikeCounter].y = pLinePoints[i + 1].y; 3404 pLinePoints[nSpikeCounter].style = 5; 3405 nSpikeCounter++; 3406 } 3407 } 3408 3409 for (j = 0; j < nOldCounter; j++) //reverse the first nOldCounter points for 3410 { 3411 pLinePoints[j] = new POINT2(pTempLinePoints[nOldCounter - j - 1]); //purpose of drawing 3412 pLinePoints[j].style = 5; 3413 } 3414 3415 if (pLinePoints[nSpikeCounter - 1].style == 0) { 3416 pLinePoints[nSpikeCounter - 1].style = 5; 3417 } 3418 int t=basePoints.size(); 3419 //for (j = nSpikeCounter; j < nSpikeCounter + basePoints.size(); j++) 3420 for (j = nSpikeCounter; j < nSpikeCounter + t; j++) 3421 { 3422 pLinePoints[j] = new POINT2(basePoints.get(j - nSpikeCounter)); 3423 //if(linetype == TacticalLines.ATDITCHM && pLinePoints[j].style != 5) 3424 if (pLinePoints[j].style != 5) { 3425 pLinePoints[j].style = 0; 3426 } 3427 } 3428 nSpikeCounter += basePoints.size(); 3429 3430 if (linetype == (int) TacticalLines.ATDITCHM) { 3431 pLinePoints[nSpikeCounter - 1].style = 5;//was 10 3432 for (j = nSpikeCounter; j < nSpikeCounter + lCircleCounter; j++) { 3433 pLinePoints[j] = new POINT2(pCirclePoints[j - nSpikeCounter]); 3434 pLinePoints[j].style = 20; 3435 } 3436 nSpikeCounter += lCircleCounter; 3437 } 3438 3439 } catch (Exception exc) { 3440 ErrorLogger.LogException(_className, "GetDitchSpikeDouble", 3441 new RendererException("Failed inside GetDitchSpikeDouble", exc)); 3442 } 3443 return nSpikeCounter; 3444 } 3445 3446 /** 3447 * Moves pixels if points are identical, used for the channel types 3448 * 3449 * @param pLinePoints OUT - client points also for returned points 3450 */ 3451 protected static void MoveChannelPixels(POINT2[] pLinePoints) { 3452 try { 3453 if (pLinePoints == null || pLinePoints.length <= 0) { 3454 return; 3455 } 3456 3457 double[] pixels = new double[pLinePoints.length * 2]; 3458 boolean bolNoRepeats; 3459 int j, k = 0; 3460 double x1; 3461 double y1; 3462 double x2; 3463 double y2; 3464 int count = pLinePoints.length; 3465 //stuff pixels 3466 for (j = 0; j < count; j++) { 3467 pixels[k++] = pLinePoints[j].x; 3468 pixels[k++] = pLinePoints[j].y; 3469 } 3470 3471 bolNoRepeats = false; 3472 do { 3473 bolNoRepeats = true; 3474 for (j = 0; j < count - 1; j++) { 3475 x1 = pixels[2 * j]; 3476 y1 = pixels[2 * j + 1]; 3477 x2 = pixels[2 * j + 2]; 3478 y2 = pixels[2 * j + 3]; 3479 if (x1 == x2 && y1 == y2) //it's the same point 3480 { 3481 bolNoRepeats = false; 3482 pixels[2 * j + 2] = (long) x2 + 1; //move the point 3483 break; 3484 } 3485 } 3486 } while (bolNoRepeats == false); 3487 //stuff pLinePoints 3488 k = 0; 3489 for (j = 0; j < count; j++) { 3490 pLinePoints[j].x = pixels[k++]; 3491 pLinePoints[j].y = pixels[k++]; 3492 } 3493 } catch (Exception exc) { 3494 ErrorLogger.LogException(_className, "MoveChannelPixels", 3495 new RendererException("Failed inside MoveChannelPixels", exc)); 3496 } 3497 } 3498 3499 /** 3500 * Single Concertina cannot have horizontal first segment 3501 * 3502 * @param linetype 3503 * @param pLinePoints 3504 */ 3505 protected static void moveSingleCPixels(int linetype, POINT2[] pLinePoints) { 3506 try { 3507 switch (linetype) { 3508 case TacticalLines.SINGLEC: 3509 break; 3510 default: 3511 return; 3512 } 3513 if (pLinePoints.length > 1) { 3514 if (pLinePoints[1].y == pLinePoints[0].y) { 3515 pLinePoints[1].y++; 3516 } 3517 } 3518 } catch (Exception exc) { 3519 ErrorLogger.LogException(_className, "MoveSingleCPixels", 3520 new RendererException("Failed inside MoveSingleCPixels", exc)); 3521 } 3522 } 3523 3524 /** 3525 * Rotates an the first vblCounter points in the array about its first point 3526 * 3527 * @param pLinePoints OUT - the points to rotate 3528 * @param vblCounter the number of points to rotate 3529 * @param lAngle the angle in degrees to rotate 3530 */ 3531 protected static void RotateGeometryDouble(POINT2[] pLinePoints, 3532 int vblCounter, 3533 double lAngle) { 3534 try { 3535 int j = 0; 3536 double dRotate = 0, 3537 dTheta = 0, 3538 dGamma = 0, 3539 x = 0, 3540 y = 0; 3541 3542 if (lAngle != 0) //if the angle is 0 no rotation occurs 3543 { 3544 POINT2 pdCenter; 3545 dRotate = lAngle * Math.PI / 180d; 3546 pdCenter = CalcCenterPointDouble(pLinePoints, vblCounter); 3547 3548 for (j = 0; j < vblCounter; j++) { 3549 //added if/else to get rid of divide by zero error 5/12/04 M. Deutch 3550 if (pLinePoints[j].x == pdCenter.x) { 3551 if ((pLinePoints[j].y > pdCenter.y)) { 3552 dGamma = Math.PI + Math.PI / 2; 3553 } else { 3554 dGamma = Math.PI / 2; 3555 } 3556 } else { 3557 dGamma = Math.PI + Math.atan((pLinePoints[j].y - pdCenter.y) 3558 / (pLinePoints[j].x - pdCenter.x)); 3559 } 3560 3561 if ((double) pLinePoints[j].x >= pdCenter.x) { 3562 dGamma = dGamma + Math.PI; 3563 } 3564 3565 dTheta = dRotate + dGamma; 3566 y = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.sin(dTheta); 3567 x = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.cos(dTheta); 3568 pLinePoints[j].y = pdCenter.y + y; 3569 pLinePoints[j].x = pdCenter.x + x; 3570 } //end for 3571 3572 return; 3573 } //end if 3574 } catch (Exception exc) { 3575 ErrorLogger.LogException(_className, "RotateGeometryDouble", 3576 new RendererException("Failed inside RotateGeometryDouble", exc)); 3577 } 3578 } // end 3579 3580 /** 3581 * Returns the point on line (pt0 to pt1) closest to ptRelative 3582 * 3583 * @param pt0 the first point on line 3584 * @param pt1 the second point on line 3585 * @param ptRelative the second point on line 3586 * @return the point closest to ptRelative on the line 3587 */ 3588 public static POINT2 ClosestPointOnLine(POINT2 pt0, POINT2 pt1, POINT2 ptRelative) { 3589 if (pt0.x == ptRelative.x && pt0.y == ptRelative.y) 3590 return new POINT2(pt0); 3591 else if (pt1.x == ptRelative.x && pt1.y == ptRelative.y) 3592 return new POINT2(pt1); 3593 else if (pt0.x == pt1.x && pt0.y == pt1.y) 3594 return new POINT2(pt0); 3595 3596 POINT2 atob = new POINT2(pt1.x - pt0.x, pt1.y - pt0.y ); 3597 POINT2 atop = new POINT2(ptRelative.x - pt0.x, ptRelative.y - pt0.y ); 3598 double len = atob.x * atob.x + atob.y * atob.y; 3599 double dot = atop.x * atob.x + atop.y * atob.y; 3600 double t = Math.min( 1, Math.max( 0, dot / len ) ); 3601 3602 return new POINT2(pt0.x + atob.x * t, pt0.y + atob.y * t); 3603 } 3604 3605 /** 3606 * Returns the intersection between two line segments or null if it doesn't exist 3607 * 3608 * @param pt1 3609 * @param pt2 3610 * @param pt3 3611 * @param pt4 3612 * @return 3613 */ 3614 private static POINT2 getIntersectionPoint(POINT2 pt1, POINT2 pt2, POINT2 pt3, POINT2 pt4) { 3615 double denom = (pt4.y - pt3.y) * (pt2.x - pt1.x) - (pt4.x - pt3.x) * (pt2.y - pt1.y); 3616 3617 if (denom == 0.0) { // Lines are parallel or collinear 3618 return null; 3619 } 3620 3621 double ua = ((pt4.x - pt3.x) * (pt1.y - pt3.y) - (pt4.y - pt3.y) * (pt1.x - pt3.x)) / denom; 3622 double ub = ((pt2.x - pt1.x) * (pt1.y - pt3.y) - (pt2.y - pt1.y) * (pt1.x - pt3.x)) / denom; 3623 3624 if (ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0) { 3625 // Intersection point lies within both segments 3626 double intersectX = pt1.x + ua * (pt2.x - pt1.x); 3627 double intersectY = pt1.y + ua * (pt2.y - pt1.y); 3628 return new POINT2(intersectX, intersectY); 3629 } 3630 3631 return null; // Segments do not intersect 3632 } 3633 3634 /** 3635 * Returns the intersection between a polygon and a line or null if it doesn't exist 3636 * 3637 * @param polyPts 3638 * @param pt0 3639 * @param pt1 3640 * @return 3641 */ 3642 public static POINT2 intersectPolygon(POINT2[] polyPts, POINT2 pt0, POINT2 pt1) { 3643 for (int i = 0; i < polyPts.length; i++) { 3644 POINT2 temp = getIntersectionPoint(polyPts[i], polyPts[(i + 1) % polyPts.length], pt0, pt1); 3645 if (temp != null) return temp; 3646 } 3647 return null; 3648 } 3649 3650 /** 3651 * Returns the point perpendicular to the line (pt0 to pt1) at the midpoint 3652 * the same distance from (and on the same side of) the the line as 3653 * ptRelative. 3654 * 3655 * @param pt0 the first point 3656 * @param pt1 the second point 3657 * @param ptRelative the point to use for computing the return point 3658 * 3659 * @return the point perpendicular to the line at the midpoint 3660 */ 3661 protected static POINT2 PointRelativeToLine(POINT2 pt0, 3662 POINT2 pt1, 3663 POINT2 ptRelative) { 3664 POINT2 ptResult = new POINT2(pt0); 3665 try { 3666 int bolVertical = 0; 3667 ref<double[]> m = new ref(); 3668 POINT2 midPt = MidPointDouble(pt0, pt1, 0); 3669 double b1 = 0, b2 = 0; 3670 //end declarations 3671 3672 bolVertical = CalcTrueSlopeDouble(pt0, pt1, m); 3673 if (bolVertical == 0) //line is vertical 3674 { 3675 ptResult.x = ptRelative.x; 3676 ptResult.y = midPt.y; 3677 } 3678 if (bolVertical != 0 && m.value[0] == 0) { 3679 ptResult.x = midPt.x; 3680 ptResult.y = ptRelative.y; 3681 } 3682 if (bolVertical != 0 && m.value[0] != 0) { 3683 b1 = midPt.y + (1 / m.value[0]) * midPt.x; //the line perp to midPt 3684 b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line ptRelative with the slope of pt1-pt2 3685 ptResult = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0); 3686 } 3687 } catch (Exception exc) { 3688 ErrorLogger.LogException(_className, "PointRelativeToLine", 3689 new RendererException("Failed inside PointRelativeToLine", exc)); 3690 } 3691 return ptResult; 3692 } 3693 3694 /** 3695 * shift the control point to match the shift that occurs in 3696 * Channels.GetAXADDouble for CATKBYFIRE. This is because the rotary feature 3697 * arrow tip must align with the anchor point 3698 * 3699 * @param linetype 3700 * @param pLinePoints the anchor points including the control point 3701 * @param dist the minimum required distance from the front of the rotary 3702 * arrow 3703 */ 3704 public static void adjustCATKBYFIREControlPoint(int linetype, 3705 ArrayList<POINT2> pLinePoints, 3706 double dist) { 3707 try { 3708 if (linetype != TacticalLines.CATKBYFIRE) { 3709 return; 3710 } 3711 3712 double dist2 = lineutility.CalcDistanceDouble(pLinePoints.get(0), pLinePoints.get(1)); 3713 if (dist2 <= dist) { 3714 return; 3715 } 3716 3717 POINT2 pt = null; 3718 int count = pLinePoints.size(); 3719 POINT2 pt0 = new POINT2(pLinePoints.get(0)); 3720 POINT2 pt1 = new POINT2(pLinePoints.get(1)); 3721 POINT2 controlPt = new POINT2(pLinePoints.get(count - 1)); 3722 POINT2 pt4 = PointRelativeToLine(pt0, pt1, pt1, controlPt); 3723 pt = lineutility.ExtendLineDouble(pt4, controlPt, dist); 3724 pLinePoints.set(count - 1, pt); 3725 } catch (Exception exc) { 3726 ErrorLogger.LogException(_className, "adjustCATKBYFIREControlPoint", 3727 new RendererException("Failed inside adjustCATKBYFIREControlPoint", exc)); 3728 } 3729 } 3730 3731 /** 3732 * Returns the point perpendicular to the line (pt0 to pt1) at atPoint the 3733 * same distance from (and on the same side of) the the line as ptRelative. 3734 * 3735 * @param pt0 the first point 3736 * @param pt1 the second point 3737 * @param atPoint the point on the line at which to compute the extended 3738 * point 3739 * @param ptRelative the point to use for computing the return point 3740 * 3741 * @return the point perpendicular to the line at ptRelative 3742 */ 3743 public static POINT2 PointRelativeToLine(POINT2 pt0, 3744 POINT2 pt1, 3745 POINT2 atPoint, 3746 POINT2 ptRelative) { 3747 POINT2 ptResult = new POINT2(pt0); 3748 try { 3749 int bolVertical = 0; 3750 ref<double[]> m = new ref(); 3751 double b1 = 0, b2 = 0; 3752 3753 bolVertical = CalcTrueSlopeDouble(pt0, pt1, m); 3754 if (bolVertical == 0) //line is vertical 3755 { 3756 ptResult.x = ptRelative.x; 3757 ptResult.y = atPoint.y; 3758 } 3759 if (bolVertical != 0 && m.value[0] == 0) { 3760 ptResult.x = atPoint.x; 3761 ptResult.y = ptRelative.y; 3762 } 3763 if (bolVertical != 0 && m.value[0] != 0) { 3764 b1 = atPoint.y + (1 / m.value[0]) * atPoint.x; //the line perp to midPt 3765 b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line ptRelative with the slope of pt1-pt2 3766 ptResult = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0); 3767 } 3768 } catch (Exception exc) { 3769 ErrorLogger.LogException(_className, "PointRelativeToLine", 3770 new RendererException("Failed inside PointRelativeToLine", exc)); 3771 } 3772 return ptResult; 3773 } 3774 3775 /** 3776 * Returns in pt2 and pt3 the line segment parallel to segment pt0-pt1 which 3777 * would contain ptRelative. pt2 corresponds to pt0 and pt3 corresponds to 3778 * pt1. 3779 * 3780 * @param pt0 first line point 3781 * @param pt1 second line point 3782 * @param ptRelative relative line point 3783 * @param pt2 OUT - first computed relative line point 3784 * @param pt3 OUT - second computed relative line point 3785 */ 3786 public static void LineRelativeToLine(POINT2 pt0, 3787 POINT2 pt1, 3788 POINT2 ptRelative, 3789 POINT2 pt2, 3790 POINT2 pt3) { 3791 try { 3792 int bolVertical = 0; 3793 ref<double[]> m = new ref(); 3794 double b1 = 0, b2 = 0; 3795 POINT2 pt2Temp = null; 3796 POINT2 pt3Temp = null; 3797 3798 bolVertical = CalcTrueSlopeDouble(pt0, pt1, m); 3799 if (bolVertical == 0) //line is vertical 3800 { 3801 pt2.x = ptRelative.x; 3802 pt2.y = pt0.y; 3803 pt3.x = ptRelative.x; 3804 pt3.y = pt1.y; 3805 } 3806 if (bolVertical != 0 && m.value[0] == 0) //line is horizontal 3807 { 3808 pt2.x = pt0.x; 3809 pt2.y = ptRelative.y; 3810 pt3.x = pt1.x; 3811 pt3.y = ptRelative.y; 3812 } 3813 if (bolVertical != 0 && m.value[0] != 0) { 3814 b1 = pt0.y + (1 / m.value[0]) * pt0.x; //the line perp to pt0 3815 b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line the ptRelative with the slope of pt0-pt1 3816 pt2Temp = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0); 3817 3818 b1 = pt1.y + (1 / m.value[0]) * pt1.x; //the line perp to pt1 3819 //b2=ptRelative.y-m*ptRelative.x; //the line the ptRelative with the slope of pt0-pt1 3820 pt3Temp = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0); 3821 3822 pt2.x = pt2Temp.x; 3823 pt2.y = pt2Temp.y; 3824 pt3.x = pt3Temp.x; 3825 pt3.y = pt3Temp.y; 3826 } 3827 } catch (Exception exc) { 3828 ErrorLogger.LogException(_className, "LineRelativeToLine", 3829 new RendererException("Failed inside LineRelativeToLine", exc)); 3830 } 3831 } 3832 3833 /** 3834 * 3835 * @param p1 start point 3836 * @param p2 end point 3837 * @param p3 point not on the line 3838 * @return the point closest to point 3. This point and point 3 will create a line that is perpendicular to 3839 * the line created by point 1 and 2. 3840 */ 3841 public static POINT2 FindClosestPointOnLine(POINT2 p1, POINT2 p2, POINT2 p3) { 3842 // Calculate the direction vector of the line (u) 3843 double dxLine = p2.x - p1.x; 3844 double dyLine = p2.y - p1.y; 3845 3846 // Calculate the vector from point 1 to point 3 (v) 3847 double dxToPoint3 = p3.x - p1.x; 3848 double dyToPoint3 = p3.y - p1.y; 3849 3850 // Compute the dot products 3851 double dotProduct_uv = dxToPoint3 * dxLine + dyToPoint3 * dyLine; // v · u 3852 double dotProduct_uu = dxLine * dxLine + dyLine * dyLine; // u · u 3853 3854 // Calculate the scalar projection factor 3855 double scalarProjection = dotProduct_uv / dotProduct_uu; 3856 3857 // Find the closest point on the line 3858 double closestX = p1.x + scalarProjection * dxLine; 3859 double closestY = p1.y + scalarProjection * dyLine; 3860 3861 return new POINT2(closestX, closestY); 3862 } 3863 3864 private static void CalcMBR(POINT2[] pLinePoints, 3865 int numpts, 3866 ref<double[]> ulx, 3867 ref<double[]> uly, 3868 ref<double[]> lrx, 3869 ref<double[]> lry) { 3870 try { 3871 int j = 0; 3872 //initialize the MBR 3873 ulx.value = new double[1]; 3874 uly.value = new double[1]; 3875 lrx.value = new double[1]; 3876 lry.value = new double[1]; 3877 ulx.value[0] = Double.MAX_VALUE;//was 99999 3878 uly.value[0] = Double.MAX_VALUE;//was 99999 3879 lrx.value[0] = -Double.MAX_VALUE;//was -99999 3880 lry.value[0] = -Double.MAX_VALUE;//was -99999 3881 for (j = 0; j < numpts; j++) { 3882 if (pLinePoints[j].x > lrx.value[0]) { 3883 lrx.value[0] = pLinePoints[j].x; 3884 } 3885 if (pLinePoints[j].y > lry.value[0]) { 3886 lry.value[0] = pLinePoints[j].y; 3887 } 3888 if (pLinePoints[j].x < ulx.value[0]) { 3889 ulx.value[0] = pLinePoints[j].x; 3890 } 3891 if (pLinePoints[j].y < uly.value[0]) { 3892 uly.value[0] = pLinePoints[j].y; 3893 } 3894 } 3895 } catch (Exception exc) { 3896 ErrorLogger.LogException(_className, "CalcMBR", 3897 new RendererException("Failed inside CalcMBR", exc)); 3898 } 3899 return; 3900 } 3901 3902 public static void CalcMBRPoints(POINT2[] pLinePoints, 3903 int numpts, 3904 POINT2 ul, 3905 POINT2 lr) { 3906 try { 3907 int j = 0; 3908 ul.x = Double.MAX_VALUE; 3909 ul.y = Double.MAX_VALUE; 3910 lr.x = -Double.MAX_VALUE; 3911 lr.y = -Double.MAX_VALUE; 3912 for (j = 0; j < numpts; j++) { 3913 if (pLinePoints[j].x > lr.x) { 3914 lr.x = pLinePoints[j].x; 3915 } 3916 if (pLinePoints[j].y > lr.y) { 3917 lr.y = pLinePoints[j].y; 3918 } 3919 if (pLinePoints[j].x < ul.x) { 3920 ul.x = pLinePoints[j].x; 3921 } 3922 if (pLinePoints[j].y < ul.y) { 3923 ul.y = pLinePoints[j].y; 3924 } 3925 } 3926 } catch (Exception exc) { 3927 ErrorLogger.LogException(_className, "CalcMBRPoints", 3928 new RendererException("Failed inside CalcMBRPoints", exc)); 3929 } 3930 } 3931 3932 /** 3933 * Computes the distance in pixels from upper left to lower right of the 3934 * minimum bounding rectangle for the first numpts of pLinePoints 3935 * 3936 * @param pLinePoints the inpupt point array 3937 * @param numpts the number of points to use 3938 * 3939 * @return the distance in pixels 3940 */ 3941 protected static double MBRDistance(POINT2[] pLinePoints, 3942 int numpts) { 3943 double result = 0; 3944 try { 3945 ref<double[]> ulx = new ref(), uly = new ref(), lrx = new ref(), lry = new ref(); 3946 CalcMBR(pLinePoints, numpts, ulx, uly, lrx, lry); 3947 result = Math.sqrt((lrx.value[0] - ulx.value[0]) * (lrx.value[0] - ulx.value[0]) + (lry.value[0] - uly.value[0]) * (lry.value[0] - uly.value[0])); 3948 //sanity check 3949 3950 //return x or y distance if returnValue is 0 or infinity 3951 double xdist = Math.abs(lrx.value[0] - ulx.value[0]); 3952 double ydist = Math.abs(lry.value[0] - uly.value[0]); 3953 double max = xdist; 3954 if (ydist > xdist) { 3955 max = ydist; 3956 } 3957 3958 if (result == 0 || Double.isInfinite(result)) { 3959 if (max > 0) { 3960 result = max; 3961 } 3962 } 3963 3964 } catch (Exception exc) { 3965 ErrorLogger.LogException(_className, "MBRDistance", 3966 new RendererException("Failed inside MBRDistance", exc)); 3967 } 3968 return result; 3969 } 3970 3971 /** 3972 * Swaps two points. 3973 * 3974 * @param pt1 OUT - first point 3975 * @param pt2 OUT - second point 3976 * 3977 */ 3978 protected static void Reverse2Points(POINT2 pt1, POINT2 pt2) { 3979 try { 3980 POINT2 tempPt = new POINT2(); 3981 //store pt1 3982 tempPt.x = pt1.x; 3983 tempPt.y = pt1.y; 3984 pt1.x = pt2.x; 3985 pt1.y = pt2.y; 3986 pt2.x = tempPt.x; 3987 pt2.y = tempPt.y; 3988 } catch (Exception exc) { 3989 ErrorLogger.LogException(_className, "Reverse2Points", 3990 new RendererException("Failed inside Reverse2Points", exc)); 3991 } 3992 } 3993 /** 3994 * Creates a GeneralPath from a Path2D 3995 * 3996 * @param shape 3997 * @return 3998 */ 3999 public static Shape createStrokedShape(Shape shape) { 4000 GeneralPath newshape = new GeneralPath(); // Start with an empty shape 4001 try { 4002 // Iterate through the specified shape, perturb its coordinates, and 4003 // use them to build up the new shape. 4004 double[] coords = new double[6]; 4005 for (PathIterator i = shape.getPathIterator(null); !i.isDone(); i.next()) { 4006 int type = i.currentSegment(coords); 4007 switch (type) { 4008 case PathIterator.SEG_MOVETO: 4009 //perturb(coords, 2); 4010 newshape.moveTo(coords[0], coords[1]); 4011 break; 4012 case PathIterator.SEG_LINETO: 4013 //perturb(coords, 2); 4014 newshape.lineTo(coords[0], coords[1]); 4015 break; 4016 case PathIterator.SEG_QUADTO: 4017 //perturb(coords, 4); 4018 newshape.quadTo(coords[0], coords[1], coords[2], coords[3]); 4019 break; 4020 case PathIterator.SEG_CUBICTO: 4021 //perturb(coords, 6); 4022 newshape.curveTo(coords[0], coords[1], coords[2], coords[3], 4023 coords[4], coords[5]); 4024 break; 4025 case PathIterator.SEG_CLOSE: 4026 newshape.closePath(); 4027 break; 4028 } 4029 4030 } 4031 } catch (Exception exc) { 4032 ErrorLogger.LogException(_className, "createStrokedShape", 4033 new RendererException("Failed inside createStrokedShape", exc)); 4034 } 4035 return newshape; 4036 } 4037 //These functions were added to create a minimum bounding polygon 4038 /** 4039 * @deprecated Returns the determinant of the point matrix This determinant 4040 * tells how far p3 is from vector p1p2 and on which side it is 4041 * @param p1 4042 * @param p2 4043 * @param p3 4044 * @return 4045 */ 4046 static private int distance(Point p1, Point p2, Point p3) { 4047 try { 4048 int x1 = p1.x; 4049 int x2 = p2.x; 4050 int x3 = p3.x; 4051 int y1 = p1.y; 4052 int y2 = p2.y; 4053 int y3 = p3.y; 4054 return x1 * y2 + x3 * y1 + x2 * y3 - x3 * y2 - x2 * y1 - x1 * y3; 4055 } catch (Exception exc) { 4056 ErrorLogger.LogException(_className, "distance", 4057 new RendererException("Failed inside distance", exc)); 4058 } 4059 return 0; 4060 } 4061 4062 /** 4063 * @deprecated Returns the determinant of the point matrix This determinant 4064 * tells how far p3 is from vector p1p2 and on which side it is 4065 * @param p1 4066 * @param p2 4067 * @param p3 4068 * @return 4069 */ 4070 static private double distance2(POINT2 p1, POINT2 p2, POINT2 p3) { 4071 try { 4072 double x1 = p1.x; 4073 double x2 = p2.x; 4074 double x3 = p3.x; 4075 double y1 = p1.y; 4076 double y2 = p2.y; 4077 double y3 = p3.y; 4078 return x1 * y2 + x3 * y1 + x2 * y3 - x3 * y2 - x2 * y1 - x1 * y3; 4079 } catch (Exception exc) { 4080 ErrorLogger.LogException(_className, "distance2", 4081 new RendererException("Failed inside distance2", exc)); 4082 } 4083 return 0; 4084 } 4085 4086 /** 4087 * @deprecated @param points 4088 * @param l 4089 * @param r 4090 * @param path 4091 */ 4092 static private void cHull(ArrayList<Point> points, Point l, Point r, ArrayList<Point> path) { 4093 4094 if (points.size() < 3) { 4095 return; 4096 } 4097 4098 int maxDist = 0; 4099 int tmp; 4100 Point p = null; 4101 4102 for (Point pt : points) { 4103 if (pt != l && pt != r) { 4104 tmp = distance(l, r, pt); 4105 4106 if (tmp > maxDist) { 4107 maxDist = tmp; 4108 p = pt; 4109 } 4110 } 4111 } 4112 4113 ArrayList<Point> left = new ArrayList<Point>(); 4114 ArrayList<Point> right = new ArrayList<Point>(); 4115 left.add(l); 4116 right.add(p); 4117 4118 for (Point pt : points) { 4119 if (distance(l, p, pt) > 0) { 4120 left.add(pt); 4121 } else if (distance(p, r, pt) > 0) { 4122 right.add(pt); 4123 } 4124 } 4125 4126 left.add(p); 4127 right.add(r); 4128 cHull(left, l, p, path); 4129 path.add(p); 4130 cHull(right, p, r, path); 4131 } 4132 4133 /** 4134 * @deprecated @param points 4135 * @param l 4136 * @param r 4137 * @param path 4138 */ 4139 static private void cHull2(ArrayList<POINT2> points, POINT2 l, POINT2 r, ArrayList<POINT2> path) { 4140 4141 if (points.size() < 3) { 4142 return; 4143 } 4144 4145 double maxDist = 0; 4146 double tmp; 4147 POINT2 p = null; 4148 4149 for (POINT2 pt : points) { 4150 if (pt != l && pt != r) { 4151 tmp = distance2(l, r, pt); 4152 4153 if (tmp > maxDist) { 4154 maxDist = tmp; 4155 p = pt; 4156 } 4157 } 4158 } 4159 4160 ArrayList<POINT2> left = new ArrayList<POINT2>(); 4161 ArrayList<POINT2> right = new ArrayList<POINT2>(); 4162 left.add(l); 4163 right.add(p); 4164 4165 for (POINT2 pt : points) { 4166 if (distance2(l, p, pt) > 0) { 4167 left.add(pt); 4168 } else if (distance2(p, r, pt) > 0) { 4169 right.add(pt); 4170 } 4171 } 4172 4173 left.add(p); 4174 right.add(r); 4175 cHull2(left, l, p, path); 4176 path.add(p); 4177 cHull2(right, p, r, path); 4178 } 4179 //Returns the points of convex hull in the correct order 4180 /** 4181 * @deprecated @param array 4182 * @return 4183 */ 4184 static public ArrayList<Point> cHull(ArrayList<Point> array) { 4185 int size = array.size(); 4186 if (size < 2) { 4187 return null; 4188 } 4189 4190 Point l = array.get(0); 4191 Point r = array.get(size - 1); 4192 ArrayList<Point> path = new ArrayList<Point>(); 4193 path.add(l); 4194 cHull(array, l, r, path); 4195 path.add(r); 4196 cHull(array, r, l, path); 4197 return path; 4198 } 4199 4200 /** 4201 * @deprecated @param array 4202 * @return 4203 */ 4204 static public ArrayList<POINT2> cHull2(ArrayList<POINT2> array) { 4205 try { 4206 int size = array.size(); 4207 if (size < 2) { 4208 return null; 4209 } 4210 4211 POINT2 l = array.get(0); 4212 POINT2 r = array.get(size - 1); 4213 ArrayList<POINT2> path = new ArrayList<POINT2>(); 4214 path.add(l); 4215 cHull2(array, l, r, path); 4216 path.add(r); 4217 cHull2(array, r, l, path); 4218 return path; 4219 } catch (Exception exc) { 4220 ErrorLogger.LogException(_className, "cHull2", 4221 new RendererException("Failed inside cHull2", exc)); 4222 } 4223 return null; 4224 } 4225 4226 public static void getExteriorPoints(POINT2[] pLinePoints, 4227 int vblCounter, 4228 int lineType, 4229 boolean interior 4230 ) { 4231 int j; 4232 int index; 4233 POINT2 pt0, pt1, pt2; 4234 ref<double[]> m01 = new ref(), m12 = new ref(); 4235 int direction; 4236 POINT2 intersectPt; 4237 //ref<double[]> m1 = new ref(), m2 = new ref(); 4238 ArrayList<POINT2> intersectPoints = new ArrayList(); 4239 double b01, b12; //the y intercepts for the lines corresponding to m1,m2 4240 double dist = pLinePoints[0].style; 4241 for (j = 0; j < vblCounter; j++) { 4242 if (j == 0 || j == vblCounter - 1) { 4243 pt0 = new POINT2(pLinePoints[vblCounter - 2]); 4244 pt1 = new POINT2(pLinePoints[0]); 4245 pt2 = new POINT2(pLinePoints[1]); 4246 } else { 4247 pt0 = new POINT2(pLinePoints[j - 1]); 4248 pt1 = new POINT2(pLinePoints[j]); 4249 pt2 = new POINT2(pLinePoints[j + 1]); 4250 } 4251 if (pt1.style > 0) { 4252 dist = pt1.style; 4253 } 4254 //the exterior/interior points 4255 POINT2 pt00, pt01, pt10, pt11; 4256 4257 index = j - 1; 4258 if (index < 0) { 4259 index = vblCounter - 1; 4260 } 4261 POINT2[] pts = new POINT2[pLinePoints.length]; 4262 int n=pLinePoints.length; 4263 //for (int k = 0; k < pLinePoints.length; k++) 4264 for (int k = 0; k < n; k++) 4265 { 4266 pts[k] = pLinePoints[k]; 4267 } 4268 4269 direction = arraysupport.GetInsideOutsideDouble2(pt0, pt1, pts, vblCounter, index, lineType); 4270 //reverse the direction if these are interior points 4271 if (interior == true) { 4272 direction = reverseDirection(direction); 4273 } 4274 //pt00-pt01 will be the interior line inside line pt0-pt1 4275 //pt00 is inside pt0, pt01 is inside pt1 4276 pt00 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, direction, dist); 4277 pt01 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, direction, dist); 4278 4279 //pt10-pt11 will be the interior line inside line pt1-pt2 4280 //pt10 is inside pt1, pt11 is inside pt2 4281 index = j; 4282 if (j == vblCounter - 1) { 4283 index = 0; 4284 } 4285 direction = arraysupport.GetInsideOutsideDouble2(pt1, pt2, (POINT2[]) pts, vblCounter, index, lineType); 4286 //reverse the direction if these are interior points 4287 if (interior == true) { 4288 direction =reverseDirection(direction); 4289 } 4290 pt10 = lineutility.ExtendDirectedLine(pt1, pt2, pt1, direction, dist); 4291 pt11 = lineutility.ExtendDirectedLine(pt1, pt2, pt2, direction, dist); 4292 //intersectPt=new POINT2(null); 4293 //get the intersection of pt01-p00 and pt10-pt11 4294 //so it it is the interior intersection of pt0-pt1 and pt1-pt2 4295 4296 //first handle the case of vertical lines. 4297 if (pt0.x == pt1.x && pt1.x == pt2.x) { 4298 intersectPt = new POINT2(pt01); 4299 intersectPoints.add(intersectPt); 4300 continue; 4301 } 4302 //it's the same situation if the slopes are identical, 4303 //simply use pt01 or pt10 since they already uniquely define the intesection 4304 lineutility.CalcTrueSlopeDouble2(pt00, pt01, m01); 4305 lineutility.CalcTrueSlopeDouble2(pt10, pt11, m12); 4306 //if(m01.dbl==m12.dbl) 4307 if (m01.value[0] == m12.value[0]) { 4308 intersectPt = new POINT2(pt01); 4309 intersectPoints.add(intersectPt); 4310 continue; 4311 } 4312 //now we are assuming a non-trivial intersection 4313 //calculate the y-intercepts using y=mx+b (use b=y-mx) 4314 b01 = pt01.y - m01.value[0] * pt01.x; 4315 b12 = pt11.y - m12.value[0] * pt11.x; 4316 intersectPt = lineutility.CalcTrueIntersectDouble2(m01.value[0], b01, m12.value[0], b12, 1, 1, 0, 0); 4317 intersectPoints.add(intersectPt); 4318 }//end for 4319 int n=intersectPoints.size(); 4320 //for (j = 0; j < intersectPoints.size(); j++) 4321 for (j = 0; j < n; j++) 4322 { 4323 pLinePoints[j] = intersectPoints.get(j); 4324 } 4325 } 4326 public static ArrayList<POINT2> getDeepCopy(ArrayList<POINT2>pts) 4327 { 4328 ArrayList<POINT2>deepCopy=null; 4329 try 4330 { 4331 if(pts == null || pts.isEmpty()) 4332 return pts; 4333 deepCopy=new ArrayList(); 4334 int j=0; 4335 POINT2 pt=null; 4336 for(j=0;j<pts.size();j++) 4337 { 4338 pt=new POINT2(pts.get(j).x,pts.get(j).y,pts.get(j).style); 4339 deepCopy.add(pt); 4340 } 4341 } 4342 catch (Exception exc) { 4343 ErrorLogger.LogException(_className, "getDeepCopy", 4344 new RendererException("Failed inside getDeepCopy", exc)); 4345 } 4346 return deepCopy; 4347 } 4348 4349 public static int reverseDirection(int direction) { 4350 switch (direction) { 4351 case extend_left: 4352 return extend_right; 4353 case extend_right: 4354 return extend_left; 4355 case extend_above: 4356 return extend_below; 4357 case extend_below: 4358 return extend_above; 4359 default: 4360 return direction; 4361 } 4362 } 4363}//end lineutility