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 protected 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 * Returns the smallest x and y pixel values from an array of points 1411 * 1412 * @param ptsSeize array of points from which to find minimum vaules 1413 * @param vblCounter the number of points to test in the array 1414 * @param x OUT - an object with a member to hold the xminimum 1415 * @param y OUT - an object with a member to hold the y minimum value 1416 * 1417 */ 1418 public static void GetPixelsMin(POINT2[] ptsSeize, 1419 int vblCounter, 1420 ref<double[]> x, 1421 ref<double[]> y) { 1422 try { 1423 double xmin = Double.POSITIVE_INFINITY; 1424 double ymin = Double.POSITIVE_INFINITY; 1425 int j = 0; 1426 1427 for (j = 0; j < vblCounter; j++) { 1428 if (ptsSeize[j].x < xmin) { 1429 xmin = ptsSeize[j].x; 1430 } 1431 if (ptsSeize[j].y < ymin) { 1432 ymin = ptsSeize[j].y; 1433 } 1434 } 1435 x.value = new double[1]; 1436 y.value = new double[1]; 1437 x.value[0] = xmin; 1438 y.value[0] = ymin; 1439 } catch (Exception exc) { 1440 ErrorLogger.LogException(_className, "GetPixelsMin", 1441 new RendererException("Failed inside GetPixelsMin", exc)); 1442 } 1443 } 1444 1445 /** 1446 * Returns the largest x and y pixel values from an array of points 1447 * 1448 * @param ptsSeize array of points from which to find maximum values 1449 * @param vblCounter the number of points to test in the array 1450 * @param x OUT - an object with a member to hold the x maximum value 1451 * @param y OUT - an object with a member to hold the y maximum value 1452 * 1453 */ 1454 public static void GetPixelsMax(POINT2[] ptsSeize, 1455 int vblCounter, 1456 ref<double[]> x, 1457 ref<double[]> y) { 1458 try { 1459 double xmax = Double.NEGATIVE_INFINITY; 1460 double ymax = Double.NEGATIVE_INFINITY; 1461 int j = 0; 1462 1463 for (j = 0; j < vblCounter; j++) { 1464 if (ptsSeize[j].x > xmax) { 1465 xmax = ptsSeize[j].x; 1466 } 1467 if (ptsSeize[j].y > ymax) { 1468 ymax = ptsSeize[j].y; 1469 } 1470 } 1471 x.value = new double[1]; 1472 y.value = new double[1]; 1473 x.value[0] = xmax; 1474 y.value[0] = ymax; 1475 } catch (Exception exc) { 1476 ErrorLogger.LogException(_className, "GetPixelsMax", 1477 new RendererException("Failed inside GetPixelsMax", exc)); 1478 } 1479 } 1480 1481 /** 1482 * Returns center point for a clockwise arc to connect pts 1 and 2. Also 1483 * returns an extended point on the line between pt1 and the new center 1484 * Caller passes a POINT1 array of size 2 for ptsSeize, passes pt1 and pt2 1485 * in ptsSeize Returns the radius of the 90 degree arc between C (arc 1486 * center) and pt1 1487 * 1488 * @param ptsSeize OUT - two point array also used for the returned two 1489 * points 1490 * 1491 * @return the radius 1492 */ 1493 protected static double CalcClockwiseCenterDouble(POINT2[] ptsSeize) { 1494 double dRadius = 0; 1495 try { 1496 //declarations 1497 POINT2 pt1 = new POINT2(ptsSeize[0]); 1498 POINT2 pt2 = new POINT2(ptsSeize[1]); 1499 POINT2 C = new POINT2(pt1), midPt = new POINT2(pt1); //the center to calculate 1500 POINT2 E = new POINT2(pt1); //the extended point to calculate 1501 POINT2 ptYIntercept = new POINT2(pt1); 1502 int nQuadrant = 1; 1503 double b = 0, b1 = 0, b2 = 0, dLength = 0; 1504 ref<double[]> m = new ref(); 1505 int bolVertical = 0; 1506 ref<double[]> offsetX = new ref(), offsetY = new ref(); 1507 POINT2[] ptsTemp = new POINT2[2]; 1508 //end declarations 1509 1510 //must offset the points if necessary because there will be calculations 1511 //extending from the Y Intercept 1512 ptsTemp[0] = new POINT2(pt1); 1513 ptsTemp[1] = new POINT2(pt2); 1514 GetPixelsMin(ptsTemp, 2, offsetX, offsetY); 1515 if (offsetX.value[0] < 0) { 1516 offsetX.value[0] = offsetX.value[0] - 100; 1517 } else { 1518 offsetX.value[0] = 0; 1519 } 1520 //end section 1521 1522 midPt.x = (pt1.x + pt2.x) / 2; 1523 midPt.y = (pt1.y + pt2.y) / 2; 1524 dLength = CalcDistanceDouble(pt1, pt2); 1525 dRadius = dLength / Math.sqrt(2); 1526 nQuadrant = GetQuadrantDouble(pt1, pt2); 1527 1528 bolVertical = CalcTrueSlopeDouble(pt1, pt2, m); 1529 if (bolVertical != 0 && m.value[0] != 0) //line not vertical or horizontal 1530 { 1531 b = pt1.y - m.value[0] * pt1.x; 1532 //y intercept of line perpendicular to midPt of pt,p2 1533 b1 = midPt.y + (1 / m.value[0]) * midPt.x; 1534 //we want to shift the Y axis to the left by offsetX 1535 //so we get the new Y intercept at x=offsetX 1536 b2 = (-1 / m.value[0]) * offsetX.value[0] + b1; 1537 ptYIntercept.x = offsetX.value[0]; 1538 ptYIntercept.y = b2; 1539 switch (nQuadrant) { 1540 case 1: 1541 case 4: 1542 C = ExtendLineDouble(ptYIntercept, midPt, dLength / 2); 1543 break; 1544 case 2: 1545 case 3: 1546 C = ExtendLineDouble(ptYIntercept, midPt, -dLength / 2); 1547 break; 1548 default: 1549 break; 1550 } 1551 } 1552 if (bolVertical != 0 && m.value[0] == 0) //horizontal line 1553 { 1554 C.x = midPt.x; 1555 if (pt1.x < pt2.x) { 1556 C.y = midPt.y + dLength / 2; 1557 } else { 1558 C.y = midPt.y - dLength / 2; 1559 } 1560 } 1561 if (bolVertical == 0) //vertical line 1562 { 1563 ptYIntercept.x = offsetX.value[0]; 1564 ptYIntercept.y = midPt.y; 1565 switch (nQuadrant) { 1566 case 1: 1567 case 4: 1568 C = ExtendLineDouble(ptYIntercept, midPt, dLength / 2); 1569 break; 1570 case 2: 1571 case 3: 1572 C = ExtendLineDouble(ptYIntercept, midPt, -dLength / 2); 1573 break; 1574 default: 1575 break; 1576 } 1577 } 1578 1579 E = ExtendLineDouble(C, pt1, 50); 1580 ptsSeize[0] = new POINT2(C); 1581 ptsSeize[1] = new POINT2(E); 1582 1583 ptsTemp = null; 1584 } catch (Exception exc) { 1585 ErrorLogger.LogException(_className, "CalcClockwiseCenterDouble", 1586 new RendererException("Failed inside CalcClockwiseCenterDouble", exc)); 1587 } 1588 return dRadius; 1589 } 1590 1591 /** 1592 * Computes the points for an arrowhead based on a line segment 1593 * 1594 * @param startLinePoint segment start point 1595 * @param endLinePoint segment end point 1596 * @param nBiSector bisecotr in pixels 1597 * @param nBase base size in pixels 1598 * @param pResultLinePoints OUT - the arrowhead points 1599 * @param styl the line style to assign the last aroowhead point 1600 */ 1601 protected static void GetArrowHead4Double(POINT2 startLinePoint, 1602 POINT2 endLinePoint, 1603 int nBiSector, 1604 int nBase, 1605 POINT2[] pResultLinePoints, 1606 int styl) { 1607 try { 1608 //declarations 1609 int j = 0; 1610 double dy = (double) (endLinePoint.y - startLinePoint.y), 1611 dx = (double) (endLinePoint.x - startLinePoint.x), 1612 dSign = 1.0, 1613 AHBY = 0, 1614 AHBX = 0, 1615 AHBLY = 0, 1616 AHBLX = 0, 1617 AHBRY = 0, 1618 AHBRX = 0, 1619 dAngle = 0, 1620 dHypotenuse = 0; 1621 1622 POINT2 tempLinePoint = new POINT2(startLinePoint); 1623 //end declarations 1624 1625 if (dy == 0) { 1626 if (dx > 0) { 1627 dAngle = Math.PI; 1628 } else { 1629 dAngle = 0; 1630 } 1631 } else { 1632 dAngle = Math.atan(dx / dy) + Math.PI / 2; 1633 } 1634 1635 tempLinePoint.style = 0;//PS_SOLID; 1636 1637 if (dx <= 0.0 && dy <= 0.0) { 1638 dSign = -1.0; 1639 } 1640 if (dx >= 0.0 && dy <= 0.0) { 1641 dSign = -1.0; 1642 } 1643 if (dx <= 0.0 && dy >= 0.0) { 1644 dSign = 1.0; 1645 } 1646 if (dx >= 0.0 && dy >= 0.0) { 1647 dSign = 1.0; 1648 } 1649 1650 dHypotenuse = dSign * (double) nBiSector; 1651 1652 //Find x, y for Arrow Head nBase startLinePoint POINT1 1653 AHBX = (double) endLinePoint.x + dHypotenuse * Math.cos(dAngle); 1654 AHBY = (double) endLinePoint.y - dHypotenuse * Math.sin(dAngle); 1655 1656 //Half of the arrow head's length will be 10 units 1657 dHypotenuse = dSign * (double) (nBase / 2.0); 1658 1659 //Find x, y of Arrow Head nBase Left side end POINT1 1660 AHBLX = AHBX - dHypotenuse * Math.sin(dAngle); 1661 AHBLY = AHBY - dHypotenuse * Math.cos(dAngle); 1662 1663 //Find x, y of Arrow Head nBase Right side end POINT1 1664 AHBRX = AHBX + dHypotenuse * Math.sin(dAngle); 1665 AHBRY = AHBY + dHypotenuse * Math.cos(dAngle); 1666 1667 //replacement, just trying to return the POINT1s 1668 tempLinePoint.x = (int) AHBLX; 1669 tempLinePoint.y = (int) AHBLY; 1670 pResultLinePoints[0] = new POINT2(tempLinePoint); 1671 pResultLinePoints[1] = new POINT2(endLinePoint); 1672 tempLinePoint.x = (int) AHBRX; 1673 tempLinePoint.y = (int) AHBRY; 1674 pResultLinePoints[2] = new POINT2(tempLinePoint); 1675 switch (styl) { 1676 case 0: 1677 for (j = 0; j < 2; j++) { 1678 pResultLinePoints[j].style = 0; 1679 } 1680 pResultLinePoints[2].style = 5; 1681 break; 1682 case 9: 1683 for (j = 0; j < 2; j++) { 1684 pResultLinePoints[j].style = 9; 1685 } 1686 pResultLinePoints[2].style = 10; 1687 break; 1688 case 18: 1689 for (j = 0; j < 2; j++) { 1690 pResultLinePoints[j].style = 18; 1691 } 1692 pResultLinePoints[2].style = 5; 1693 break; 1694 default: 1695 for (j = 0; j < 2; j++) { 1696 pResultLinePoints[j].style = styl; 1697 } 1698 pResultLinePoints[2].style = 5; 1699 break; 1700 } 1701 } catch (Exception exc) { 1702 ErrorLogger.LogException(_className, "GetArrowhead4Double", 1703 new RendererException("Failed inside GetArrowhead4Double", exc)); 1704 } 1705 } 1706 1707 /** 1708 * Returns the midpoint between two points. 1709 * 1710 * @param pt0 the first point 1711 * @param pt1 the second point 1712 * @param styl the style to assign the mid point 1713 * 1714 * @return the mid point 1715 */ 1716 public static POINT2 MidPointDouble(POINT2 pt0, 1717 POINT2 pt1, 1718 int styl) { 1719 POINT2 ptResult = new POINT2(pt0); 1720 try { 1721 ptResult.x = (pt0.x + pt1.x) / 2; 1722 ptResult.y = (pt0.y + pt1.y) / 2; 1723 ptResult.style = styl; 1724 } catch (Exception exc) { 1725 ErrorLogger.LogException(_className, "MidPointDouble", 1726 new RendererException("Failed inside MidPointDouble", exc)); 1727 } 1728 return ptResult; 1729 } 1730 1731 /** 1732 * Rotates an the first vblCounter points in the array about its first point 1733 * 1734 * @param pLinePoints OUT - the points to rotate 1735 * @param vblCounter the number of points to rotate 1736 * @param lAngle the angle in degrees to rotate 1737 * 1738 * @return pLinePoints 1739 */ 1740 protected static POINT2[] RotateGeometryDoubleOrigin(POINT2[] pLinePoints, 1741 int vblCounter, 1742 int lAngle) { 1743 try { 1744 //declarations 1745 int j = 0; 1746 double dRotate = 0, 1747 dTheta = 0, 1748 dGamma = 0, 1749 x = 0, 1750 y = 0; 1751 //end declarations 1752 1753 if (lAngle != 0) { 1754 POINT2 pdCenter = new POINT2(); 1755 dRotate = (double) lAngle * Math.PI / 180d; 1756 //pdCenter = CalcCenterPointDouble(pLinePoints,vblCounter); 1757 pdCenter = new POINT2(pLinePoints[0]); 1758 1759 for (j = 0; j < vblCounter; j++) { 1760 dGamma = Math.PI + Math.atan((pLinePoints[j].y - pdCenter.y) 1761 / (pLinePoints[j].x - pdCenter.x)); 1762 1763 if (pLinePoints[j].x >= pdCenter.x) { 1764 dGamma = dGamma + Math.PI; 1765 } 1766 1767 dTheta = dRotate + dGamma; 1768 y = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.sin(dTheta); 1769 x = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.cos(dTheta); 1770 pLinePoints[j].y = pdCenter.y + y; 1771 pLinePoints[j].x = pdCenter.x + x; 1772 } //end for 1773 1774 return pLinePoints; 1775 } //end if 1776 } catch (Exception exc) { 1777 ErrorLogger.LogException(_className, "RotateGeometryDoubleOrigin", 1778 new RendererException("Failed inside RotateGeometryDoubleOrigin", exc)); 1779 } 1780 return pLinePoints; 1781 } // end function 1782 1783 /** 1784 * Returns a point a distance d pixels perpendicular to the pt0-pt1 line and 1785 * going toward pt2 1786 * 1787 * @param pt0 the first line point 1788 * @param pt1 the second line point 1789 * @param pt2 the relative line point 1790 * @param d the distance in pixels 1791 * @param styl the linestyle to assign the computed point 1792 * 1793 * @return the extended point 1794 */ 1795 public static POINT2 ExtendTrueLinePerpDouble(POINT2 pt0, 1796 POINT2 pt1, 1797 POINT2 pt2, 1798 double d, 1799 int styl) { 1800 POINT2 ptResult = new POINT2(pt0); 1801 try { 1802 POINT2 ptYIntercept = new POINT2(pt0); 1803 ref<double[]> m = new ref(); 1804 double b = 0, b1 = 0; //b is the normal Y intercept (at 0) 1805 int nTemp = 0; //b1 is the y intercept at offsetX 1806 1807 //must obtain x minimum to get the y-intercept to the left of 1808 //the left-most point 1809 ref<double[]> offsetX = new ref(), offsetY = new ref(); 1810 POINT2[] pts = new POINT2[3]; 1811 pts[0] = new POINT2(pt0); 1812 pts[1] = new POINT2(pt1); 1813 pts[2] = new POINT2(pt2); 1814 GetPixelsMin(pts, 3, offsetX, offsetY); 1815 1816 if (offsetX.value[0] <= 0) //was < 0 1817 { 1818 offsetX.value[0] = offsetX.value[0] - 100; 1819 } else { 1820 offsetX.value[0] = 0; 1821 } 1822 //end section 1823 1824 nTemp = CalcTrueSlopeDouble(pt0, pt1, m); 1825 switch (nTemp) { 1826 case 0: //vertical line 1827 if (pt0.y < pt1.y) { 1828 ptResult.x = pt2.x - d; 1829 ptResult.y = pt2.y; 1830 } else { 1831 ptResult.x = pt2.x + d; 1832 ptResult.y = pt2.y; 1833 } 1834 break; 1835 default: //non-vertical line 1836 if (m.value[0] == 0) { 1837 ptResult.x = pt2.x; 1838 ptResult.y = pt2.y + d; 1839 } else { 1840 b = (double) pt2.y + (1 / m.value[0]) * (double) pt2.x; 1841 //we need the y-intercept at the -offset 1842 b1 = (-1 / m.value[0]) * offsetX.value[0] + b; 1843 ptYIntercept.x = offsetX.value[0]; 1844 ptYIntercept.y = b1; 1845 ptResult = ExtendLineDouble(ptYIntercept, pt2, d); 1846 } 1847 break; 1848 } 1849 ptResult.style = styl; 1850 pts = null; 1851 } catch (Exception exc) { 1852 ErrorLogger.LogException(_className, "ExtendTrueLinePerpDouble", 1853 new RendererException("Failed inside ExtendTrueLinePerpDouble", exc)); 1854 } 1855 return ptResult; 1856 } 1857 1858 /** 1859 * Calculates the intersection of 2 lines pelative to a point. if one of the 1860 * lines is vertical use a distance dWidth above or below the line. pass 1861 * bolVertical1 = 1, or bolVertical2 = 1 if either line segment is vertical, 1862 * else pass 0. return the unique intersection in X,Y pointers. p2 is the 1863 * point that connects the 2 line segments to which the intersecting lines 1864 * are related, i.e. the intersecting lines are a distance dWidth pixels 1865 * above or below p2. uses dWidth and lOrient for cases in which at least 1866 * one of the lines is vertical. for normal lines this function assumes the 1867 * caller has passed the m, b for the appropriate upper or lower lines to 1868 * get the desired intgercept. this function is used for calculating the 1869 * upper and lower channel lines for channel types. For lOrient: see 1870 * comments in Channels.ConnectTrueDouble2 1871 * 1872 * @param m1 slope of the first line 1873 * @param b1 intercept of the first line 1874 * @param m2 slope of the second line 1875 * @param b2 y intercept of the second line 1876 * @param p2 point that connects the 2 line segments to which the 1877 * intersecting lines are related 1878 * @param bolVerticalSlope1 1 if first segment is vertical, else 0 1879 * @param bolVerticalSlope2 1 if second line segment is vertical, else 0 1880 * @param dWidth the distance of the intersecting lines from p2 in pixels 1881 * @param lOrient the orientation of the intersecting lines relative to the 1882 * segments connecting p2 1883 * @param X OUT - object holds the x value of the intersection point 1884 * @param Y OUT - object holds the y value of the intersection point 1885 */ 1886 protected static int CalcTrueIntersectDouble(double m1, 1887 double b1, 1888 double m2, 1889 double b2, 1890 POINT2 p2, //can use for vertical lines 1891 int bolVerticalSlope1, 1892 int bolVerticalSlope2, 1893 double dWidth, //use for vertical lines, use + for upper line, - for lower line 1894 int lOrient, 1895 ref<double[]> X, //intersection x value 1896 ref<double[]> Y) //intersection y value 1897 { 1898 1899 try { 1900 //case both lines are vertical 1901 double dWidth2 = Math.abs(dWidth); 1902 double b = 0; 1903 double dx = 0, dy = 0, m = 0; 1904 X.value = new double[1]; 1905 Y.value = new double[1]; 1906 1907 //cannot get out of having to do this 1908 //the problem is caused by inexact slopes which are created by 1909 //clsLineUtility.DisplayIntersectPixels. This occurs when setting 1910 //pt2 or pt3 with X or Y on the boundary +/-maxPixels 1911 //if you try to walk out until you get exactly the same slope 1912 //it can be thousands of pixels, so you have to accept an arbitrary 1913 //and, unfortuantely, inexact slope 1914 if (m1 != m2 && Math.abs(m1 - m2) <= Double.MIN_VALUE) { 1915 m1 = m2; 1916 } 1917 if (b1 != b2 && Math.abs(b1 - b2) <= Double.MIN_VALUE) { 1918 b1 = b2; 1919 } 1920 1921 //M. Deutch 10-24-11 1922 if (b1 == b2 && m1 + b1 == m2 + b2) { 1923 m1 = m2; 1924 } 1925 1926 if (bolVerticalSlope1 == 0 && bolVerticalSlope2 == 0) //both lines vertical 1927 { 1928 switch (lOrient) { 1929 case 0: 1930 X.value[0] = p2.x - dWidth2; 1931 Y.value[0] = p2.y; 1932 break; 1933 case 3: 1934 X.value[0] = p2.x + dWidth2; 1935 Y.value[0] = p2.y; 1936 break; 1937 default: //can never occur 1938 X.value[0] = p2.x; 1939 Y.value[0] = p2.y; 1940 break; 1941 } 1942 return 1; 1943 } 1944 if (bolVerticalSlope1 == 0 && bolVerticalSlope2 != 0) //line1 vertical, line2 is not 1945 { //there is a unique intersection 1946 switch (lOrient) { 1947 case 0: //Line1 above segment1 1948 case 1: 1949 X.value[0] = p2.x - dWidth2; 1950 Y.value[0] = m2 * X.value[0] + b2; 1951 break; 1952 case 2: //Line1 below segment1 1953 case 3: 1954 X.value[0] = p2.x + dWidth2; 1955 Y.value[0] = m2 * X.value[0] + b2; 1956 break; 1957 default: //can not occur 1958 X.value[0] = p2.x; 1959 Y.value[0] = p2.y; 1960 break; 1961 } 1962 return 1; 1963 } 1964 if (bolVerticalSlope2 == 0 && bolVerticalSlope1 != 0) //line2 vertical, line1 is not 1965 { //there is a unique intersection 1966 switch (lOrient) { 1967 case 0: //Line1 above segment2 1968 case 2: 1969 X.value[0] = p2.x - dWidth2; 1970 Y.value[0] = m1 * (X.value[0]) + b1; 1971 break; 1972 case 1: //Line1 below segment2 1973 case 3: 1974 X.value[0] = p2.x + dWidth2; 1975 Y.value[0] = m1 * (X.value[0]) + b1; 1976 break; 1977 default: //can not occur 1978 X.value[0] = p2.x; 1979 Y.value[0] = p2.y; 1980 break; 1981 } 1982 return 1; 1983 }//end if 1984 1985 //must deal with this case separately because normal lines use m1-m2 as a denominator 1986 //but we've handled all the vertical cases above so can assume it's not vertical 1987 //if the b's are different then one is an upper line, the other is a lower, no intersection 1988 //m and b will be used to build the perpendicular line thru p2 which we will use to 1989 //build the intersection, so must assume slopes are not 0, handle separately 1990 if (m1 == m2 && m1 != 0) { 1991 if (b1 == b2) //then the intercept is the point joining the 2 segments 1992 { 1993 //build the perpendicular line 1994 m = -1 / m1; 1995 b = p2.y - m * p2.x; 1996 X.value[0] = (b2 - b) / (m - m2); //intersect the lines (cannot blow up, m = m2 not possible) 1997 Y.value[0] = (m1 * (X.value[0]) + b1); 1998 return 1; 1999 } else //can not occur 2000 { 2001 X.value[0] = p2.x; 2002 Y.value[0] = p2.y; 2003 return 1; 2004 } 2005 } 2006 //slope is zero 2007 if (m1 == m2 && m1 == 0) { 2008 switch (lOrient) { 2009 case 0: //Line1 above the line 2010 case 1: //should never happen 2011 X.value[0] = p2.x; 2012 Y.value[0] = p2.y - dWidth2; 2013 break; 2014 case 3: //Line1 below the line 2015 case 2: //should never happen 2016 X.value[0] = p2.x; 2017 Y.value[0] = p2.y + dWidth2; 2018 break; 2019 default: //can not occur 2020 X.value[0] = p2.x; 2021 Y.value[0] = p2.y; 2022 break; 2023 } 2024 return 1; 2025 } 2026 2027 if (m1 == m2 && b1 == b2 && bolVerticalSlope1 != 0 && bolVerticalSlope2 != 0) { 2028 switch (lOrient) { 2029 case 0: //Line1 is above the line 2030 if (m1 < 0) { 2031 dy = m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is negative 2032 dx = dy / m1; //dx is negative 2033 X.value[0] = p2.x + dx; 2034 Y.value[0] = p2.y + dy; 2035 } 2036 if (m1 > 0) //slope is positive 2037 { 2038 dy = -m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is negative 2039 dx = -dy / m1; //dx is positive 2040 X.value[0] = p2.x + dx; 2041 Y.value[0] = p2.y + dy; 2042 } 2043 break; 2044 case 3: //Line1 is below the line 2045 if (m1 <= 0) { 2046 dy = -m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is positive 2047 dx = dy / m1; //dx is positive 2048 X.value[0] = p2.x + dx; 2049 Y.value[0] = p2.y + dy; 2050 } else { 2051 dy = m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is positive 2052 dx = -dy / m1; //dx is negative 2053 X.value[0] = p2.x + dx; 2054 Y.value[0] = p2.y + dy; 2055 } 2056 break; 2057 default: 2058 X.value[0] = p2.x; 2059 Y.value[0] = p2.y; 2060 break; 2061 } 2062 return 1; 2063 }//end if 2064 2065 //a normal line. no vertical or identical slopes 2066 //if m1=m2 function will not reach this point 2067 X.value[0] = (b2 - b1) / (m1 - m2); //intersect the lines 2068 Y.value[0] = (m1 * (X.value[0]) + b1); 2069 return 1; 2070 }//end try 2071 catch (Exception exc) { 2072 X.value[0] = p2.x; 2073 Y.value[0] = p2.y; 2074 ErrorLogger.LogException(_className, "CalcTrueIntersectDouble", 2075 new RendererException("Failed inside ExtendTrueIntersectDouble", exc)); 2076 } 2077 return 1; 2078 } 2079 2080 /** 2081 * Returns the distance in pixels from x1,y1 to x2,y2 2082 * 2083 * @param x1 first point x location in pixels 2084 * @param y1 first point y location in pixels 2085 * @param x2 second point x location in pixels 2086 * @param y2 second point y location in pixels 2087 * 2088 * @return the distance 2089 */ 2090 protected static double CalcDistance2(long x1, 2091 long y1, 2092 long x2, 2093 long y2) { 2094 double dResult = 0; 2095 try { 2096 dResult = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); 2097 2098 //sanity check 2099 //return x or y distance if return value is 0 or infinity 2100 double xdist = Math.abs(x1 - x2); 2101 double ydist = Math.abs(y1 - y2); 2102 double max = xdist; 2103 if (ydist > xdist) { 2104 max = ydist; 2105 } 2106 if (dResult == 0 || Double.isInfinite(dResult)) { 2107 if (max > 0) { 2108 dResult = max; 2109 } 2110 } 2111 } catch (Exception exc) { 2112 ErrorLogger.LogException(_className, "CalcDistance2", 2113 new RendererException("Failed inside CalcDistance2", exc)); 2114 } 2115 return dResult; 2116 } 2117 /** 2118 * gets the middle line for Rev B air corridors AC, LLTR, MRR, UAV 2119 * Middle line is handled separately now because the line may have been segmented 2120 * @param pLinePoints 2121 * @return 2122 */ 2123 protected static POINT2[] GetSAAFRMiddleLine(POINT2[] pLinePoints) { 2124 POINT2[] pts = null; 2125 try { 2126 int j = 0, count = 0; 2127 for (j = 0; j < pLinePoints.length-1; j++) { 2128 if (pLinePoints[j].style > 0) { 2129 count++; 2130 } 2131 } 2132 pts = new POINT2[count*2]; 2133 count=0; 2134 double dMRR=0; 2135 POINT2 firstSegPt=null,lastSegPt=null,pt0=null,pt1=null; 2136 for (j = 0; j < pLinePoints.length; j++) { 2137 if(pLinePoints[j].style>=0 || j==pLinePoints.length-1) 2138 { 2139 if(lastSegPt != null) 2140 { 2141 firstSegPt=new POINT2(lastSegPt); 2142 lastSegPt=new POINT2(pLinePoints[j]); 2143 dMRR=firstSegPt.style; 2144 pt0 = ExtendLine2Double(lastSegPt, firstSegPt, -dMRR, 0); 2145 pt1 = ExtendLine2Double(firstSegPt, lastSegPt, -dMRR, 5); 2146 pts[count++]=pt0; 2147 pts[count++]=pt1; 2148 } 2149 else 2150 { 2151 lastSegPt=new POINT2(pLinePoints[j]); 2152 } 2153 } 2154 } 2155 } catch (Exception exc) { 2156 ErrorLogger.LogException(_className, "GetSAAFRMiddleLine", 2157 new RendererException("Failed inside GetSAAFRMiddleLine", exc)); 2158 } 2159 return pts; 2160 } 2161 /** 2162 * Computes the points for a SAAFR segment 2163 * 2164 * @param pLinePoints OUT - the client points also used for the returned 2165 * points 2166 * @param lineType the line type 2167 * @param dMRR the symbol width 2168 */ 2169 protected static void GetSAAFRSegment(POINT2[] pLinePoints, 2170 int lineType, 2171 double dMRR) { 2172 try { 2173 POINT2 pt0 = new POINT2(); 2174 POINT2 pt1 = new POINT2(); 2175 POINT2 pt2 = new POINT2(); 2176 POINT2 pt3 = new POINT2(); 2177 POINT2 pt4 = new POINT2(); 2178 POINT2 pt5 = new POINT2(); 2179 ref<double[]> m = new ref(); 2180 int bolVertical = CalcTrueSlopeDouble(pLinePoints[0], pLinePoints[1], m); 2181 //shortened line 2182 //pt1=ExtendLine2Double(pLinePoints[0],pLinePoints[1],-dMRR/2,5); 2183 //pt0=ExtendLine2Double(pLinePoints[1],pLinePoints[0],-dMRR/2,0); 2184 pt1 = ExtendLine2Double(pLinePoints[0], pLinePoints[1], -dMRR, 5); 2185 pt0 = ExtendLine2Double(pLinePoints[1], pLinePoints[0], -dMRR, 0); 2186 if (bolVertical != 0 && m.value[0] < 1) { 2187 //upper line 2188 pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 2, dMRR); 2189 pt2.style = 0; 2190 pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 2, dMRR); 2191 pt3.style = 5; 2192 //lower line 2193 pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 3, dMRR); 2194 pt4.style = 0; 2195 pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 3, dMRR); 2196 pt5.style = 5; 2197 } //if( (bolVertical!=0 && m>1) || bolVertical==0) 2198 else { 2199 //left line 2200 pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 0, dMRR); 2201 pt2.style = 0; 2202 pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 0, dMRR); 2203 pt3.style = 5; 2204 //right line 2205 pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 1, dMRR); 2206 pt4.style = 0; 2207 pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 1, dMRR); 2208 pt5.style = 5; 2209 } 2210 //load the line points 2211 pLinePoints[0] = new POINT2(pt0); 2212 pLinePoints[1] = new POINT2(pt1); 2213 pLinePoints[2] = new POINT2(pt2); 2214 pLinePoints[3] = new POINT2(pt3); 2215 pLinePoints[4] = new POINT2(pt4); 2216 pLinePoints[5] = new POINT2(pt5); 2217 pLinePoints[5].style = 5; 2218 pLinePoints[0].style = 5; 2219 } catch (Exception exc) { 2220 ErrorLogger.LogException(_className, "GetSAAFRSegment", 2221 new RendererException("Failed inside GetSAAFRSegment", exc)); 2222 } 2223 } 2224 /** 2225 * Called by arraysupport for SAAFR and AC fill shapes 2226 * @param pLinePoints 2227 * @param dMRR 2228 */ 2229 protected static void GetSAAFRFillSegment(POINT2[] pLinePoints, 2230 double dMRR) { 2231 try { 2232 POINT2 pt2 = new POINT2(); 2233 POINT2 pt3 = new POINT2(); 2234 POINT2 pt4 = new POINT2(); 2235 POINT2 pt5 = new POINT2(); 2236 ref<double[]> m = new ref(); 2237 int bolVertical = CalcTrueSlopeDouble(pLinePoints[0], pLinePoints[1], m); 2238 if (bolVertical != 0 && m.value[0] < 1) { 2239 //upper line 2240 pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 2, dMRR); 2241 pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 2, dMRR); 2242 //lower line 2243 pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 3, dMRR); 2244 pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 3, dMRR); 2245 } //if( (bolVertical!=0 && m>1) || bolVertical==0) 2246 else { 2247 //left line 2248 pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 0, dMRR); 2249 pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 0, dMRR); 2250 //right line 2251 pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 1, dMRR); 2252 pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 1, dMRR); 2253 } 2254 //load the line points 2255 pLinePoints[0] = new POINT2(pt2); 2256 pLinePoints[1] = new POINT2(pt3); 2257 pLinePoints[2] = new POINT2(pt5); 2258 pLinePoints[3] = new POINT2(pt4); 2259 } catch (Exception exc) { 2260 ErrorLogger.LogException(_className, "GetSAAFRFillSegment", 2261 new RendererException("Failed inside GetSAAFRFillSegment", exc)); 2262 } 2263 //return; 2264 } 2265 /** 2266 * Computes an arc. 2267 * 2268 * @param pResultLinePoints OUT - contains center and start point and holds 2269 * the result arc points 2270 * @param vblCounter the number of client points 2271 * @param dRadius the arc radius in pixels 2272 * @param linetype the linetype determines start andgle and end angle for 2273 * the arc 2274 * 2275 */ 2276 protected static POINT2[] ArcArrayDouble(POINT2[] pResultLinePoints, 2277 int vblCounter, 2278 double dRadius, 2279 int linetype, 2280 IPointConversion converter) { 2281 try { 2282 //declarations 2283 double startangle = 0, //start of pArcLinePoints 2284 endangle = 0, //end of the pArcLinePoints 2285 increment = 0, 2286 //m = 0, 2287 length = 0, //length of a to e 2288 M = 0; 2289 2290 int j, numarcpts = 0, bolVertical = 0; 2291 ref<double[]> m = new ref(); 2292 //C is the center of the pArcLinePoints derived from a and e 2293 POINT2 C = new POINT2(pResultLinePoints[0]), 2294 a = new POINT2(pResultLinePoints[1]), 2295 e = new POINT2(pResultLinePoints[0]); 2296 2297 POINT2[] pArcLinePoints = null; 2298 //end declarations 2299 2300 bolVertical = CalcTrueSlopeDouble(a, e, m); 2301 if (bolVertical != 0) { 2302 M = Math.atan(m.value[0]); 2303 } else { 2304 if (a.y < e.y) { 2305 M = -Math.PI / 2; 2306 } else { 2307 M = Math.PI / 2; 2308 } 2309 } 2310 if(converter != null) 2311 { 2312 Point2D pt02d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y); 2313 Point2D pt12d=new Point2D.Double(pResultLinePoints[1].x,pResultLinePoints[1].y); 2314 //boolean reverseM=false; 2315 pt02d=converter.PixelsToGeo(pt02d); 2316 pt12d=converter.PixelsToGeo(pt12d); 2317 //M=mdlGeodesic.GetAzimuth(pt02d,pt12d); 2318 M= mdlGeodesic.GetAzimuth(new POINT2(pt02d.getX(),pt02d.getY()),new POINT2(pt12d.getX(),pt12d.getY() ) ); 2319 M*=(Math.PI/180); 2320 if(M<0) 2321 M+=Math.PI; 2322 } 2323 length = CalcDistanceDouble(a, e); 2324 if(converter != null) 2325 { 2326 Point2D pt02d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y); 2327 Point2D pt12d=new Point2D.Double(pResultLinePoints[1].x,pResultLinePoints[1].y); 2328 pt02d=converter.PixelsToGeo(pt02d); 2329 pt12d=converter.PixelsToGeo(pt12d); 2330 //length=mdlGeodesic.geodesic_distance(pt02d,pt12d,null,null); 2331 length=mdlGeodesic.geodesic_distance(new POINT2(pt02d.getX(),pt02d.getY()),new POINT2(pt12d.getX(),pt12d.getY()),null,null); 2332 } 2333 switch (linetype) { 2334 case TacticalLines.CLUSTER: 2335 startangle = M - 90 * Math.PI / 180.0; 2336 endangle = startangle + 2 * 90 * Math.PI / 180.0; 2337 break; 2338 case TacticalLines.ISOLATE: 2339 case TacticalLines.CORDONKNOCK: 2340 case TacticalLines.CORDONSEARCH: 2341 case TacticalLines.AREA_DEFENSE: 2342 startangle = M; 2343 endangle = startangle + 330 * Math.PI / 180; 2344 break; 2345 case TacticalLines.TURN_REVD: 2346 case TacticalLines.TURN: 2347 startangle = M; 2348 endangle = startangle + 90 * Math.PI / 180; 2349 break; 2350 case TacticalLines.OCCUPY: 2351 case TacticalLines.RETAIN: 2352 case TacticalLines.SECURE: 2353 startangle = M; 2354 //if(CELineArrayGlobals.Change1==false) 2355 endangle = startangle + 338 * Math.PI / 180; 2356 //else 2357 // endangle=startangle+330*pi/180; 2358 break; 2359 default: 2360 startangle = 0; 2361 endangle = 2 * Math.PI; 2362 break; 2363 } 2364 2365 if (a.x < e.x) { 2366 switch (linetype) { 2367 case TacticalLines.ISOLATE: 2368 case TacticalLines.CORDONKNOCK: 2369 case TacticalLines.CORDONSEARCH: 2370 case TacticalLines.AREA_DEFENSE: 2371 startangle = M - Math.PI; 2372 endangle = startangle + 330 * Math.PI / 180; 2373 break; 2374 case TacticalLines.OCCUPY: 2375 case TacticalLines.RETAIN: 2376 case TacticalLines.SECURE: 2377 startangle = M - Math.PI; 2378 //if(CELineArrayGlobals.Change1==false) 2379 endangle = startangle + 338 * Math.PI / 180; 2380 //else 2381 // endangle=startangle+330*pi/180; 2382 break; 2383 case TacticalLines.TURN_REVD: 2384 case TacticalLines.TURN: 2385 startangle = M - Math.PI; 2386 endangle = startangle + 90 * Math.PI / 180; 2387 break; 2388 case TacticalLines.CLUSTER: 2389 startangle = M - Math.PI + 90 * Math.PI / 180.0; 2390 endangle = startangle - 2 * 90 * Math.PI / 180.0; 2391 break; 2392 default: 2393 break; 2394 } 2395 } 2396 2397 numarcpts = 26; 2398 pArcLinePoints = new POINT2[numarcpts]; 2399 InitializePOINT2Array(pArcLinePoints); 2400 increment = (endangle - startangle) / (numarcpts - 1); 2401 if(dRadius != 0 && length != 0) 2402 { 2403 C.x = (int) ((double) e.x - (dRadius / length) 2404 * ((double) a.x - (double) e.x)); 2405 C.y = (int) ((double) e.y - (dRadius / length) 2406 * ((double) a.y - (double) e.y)); 2407 } 2408 else 2409 { 2410 C.x=e.x; 2411 C.y=e.y; 2412 } 2413 if (converter != null) 2414 { 2415 Point2D C2d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y); 2416 C2d=converter.PixelsToGeo(C2d); 2417 double az=0; 2418 Point2D ptGeo2d=null; 2419 POINT2 ptGeo=null; 2420 POINT2 ptPixels=null; 2421 for (j = 0; j < numarcpts; j++) { 2422 az=startangle*180/Math.PI+j*increment*180/Math.PI; 2423 //ptGeo=mdlGeodesic.geodesic_coordinate(C2d,length,az); 2424 ptGeo=mdlGeodesic.geodesic_coordinate(new POINT2(C2d.getX(),C2d.getY()),length,az); 2425 ptGeo2d=new Point2D.Double(ptGeo.x,ptGeo.y); 2426 ptGeo2d=converter.GeoToPixels(ptGeo2d); 2427 ptPixels=new POINT2(ptGeo2d.getX(),ptGeo2d.getY()); 2428 pArcLinePoints[j].x = ptPixels.x; 2429 pArcLinePoints[j].y = ptPixels.y; 2430 } 2431 } 2432 else 2433 { 2434 for (j = 0; j < numarcpts; j++) { 2435 //pArcLinePoints[j]=pResultLinePoints[0]; //initialize 2436 pArcLinePoints[j].x = (int) (dRadius * Math.cos(startangle + j * increment)); 2437 pArcLinePoints[j].y = (int) (dRadius * Math.sin(startangle + j * increment)); 2438 } 2439 2440 for (j = 0; j < numarcpts; j++) { 2441 pArcLinePoints[j].x += C.x; 2442 pArcLinePoints[j].y += C.y; 2443 } 2444 } 2445 for (j = 0; j < numarcpts; j++) { 2446 pResultLinePoints[j] = new POINT2(pArcLinePoints[j]); 2447 } 2448 pArcLinePoints = null; 2449 } catch (Exception exc) { 2450 ErrorLogger.LogException(_className, "ArcArrayDouble", 2451 new RendererException("Failed inside ArcArrayDouble", exc)); 2452 } 2453 return pResultLinePoints; 2454 } 2455 /** 2456 * Gets geodesic circle using the converter 2457 * @param Center in pixels 2458 * @param pt1 a point on the radius in pixels 2459 * @param numpts number of points to return 2460 * @param CirclePoints the result points 2461 * @param converter 2462 */ 2463 protected static void CalcCircleDouble2(POINT2 Center, 2464 POINT2 pt1, 2465 int numpts, 2466 POINT2[] CirclePoints, 2467 IPointConversion converter) { 2468 try { 2469 int j = 0; 2470 double increment = (Math.PI * 2) / (numpts - 1); 2471 Point2D ptCenter2d=new Point2D.Double(Center.x,Center.y); 2472 ptCenter2d=converter.PixelsToGeo(ptCenter2d); 2473 Point2D pt12d=new Point2D.Double(pt1.x,pt1.y); 2474 pt12d=converter.PixelsToGeo(pt12d); 2475 Center=new POINT2(ptCenter2d.getX(),ptCenter2d.getY()); 2476 pt1=new POINT2(pt12d.getX(),pt12d.getY()); 2477 double dist=mdlGeodesic.geodesic_distance(Center, pt1, null, null); 2478 2479 //double dSegmentAngle = 2 * Math.PI / numpts; 2480 double az=0; 2481 double startangle=0,endAngle=Math.PI*2; 2482 POINT2 ptGeo=null,ptPixels=null; 2483 Point2D ptGeo2d=null; 2484 for (j = 0; j < numpts - 1; j++) { 2485 az=startangle*180/Math.PI+j*increment*180/Math.PI; 2486 //ptGeo=mdlGeodesic.geodesic_coordinate(C2d,length,az); 2487 ptGeo=mdlGeodesic.geodesic_coordinate(Center,dist,az); 2488 ptGeo2d=new Point2D.Double(ptGeo.x,ptGeo.y); 2489 ptGeo2d=converter.GeoToPixels(ptGeo2d); 2490 ptPixels=new POINT2(ptGeo2d.getX(),ptGeo2d.getY()); 2491 CirclePoints[j].x = ptPixels.x; 2492 CirclePoints[j].y = ptPixels.y; 2493 } 2494 CirclePoints[numpts - 1] = new POINT2(CirclePoints[0]); 2495 2496 } catch (Exception exc) { 2497 ErrorLogger.LogException(_className, "CalcCircleDouble2", 2498 new RendererException("Failed inside CalcCircleDouble2", exc)); 2499 } 2500 return; 2501 } 2502 /** 2503 * Computes the points for a circle. Assumes CirclePoints has been allocated 2504 * with size numpts. 2505 * 2506 * @param Center the cicle center 2507 * @param radius the circle radius in pixels 2508 * @param numpts the number of circle points 2509 * @param CirclePoints - OUT - array of circle points 2510 * @param styl the style to set the last circle point 2511 */ 2512 protected static void CalcCircleDouble(POINT2 Center, 2513 double radius, 2514 int numpts, 2515 POINT2[] CirclePoints, 2516 int styl) { 2517 try { 2518 int j = 0; 2519 double dSegmentAngle = 2 * Math.PI / (numpts - 1); 2520 double x = 0, y = 0; 2521 for (j = 0; j < numpts - 1; j++) { 2522 x = Center.x + (radius * Math.cos((double) j * dSegmentAngle)); 2523 y = Center.y + (radius * Math.sin((double) j * dSegmentAngle)); 2524 CirclePoints[j] = new POINT2(x, y); 2525 CirclePoints[j].style = styl; 2526 } 2527 CirclePoints[numpts - 1] = new POINT2(CirclePoints[0]); 2528 2529 switch (styl) { 2530 case 0: 2531 CirclePoints[numpts - 1].style = 0; 2532 break; 2533 case 9: 2534 CirclePoints[numpts - 1].style = 10; 2535 break; 2536 case 11: 2537 CirclePoints[numpts - 1].style = 12; 2538 break; 2539 default: 2540 CirclePoints[numpts - 1].style = 5; 2541 break; 2542 } 2543 } catch (Exception exc) { 2544 ErrorLogger.LogException(_className, "CalcCircleDouble", 2545 new RendererException("Failed inside CalcCircleDouble", exc)); 2546 } 2547 } 2548 2549 protected static Shape2 CalcCircleShape(POINT2 Center, 2550 double radius, 2551 int numpts, 2552 POINT2[] CirclePoints, 2553 int styl) { 2554 Shape2 shape; 2555 if (styl == 9) { 2556 shape = new Shape2(Shape2.SHAPE_TYPE_FILL); 2557 } else { 2558 shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE); 2559 } 2560 2561 shape.set_Style(styl); 2562 try { 2563 int j = 0; 2564 CalcCircleDouble(Center, radius, numpts, CirclePoints, styl); 2565 shape.moveTo(CirclePoints[0]); 2566 for (j = 1; j < numpts; j++) { 2567 shape.lineTo(CirclePoints[j]); 2568 } 2569 } catch (Exception exc) { 2570 ErrorLogger.LogException(_className, "CalcCircleShape", 2571 new RendererException("Failed inside CalcCircleShape", exc)); 2572 } 2573 return shape; 2574 } 2575 2576 private static void GetSquallCurve(POINT2 StartPt, 2577 POINT2 EndPt, 2578 POINT2[] pSquallPts, 2579 int sign, 2580 double amplitude, 2581 int quantity) { 2582 try { 2583 double dist = CalcDistanceDouble(StartPt, EndPt); 2584 POINT2 ptTemp = new POINT2(); 2585 int j = 0; 2586 //end declarations 2587 2588 //get points along the horizontal segment between StartPt and EndPt2; 2589 for (j = 0; j < quantity; j++) { 2590 ptTemp = ExtendLineDouble(EndPt, StartPt, -dist * (double) j / (double) quantity); 2591 pSquallPts[j].x = ptTemp.x; 2592 //calculate the sin value along the x axis 2593 pSquallPts[j].y = ptTemp.y + amplitude * sign * Math.sin((double) j * 180 / (double) quantity * Math.PI / 180); 2594 } 2595 } catch (Exception exc) { 2596 ErrorLogger.LogException(_className, "GetSquallShape", 2597 new RendererException("Failed inside GeSquallShape", exc)); 2598 } 2599 } 2600 //caller needs to instantiate sign.value 2601 /** 2602 * Gets the squall curves for a line segment Assumes pSquallPts has been 2603 * allocated the proper number of points. 2604 * 2605 * @param StartPt segment start point 2606 * @param EndPt segment end point 2607 * @param pSquallPts OUT - the squall points 2608 * @param sign OUT - an object with a member to hold the starting curve sign 2609 * for the segment. 2610 * @param amplitude the sin curve amplitutde 2611 * @param quantity the number of points for each sin curve 2612 * @param length the desired length of the curve along the segment for each 2613 * sin curve 2614 * 2615 * @return segment squall points count 2616 */ 2617 protected static int GetSquallSegment(POINT2 StartPt, 2618 POINT2 EndPt, 2619 POINT2[] pSquallPts, 2620 ref<int[]> sign, 2621 double amplitude, 2622 int quantity, 2623 double length) { 2624 int counter = 0; 2625 try { 2626 POINT2 StartCurvePt, EndCurvePt; //use these for the curve points 2627 POINT2[] pSquallPts2 = new POINT2[quantity]; 2628 double dist = CalcDistanceDouble(StartPt, EndPt); 2629 int numCurves = (int) (dist / (double) length); 2630 int j = 0, k = 0; 2631 POINT2 EndPt2 = new POINT2(); 2632 double angle = Math.atan((StartPt.y - EndPt.y) / (StartPt.x - EndPt.x)); 2633 int lAngle = (int) ((180 / Math.PI) * angle); 2634 InitializePOINT2Array(pSquallPts2); 2635 //define EndPt2 to be the point dist from StartPt along the x axis 2636 if (StartPt.x < EndPt.x) { 2637 EndPt2.x = StartPt.x + dist; 2638 } else { 2639 EndPt2.x = StartPt.x - dist; 2640 } 2641 2642 EndPt2.y = StartPt.y; 2643 2644 EndCurvePt = StartPt; 2645 for (j = 0; j < numCurves; j++) { 2646 StartCurvePt = ExtendLineDouble(EndPt2, StartPt, -(double) (j * length)); 2647 EndCurvePt = ExtendLineDouble(EndPt2, StartPt, -(double) ((j + 1) * length)); 2648 2649 //get the curve points 2650 GetSquallCurve(StartCurvePt, EndCurvePt, pSquallPts2, sign.value[0], amplitude, quantity); 2651 2652 //fill the segment points with the curve points 2653 for (k = 0; k < quantity; k++) { 2654 //pSquallPts[counter].x=pSquallPts2[k].x; 2655 //pSquallPts[counter].y=pSquallPts2[k].y; 2656 pSquallPts[counter] = new POINT2(pSquallPts2[k]); 2657 counter++; 2658 } 2659 //reverse the sign 2660 2661 sign.value[0] = -sign.value[0]; 2662 } 2663 if (numCurves == 0) { 2664 pSquallPts[counter] = new POINT2(StartPt); 2665 counter++; 2666 pSquallPts[counter] = new POINT2(EndPt); 2667 counter++; 2668 } 2669 //the points are along the x axis. Rotate them about the first point as the origin 2670 RotateGeometryDoubleOrigin(pSquallPts, counter, lAngle); 2671 pSquallPts2 = null; 2672 } catch (Exception exc) { 2673 ErrorLogger.LogException(_className, "GetSquallSegment", 2674 new RendererException("Failed inside GetSquallSegment", exc)); 2675 } 2676 return counter; 2677 } 2678 2679 //temporarily using 2000 pixels 2680 private static int PointInBounds(POINT2 pt) { 2681 try { 2682 //double maxPixels=CELineArrayGlobals.MaxPixels2; 2683 double maxPixels = 100000;//was 2000 2684 if (Math.abs(pt.x) <= maxPixels && Math.abs(pt.y) <= maxPixels) { 2685 return 1; 2686 } else { 2687 return 0; 2688 } 2689 } catch (Exception exc) { 2690 ErrorLogger.LogException(_className, "PointInBounds", 2691 new RendererException("Failed inside PointInBounds", exc)); 2692 } 2693 return 1; 2694 } 2695 2696 /** 2697 * @param pt 2698 * @param ul 2699 * @param lr 2700 * @return 2701 */ 2702 private static int PointInBounds2(POINT2 pt, POINT2 ul, POINT2 lr) { 2703 try { 2704 double maxX = lr.x, minX = ul.x, maxY = lr.y, minY = ul.y; 2705 if (pt.x <= maxX && pt.x >= minX && pt.y <= maxY && pt.y >= minY) { 2706 return 1; 2707 } else { 2708 return 0; 2709 } 2710 } catch (Exception exc) { 2711 ErrorLogger.LogException(_className, "PointInBounds2", 2712 new RendererException("Failed inside PointInBounds2", exc)); 2713 } 2714 return 1; 2715 } 2716 2717 /** 2718 * Analyzes if line from pt0 to pt 1 intersects a side and returns the 2719 * intersection or null assumes pt0 to pt1 is not vertical. the caller will 2720 * replace pt0 with the intersection point if it is not null 2721 * 2722 * @param pt0 2723 * @param pt1 2724 * @param sidePt0 vertical or horizontal side first point 2725 * @param sidePt1 2726 * @return null if it does not intersect the side 2727 */ 2728 private static POINT2 intersectSegment(POINT2 pt0, POINT2 pt1, POINT2 sidePt0, POINT2 sidePt1) { 2729 POINT2 pt = null; 2730 try { 2731 if (pt0.x == pt1.x) { 2732 return null; 2733 } 2734 double m = (pt1.y - pt0.y) / (pt1.x - pt0.x); 2735 double dx = 0, dy = 0, x = 0, y = 0; 2736 POINT2 upper = null, lower = null, left = null, right = null; 2737 Boolean bolVertical = false; 2738 //the side is either vertical or horizontal 2739 if (sidePt0.x == sidePt1.x) //vertical side 2740 { 2741 bolVertical = true; 2742 if (sidePt0.y < sidePt1.y) { 2743 upper = sidePt0; 2744 lower = sidePt1; 2745 } else { 2746 upper = sidePt1; 2747 lower = sidePt0; 2748 } 2749 } else //horizontal side 2750 { 2751 if (sidePt0.x < sidePt1.x) { 2752 left = sidePt0; 2753 right = sidePt1; 2754 } else { 2755 left = sidePt1; 2756 right = sidePt0; 2757 } 2758 } 2759 //travel in the direction from pt0 to pt1 to find the pt0 intersect 2760 if (bolVertical) { //the side to intersect is vertical 2761 dx = upper.x - pt0.x; 2762 dy = m * dx; 2763 x = upper.x; 2764 y = pt0.y + dy; 2765 //the potential intersection point 2766 pt = new POINT2(x, y); 2767 2768 if (pt0.x <= pt.x && pt.x <= pt1.x) //left to right 2769 { 2770 if (upper.y <= pt.y && pt.y <= lower.y) { 2771 return pt; 2772 } 2773 } else if (pt0.x >= pt.x && pt.x >= pt1.x) //right to left 2774 { 2775 if (upper.y <= pt.y && pt.y <= lower.y) { 2776 return pt; 2777 } 2778 } 2779 } else //horizontal side 2780 { 2781 dy = left.y - pt0.y; 2782 dx = dy / m; 2783 x = pt0.x + dx; 2784 y = left.y; 2785 //the potential intersection point 2786 pt = new POINT2(x, y); 2787 2788 if (pt0.y <= pt.y && pt.y <= pt1.y) { 2789 if (left.x <= pt.x && pt.x <= right.x) { 2790 return pt; 2791 } 2792 } else if (pt0.y >= pt.y && pt.y >= pt1.y) { 2793 if (left.x <= pt.x && pt.x <= right.x) { 2794 return pt; 2795 } 2796 } 2797 } 2798 } catch (Exception exc) { 2799 ErrorLogger.LogException(_className, "intersectSegment", 2800 new RendererException("Failed inside intersectSegment", exc)); 2801 } 2802 return null; 2803 } 2804 2805 /** 2806 * side 1 ----- | | side 0 | | side 2 | | ------ side 3 bounds one segment 2807 * for autoshapes that need it: bydif, fordif, fix, mnfldfix if null is 2808 * returned the client should conect the original line points (i.e. no 2809 * jaggies) 2810 * 2811 * @param pt0 2812 * @param pt1 2813 * @param ul 2814 * @param lr 2815 * @return bounded segment or null 2816 */ 2817 public static POINT2[] BoundOneSegment(POINT2 pt0, POINT2 pt1, POINT2 ul, POINT2 lr) { 2818 POINT2[] line = new POINT2[2]; 2819 try { 2820 if (pt0.y < ul.y && pt1.y < ul.y) { 2821 return null; 2822 } 2823 if (pt0.y > lr.y && pt1.y > lr.y) { 2824 return null; 2825 } 2826 if (pt0.x < ul.x && pt1.x < ul.x) { 2827 return null; 2828 } 2829 if (pt0.x > lr.x && pt1.x > lr.x) { 2830 return null; 2831 } 2832 2833 Boolean bolVertical = false; 2834 InitializePOINT2Array(line); 2835 if (pt0.x == pt1.x) { 2836 bolVertical = true; 2837 } 2838 2839 if (bolVertical) { 2840 line[0] = new POINT2(pt0); 2841 if (line[0].y < ul.y) { 2842 line[0].y = ul.y; 2843 } 2844 if (line[0].y > lr.y) { 2845 line[0].y = lr.y; 2846 } 2847 2848 line[1] = new POINT2(pt1); 2849 if (line[1].y < ul.y) { 2850 line[1].y = ul.y; 2851 } 2852 if (line[1].y > lr.y) { 2853 line[1].y = lr.y; 2854 } 2855 2856 return line; 2857 } 2858 2859 double dx = 0, dy = 0, x = 0, y = 0; 2860 double m = (pt1.y - pt0.y) / (pt1.x - pt0.x); 2861 Boolean side0Intersect = false, 2862 side1Intersect = false, 2863 side2Intersect = false, 2864 side3Intersect = false; 2865 //travel in the direction from pt0 to pt1 to find pt0 intersect 2866 POINT2 ur = new POINT2(lr.x, ul.y); 2867 POINT2 ll = new POINT2(ul.x, lr.y); 2868 2869 POINT2 pt0Intersect = null; 2870 if (PointInBounds2(pt0, ul, lr) == 1) { 2871 pt0Intersect = pt0; 2872 } 2873 if (pt0Intersect == null) { 2874 pt0Intersect = intersectSegment(pt0, pt1, ll, ul); //interesect side 0 2875 side0Intersect = true; 2876 } 2877 if (pt0Intersect == null) { 2878 pt0Intersect = intersectSegment(pt0, pt1, ul, ur); //interesect side 1 2879 side1Intersect = true; 2880 } 2881 if (pt0Intersect == null) { 2882 pt0Intersect = intersectSegment(pt0, pt1, ur, lr); //interesect side 2 2883 side2Intersect = true; 2884 } 2885 if (pt0Intersect == null) { 2886 pt0Intersect = intersectSegment(pt0, pt1, ll, lr); //interesect side 3 2887 side3Intersect = true; 2888 } 2889 2890 //travel in the direction from pt1 to pt0 to find pt1 intersect 2891 POINT2 pt1Intersect = null; 2892 if (PointInBounds2(pt1, ul, lr) == 1) { 2893 pt1Intersect = pt1; 2894 } 2895 if (pt1Intersect == null && side0Intersect == false) { 2896 pt1Intersect = intersectSegment(pt1, pt0, ll, ul); //interesect side 0 2897 } 2898 if (pt1Intersect == null && side1Intersect == false) { 2899 pt1Intersect = intersectSegment(pt1, pt0, ul, ur); //interesect side 1 2900 } 2901 if (pt1Intersect == null && side2Intersect == false) { 2902 pt1Intersect = intersectSegment(pt1, pt0, ur, lr); //interesect side 2 2903 } 2904 if (pt1Intersect == null && side3Intersect == false) { 2905 pt1Intersect = intersectSegment(pt1, pt0, ll, lr); //interesect side 3 2906 } 2907 2908 if (pt0Intersect != null && pt1Intersect != null) { 2909 line[0] = pt0Intersect; 2910 line[1] = pt1Intersect; 2911 //return line; 2912 } else { 2913 line = null; 2914 } 2915 } catch (Exception exc) { 2916 ErrorLogger.LogException(_className, "BoundOneSegment", 2917 new RendererException("Failed inside BoundOneSegment", exc)); 2918 } 2919 return line; 2920 } 2921 2922 private static int DisplayIntersectPixels(POINT2 pt0, 2923 POINT2 pt1, 2924 ref<double[]> pt2x, 2925 ref<double[]> pt2y, 2926 ref<double[]> pt3x, 2927 ref<double[]> pt3y) //POINT2 ul, 2928 //POINT2 lr) 2929 { 2930 int nResult = -1; 2931 try { 2932 //declarations 2933 double X = 0, Y = 0; 2934 ref<double[]> m = new ref(); 2935 //double maxPixels=CELineArrayGlobals.MaxPixels2; 2936 double maxPixels = 2000; 2937 //double maxX=lr.x,minX=ul.x,maxY=lr.y,minY=ul.y; 2938 2939 int bol0Inside = 0, bol1Inside = 0; 2940 int bolVertical = CalcTrueSlopeDouble(pt0, pt1, m); 2941 double b = pt0.y - m.value[0] * pt0.x; //the y intercept for the segment line 2942 POINT2 pt2, pt3; 2943 //end declarations 2944 2945 pt2x.value = new double[1]; 2946 pt2y.value = new double[1]; 2947 pt3x.value = new double[1]; 2948 pt3y.value = new double[1]; 2949 pt2 = new POINT2(pt0); 2950 pt3 = new POINT2(pt1); 2951 2952 //diagnostic 2953 if (pt0.x <= maxPixels && pt0.x >= -maxPixels 2954 && pt0.y <= maxPixels && pt0.y >= -maxPixels) { 2955 bol0Inside = 1; 2956 } 2957 if (pt1.x <= maxPixels && pt1.x >= -maxPixels 2958 && pt1.y <= maxPixels && pt1.y >= -maxPixels) { 2959 bol1Inside = 1; 2960 } 2961 //if both points are inside the area then use the whole segment 2962 if (bol0Inside == 1 && bol1Inside == 1) { 2963 return 0; 2964 } 2965 //if at leat one of the points is inside the area then use some of the segment 2966 if (bol0Inside == 1 || bol1Inside == 1) { 2967 nResult = 1; 2968 } 2969 2970 //segment is not vertical 2971 if (bolVertical != 0) { 2972 //analysis for side 0, get the intersection for either point if it exists 2973 //diagnostic 2974 X = -maxPixels; 2975 //X=minX; 2976 2977 Y = m.value[0] * X + b; 2978 if (pt0.x < -maxPixels && -maxPixels < pt1.x) //pt0 is outside the area 2979 { 2980 if (-maxPixels <= Y && Y <= maxPixels) //intersection is on side 0 2981 //if(minY<=Y && Y<=maxY) //intersection is on side 0 2982 { 2983 pt2.x = X; 2984 pt2.y = Y; 2985 nResult = 1; //use at least some of the pixels 2986 } 2987 } 2988 if (pt1.x < -maxPixels && -maxPixels < pt0.x) //pt1 is outside the area 2989 //if(pt1.x<minX && minX<pt0.x) //pt1 is outside the area 2990 { 2991 if (-maxPixels <= Y && Y <= maxPixels) //intersection is on side 0 2992 { 2993 pt3.x = X; 2994 pt3.y = Y; 2995 nResult = 1; //use at least some of the pixels 2996 } 2997 } 2998 2999 //analysis for side 1, get the intersection for either point if it exists 3000 Y = -maxPixels; 3001 if (m.value[0] != 0) { 3002 X = (Y - b) / m.value[0]; 3003 if (pt0.y < -maxPixels && -maxPixels < pt1.y) //pt0 is outside the area 3004 { 3005 if (-maxPixels <= X && X <= maxPixels) //intersection is on side 1 3006 { 3007 pt2.x = X; 3008 pt2.y = Y; 3009 nResult = 1; //use at least some of the pixels 3010 } 3011 } 3012 if (pt1.y <= -maxPixels && -maxPixels <= pt0.y) //pt1 is outside the area 3013 { 3014 if (-maxPixels < X && X < maxPixels) //intersection is on the boundary 3015 { 3016 pt3.x = X; 3017 pt3.y = Y; 3018 nResult = 1; //use at least some of the pixels 3019 } 3020 } 3021 } 3022 //analysis for side 2, get the intersection for either point if it exists 3023 X = maxPixels; 3024 Y = m.value[0] * X + b; 3025 if (pt0.x < maxPixels && maxPixels < pt1.x) //pt1 is outside the area 3026 { 3027 if (-maxPixels <= Y && Y <= maxPixels) //intersection is on the boundary 3028 { 3029 pt3.x = X; 3030 pt3.y = Y; 3031 nResult = 1; //use at least some of the pixels 3032 } 3033 } 3034 if (pt1.x < maxPixels && maxPixels < pt0.x) //pt0 is outside the area 3035 { 3036 if (-maxPixels <= Y && Y <= maxPixels) //intersection is on the boundary 3037 { 3038 pt2.x = X; 3039 pt2.y = Y; 3040 nResult = 1; //use at least some of the pixels 3041 } 3042 } 3043 3044 //analysis for side 3, get the intersection for either point if it exists 3045 Y = maxPixels; 3046 if (m.value[0] != 0) { 3047 X = (Y - b) / m.value[0]; 3048 if (pt0.y < maxPixels && maxPixels < pt1.y) //pt1 is outside the area 3049 { 3050 if (-maxPixels <= X && X <= maxPixels) //intersection is on the boundary 3051 { 3052 pt3.x = X; 3053 pt3.y = Y; 3054 nResult = 1; //use at least some of the pixels 3055 } 3056 } 3057 if (pt1.y < maxPixels && maxPixels < pt0.y) //pt0 is outside the area 3058 { 3059 if (-maxPixels <= X && X <= maxPixels) //intersection is on the boundary 3060 { 3061 pt2.x = X; 3062 pt2.y = Y; 3063 nResult = 1; //use at least some of the pixels 3064 } 3065 } 3066 } 3067 } 3068 3069 //segment is vertical 3070 if (bolVertical == 0) { 3071 //analysis for side 1 3072 X = pt0.x; 3073 Y = -maxPixels; 3074 if (-maxPixels < pt0.x && pt0.x < maxPixels) { 3075 if (pt0.y <= -maxPixels && -maxPixels <= pt1.y) //pt0 outside the area 3076 { 3077 pt2.x = X; 3078 pt2.y = Y; 3079 nResult = 1; //use at least some of the pixels 3080 } 3081 if (pt1.y <= -maxPixels && -maxPixels <= pt0.y) //pt1 outside the area 3082 { 3083 pt3.x = X; 3084 pt3.y = Y; 3085 nResult = 1; //use at least some of the pixels 3086 } 3087 } 3088 3089 //analysis for side 3 3090 X = pt0.x; 3091 Y = maxPixels; 3092 if (-maxPixels < pt0.x && pt0.x < maxPixels) { 3093 if (pt0.y <= maxPixels && maxPixels <= pt1.y) //pt1 outside the area 3094 { 3095 pt3.x = X; 3096 pt3.y = Y; 3097 nResult = 1; //use at least some of the pixels 3098 } 3099 if (pt1.y <= maxPixels && maxPixels <= pt0.y) //pt0 outside the area 3100 { 3101 pt2.x = X; 3102 pt2.y = Y; 3103 nResult = 1; //use at least some of the pixels 3104 } 3105 } 3106 } 3107 3108 pt2x.value[0] = pt2.x; 3109 pt2y.value[0] = pt2.y; 3110 pt3x.value[0] = pt3.x; 3111 pt3y.value[0] = pt3.y; 3112 } catch (Exception exc) { 3113 ErrorLogger.LogException(_className, "DisplayIntersectPixels", 3114 new RendererException("Failed inside DisplayIntersectPixels", exc)); 3115 } 3116 return nResult; 3117 } 3118 /** 3119 * Computes Ditch spikes for the ATDITCH line types. This function uses 3120 * linestyles provided by the caller to skip segments. 3121 * 3122 * @param pLinePoints OUT - the client points also used for the return 3123 * points 3124 * @param nOldCounter the number of client points 3125 * @param bWayIs the parallel line to use (0) for inner or outer spikes 3126 * @param linetype the line type 3127 * 3128 * @return the symbol point count 3129 */ 3130 protected static int GetDitchSpikeDouble(TGLight tg, POINT2[] pLinePoints, 3131 int nOldCounter, 3132 int bWayIs) { 3133 int nSpikeCounter = 0; 3134 try { 3135 //declarations 3136 int linetype = tg.get_LineType(); 3137 int nNumberOfSegments = 0, 3138 lCircleCounter = 0, 3139 bolVertical = 0, 3140 nTemp = 0, 3141 i, 3142 j; 3143 double dPrinter = 1.0; 3144 double dIntLocation1x = 0, 3145 dIntLocation2x = 0, 3146 dIntLocation1y = 0, 3147 dIntLocation2y = 0, 3148 r = 0, 3149 s = 0, 3150 use = 0, 3151 length = 0, 3152 k = 0, 3153 bint = 0; 3154 ref<double[]> pdAnswer = new ref();//new double[6]; 3155 ref<double[]> m = new ref(); 3156 3157 POINT2 UpperLinePoint = new POINT2(pLinePoints[0]), 3158 Lower1LinePoint = new POINT2(pLinePoints[0]), 3159 Lower2LinePoint = new POINT2(pLinePoints[0]), 3160 a = new POINT2(pLinePoints[0]), 3161 b = new POINT2(pLinePoints[0]); 3162 POINT2[] pCirclePoints = new POINT2[pLinePoints.length]; 3163 POINT2 averagePoint = new POINT2(); 3164 POINT2 lastAveragePoint = new POINT2(); 3165 POINT2[] pTempLinePoints = null; 3166 //end declarations 3167 3168 pTempLinePoints = new POINT2[nOldCounter]; 3169 for (j = 0; j < nOldCounter; j++) { 3170 pTempLinePoints[j] = new POINT2(pLinePoints[j]); 3171 } 3172 3173 ArrayList<POINT2> basePoints = new ArrayList(); 3174 3175 InitializePOINT2Array(pCirclePoints); 3176 nSpikeCounter = nOldCounter; 3177 double spikeLength = arraysupport.getScaledSize(12, tg.get_LineThickness(), tg.get_patternScale()); 3178 double spikeHeight = spikeLength * 1.25; 3179 double minLength = 2 * spikeLength; 3180 for (i = 0; i < nOldCounter - 1; i++) { 3181 if (linetype == TacticalLines.ATDITCHM && i == 0) { 3182 double radius = arraysupport.getScaledSize(4, tg.get_LineThickness(), tg.get_patternScale()); 3183 minLength = spikeLength * 2.5 + radius * 2; 3184 } 3185 3186 nTemp = CalcTrueLinesDouble((long) (spikeHeight * dPrinter), pLinePoints[i], pLinePoints[i + 1], pdAnswer); 3187 r = pdAnswer.value[3]; 3188 s = pdAnswer.value[5]; 3189 length = CalcDistanceDouble(pLinePoints[i], pLinePoints[i + 1]); 3190 bolVertical = CalcTrueSlopeDouble(pLinePoints[i], pLinePoints[i + 1], m); 3191 nNumberOfSegments = (int) ((length - 1) / (spikeLength * dPrinter)); 3192 3193 if (length > minLength * dPrinter) { //minLength was 24 3194 if (bWayIs != 0) { 3195 if (pLinePoints[i].x <= pLinePoints[i + 1].x) { 3196 use = r; 3197 } 3198 if (pLinePoints[i].x >= pLinePoints[i + 1].x) { 3199 use = s; 3200 } 3201 } //end if 3202 else { 3203 if (pLinePoints[i].x <= pLinePoints[i + 1].x) { 3204 use = s; 3205 } 3206 if (pLinePoints[i].x >= pLinePoints[i + 1].x) { 3207 use = r; 3208 } 3209 } //end else 3210 3211 for (j = 1; j <= nNumberOfSegments; j++) { 3212 k = (double) j; 3213 a = new POINT2(pLinePoints[i]); 3214 b = new POINT2(pLinePoints[i + 1]); 3215 3216 if (j > 1) { 3217 dIntLocation1x = dIntLocation2x; 3218 } else { 3219 dIntLocation1x 3220 = (double) pLinePoints[i].x + ((k * spikeLength - spikeLength) * dPrinter / length) 3221 * (double) (pLinePoints[i + 1].x - pLinePoints[i].x); 3222 } 3223 3224 if (j > 1) //added M. Deutch 2-23-99 3225 { 3226 dIntLocation1y = dIntLocation2y; 3227 } else { 3228 dIntLocation1y 3229 = (double) pLinePoints[i].y + ((k * spikeLength - spikeLength / 2) * dPrinter / length) 3230 * (double) (pLinePoints[i + 1].y - pLinePoints[i].y); 3231 } 3232 3233 dIntLocation2x = (double) pLinePoints[i].x 3234 + ((k * spikeLength + spikeLength / 2) * dPrinter / length) 3235 * (double) (pLinePoints[i + 1].x 3236 - pLinePoints[i].x); 3237 3238 dIntLocation2y = (double) pLinePoints[i].y 3239 + ((k * spikeLength + spikeLength / 2) * dPrinter / length) 3240 * (double) (pLinePoints[i + 1].y 3241 - pLinePoints[i].y); 3242 3243 if (m.value[0] != 0 && bolVertical != 0) { 3244 bint = (dIntLocation1y + dIntLocation2y) / 2.0 3245 + (1 / m.value[0]) * (dIntLocation1x + dIntLocation2x) / 2.0; 3246 //independent of direction 3247 UpperLinePoint = CalcTrueIntersectDouble2(m.value[0], use, -1 / m.value[0], bint, 1, 1, pLinePoints[0].x, pLinePoints[0].y); 3248 } 3249 3250 if (bolVertical == 0) //vertical segment 3251 { 3252 if (dIntLocation1y < dIntLocation2y) { 3253 UpperLinePoint.y = (int) dIntLocation1y + (int) (length / nNumberOfSegments / 2); 3254 } else { 3255 UpperLinePoint.y = (int) dIntLocation1y - (int) (length / nNumberOfSegments / 2); 3256 } 3257 if (pLinePoints[i].y < pLinePoints[i + 1].y) { 3258 UpperLinePoint.x = (int) dIntLocation1x + (int) (length / nNumberOfSegments); 3259 } else { 3260 UpperLinePoint.x = (int) dIntLocation1x - (int) (length / nNumberOfSegments); 3261 } 3262 } 3263 if (m.value[0] == 0 && bolVertical != 0) { 3264 if (dIntLocation1x < dIntLocation2x) { 3265 UpperLinePoint.x = (int) dIntLocation1x + (int) (length / nNumberOfSegments / 2); 3266 } else { 3267 UpperLinePoint.x = (int) dIntLocation1x - (int) (length / nNumberOfSegments / 2); 3268 } 3269 if (pLinePoints[i + 1].x < pLinePoints[i].x) { 3270 UpperLinePoint.y = (int) dIntLocation1y + (int) (length / nNumberOfSegments); 3271 } else { 3272 UpperLinePoint.y = (int) dIntLocation1y - (int) (length / nNumberOfSegments); 3273 } 3274 } 3275 //end section 3276 3277 Lower1LinePoint.x = dIntLocation1x; 3278 Lower1LinePoint.y = dIntLocation1y; 3279 Lower2LinePoint.x = dIntLocation2x; 3280 Lower2LinePoint.y = dIntLocation2y; 3281 3282 pLinePoints[nSpikeCounter] = new POINT2(Lower1LinePoint); 3283 if (linetype == TacticalLines.ATDITCHC || linetype == TacticalLines.ATDITCHM) { 3284 pLinePoints[nSpikeCounter].style = 9; 3285 } 3286 if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13 3287 { 3288 pLinePoints[nSpikeCounter].style = 5; 3289 } 3290 3291 nSpikeCounter++; 3292 3293 pLinePoints[nSpikeCounter] = new POINT2(UpperLinePoint); 3294 if (linetype == (long) TacticalLines.ATDITCHC || linetype == (long) TacticalLines.ATDITCHM) { 3295 pLinePoints[nSpikeCounter].style = 9; 3296 } 3297 if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13 3298 { 3299 pLinePoints[nSpikeCounter].style = 5; 3300 } 3301 3302 nSpikeCounter++; 3303 3304 pLinePoints[nSpikeCounter] = new POINT2(Lower2LinePoint); 3305 if (linetype == (long) TacticalLines.ATDITCHC || linetype == (long) TacticalLines.ATDITCHM) { 3306 pLinePoints[nSpikeCounter].style = 10; 3307 } 3308 if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13 3309 { 3310 pLinePoints[nSpikeCounter].style = 5; 3311 } 3312 3313 nSpikeCounter++; 3314 3315 if (linetype == TacticalLines.ATDITCHM) { 3316 if (j % 2 == 0) { 3317 averagePoint = lineutility.MidPointDouble(Lower1LinePoint, Lower2LinePoint, 0); 3318 averagePoint = lineutility.MidPointDouble(averagePoint, UpperLinePoint, 0); 3319 } else if (j == 1) { 3320 averagePoint = lineutility.ExtendLineDouble(Lower2LinePoint, Lower1LinePoint, 5); 3321 averagePoint = lineutility.MidPointDouble(averagePoint, UpperLinePoint, 0); 3322 } 3323 } 3324 //end section 3325 if (j > 1 && j < nNumberOfSegments) { 3326 basePoints.add(new POINT2(Lower1LinePoint)); 3327 //if(j==nNumberOfSegments-1) 3328 // basePoints.get(basePoints.size()-1).style=5; 3329 } else if (j == 1) { 3330 basePoints.add(new POINT2(pLinePoints[i])); 3331 } else if (j == nNumberOfSegments) { 3332 basePoints.add(new POINT2(pLinePoints[i + 1])); 3333 basePoints.get(basePoints.size() - 1).style = 5; 3334 } 3335 if (linetype == TacticalLines.ATDITCHM && j > 1) { 3336 if (j % 2 == 0) { 3337 pCirclePoints[lCircleCounter] = lineutility.MidPointDouble(averagePoint, lastAveragePoint, 20); 3338 lCircleCounter++; 3339 } 3340 //end section 3341 } 3342 if (j < nNumberOfSegments && linetype == TacticalLines.ATDITCHM) { 3343 if (j == 1 || j % 2 == 0) { 3344 //LastUpperLinePoint = new POINT2(UpperLinePoint); 3345 lastAveragePoint = new POINT2(averagePoint); 3346 } 3347 //end section 3348 } 3349 }//end for j<numberOfsegments 3350 } //end if length big enough 3351 else { 3352 //diagnostic 3353 pLinePoints[nSpikeCounter].x = pLinePoints[i].x; 3354 pLinePoints[nSpikeCounter].y = pLinePoints[i].y; 3355 pLinePoints[nSpikeCounter].style = 0; 3356 nSpikeCounter++; 3357 pLinePoints[nSpikeCounter].x = pLinePoints[i + 1].x; 3358 pLinePoints[nSpikeCounter].y = pLinePoints[i + 1].y; 3359 pLinePoints[nSpikeCounter].style = 5; 3360 nSpikeCounter++; 3361 } 3362 } 3363 3364 for (j = 0; j < nOldCounter; j++) //reverse the first nOldCounter points for 3365 { 3366 pLinePoints[j] = new POINT2(pTempLinePoints[nOldCounter - j - 1]); //purpose of drawing 3367 pLinePoints[j].style = 5; 3368 } 3369 3370 if (pLinePoints[nSpikeCounter - 1].style == 0) { 3371 pLinePoints[nSpikeCounter - 1].style = 5; 3372 } 3373 int t=basePoints.size(); 3374 //for (j = nSpikeCounter; j < nSpikeCounter + basePoints.size(); j++) 3375 for (j = nSpikeCounter; j < nSpikeCounter + t; j++) 3376 { 3377 pLinePoints[j] = new POINT2(basePoints.get(j - nSpikeCounter)); 3378 //if(linetype == TacticalLines.ATDITCHM && pLinePoints[j].style != 5) 3379 if (pLinePoints[j].style != 5) { 3380 pLinePoints[j].style = 0; 3381 } 3382 } 3383 nSpikeCounter += basePoints.size(); 3384 3385 if (linetype == (int) TacticalLines.ATDITCHM) { 3386 pLinePoints[nSpikeCounter - 1].style = 5;//was 10 3387 for (j = nSpikeCounter; j < nSpikeCounter + lCircleCounter; j++) { 3388 pLinePoints[j] = new POINT2(pCirclePoints[j - nSpikeCounter]); 3389 pLinePoints[j].style = 20; 3390 } 3391 nSpikeCounter += lCircleCounter; 3392 } 3393 3394 } catch (Exception exc) { 3395 ErrorLogger.LogException(_className, "GetDitchSpikeDouble", 3396 new RendererException("Failed inside GetDitchSpikeDouble", exc)); 3397 } 3398 return nSpikeCounter; 3399 } 3400 3401 /** 3402 * Moves pixels if points are identical, used for the channel types 3403 * 3404 * @param pLinePoints OUT - client points also for returned points 3405 */ 3406 protected static void MoveChannelPixels(POINT2[] pLinePoints) { 3407 try { 3408 if (pLinePoints == null || pLinePoints.length <= 0) { 3409 return; 3410 } 3411 3412 double[] pixels = new double[pLinePoints.length * 2]; 3413 boolean bolNoRepeats; 3414 int j, k = 0; 3415 double x1; 3416 double y1; 3417 double x2; 3418 double y2; 3419 int count = pLinePoints.length; 3420 //stuff pixels 3421 for (j = 0; j < count; j++) { 3422 pixels[k++] = pLinePoints[j].x; 3423 pixels[k++] = pLinePoints[j].y; 3424 } 3425 3426 bolNoRepeats = false; 3427 do { 3428 bolNoRepeats = true; 3429 for (j = 0; j < count - 1; j++) { 3430 x1 = pixels[2 * j]; 3431 y1 = pixels[2 * j + 1]; 3432 x2 = pixels[2 * j + 2]; 3433 y2 = pixels[2 * j + 3]; 3434 if (x1 == x2 && y1 == y2) //it's the same point 3435 { 3436 bolNoRepeats = false; 3437 pixels[2 * j + 2] = (long) x2 + 1; //move the point 3438 break; 3439 } 3440 } 3441 } while (bolNoRepeats == false); 3442 //stuff pLinePoints 3443 k = 0; 3444 for (j = 0; j < count; j++) { 3445 pLinePoints[j].x = pixels[k++]; 3446 pLinePoints[j].y = pixels[k++]; 3447 } 3448 } catch (Exception exc) { 3449 ErrorLogger.LogException(_className, "MoveChannelPixels", 3450 new RendererException("Failed inside MoveChannelPixels", exc)); 3451 } 3452 } 3453 3454 /** 3455 * Single Concertina cannot have horizontal first segment 3456 * 3457 * @param linetype 3458 * @param pLinePoints 3459 */ 3460 protected static void moveSingleCPixels(int linetype, POINT2[] pLinePoints) { 3461 try { 3462 switch (linetype) { 3463 case TacticalLines.SINGLEC: 3464 break; 3465 default: 3466 return; 3467 } 3468 if (pLinePoints.length > 1) { 3469 if (pLinePoints[1].y == pLinePoints[0].y) { 3470 pLinePoints[1].y++; 3471 } 3472 } 3473 } catch (Exception exc) { 3474 ErrorLogger.LogException(_className, "MoveSingleCPixels", 3475 new RendererException("Failed inside MoveSingleCPixels", exc)); 3476 } 3477 } 3478 3479 /** 3480 * Rotates an the first vblCounter points in the array about its first point 3481 * 3482 * @param pLinePoints OUT - the points to rotate 3483 * @param vblCounter the number of points to rotate 3484 * @param lAngle the angle in degrees to rotate 3485 */ 3486 protected static void RotateGeometryDouble(POINT2[] pLinePoints, 3487 int vblCounter, 3488 double lAngle) { 3489 try { 3490 int j = 0; 3491 double dRotate = 0, 3492 dTheta = 0, 3493 dGamma = 0, 3494 x = 0, 3495 y = 0; 3496 3497 if (lAngle != 0) //if the angle is 0 no rotation occurs 3498 { 3499 POINT2 pdCenter; 3500 dRotate = lAngle * Math.PI / 180d; 3501 pdCenter = CalcCenterPointDouble(pLinePoints, vblCounter); 3502 3503 for (j = 0; j < vblCounter; j++) { 3504 //added if/else to get rid of divide by zero error 5/12/04 M. Deutch 3505 if (pLinePoints[j].x == pdCenter.x) { 3506 if ((pLinePoints[j].y > pdCenter.y)) { 3507 dGamma = Math.PI + Math.PI / 2; 3508 } else { 3509 dGamma = Math.PI / 2; 3510 } 3511 } else { 3512 dGamma = Math.PI + Math.atan((pLinePoints[j].y - pdCenter.y) 3513 / (pLinePoints[j].x - pdCenter.x)); 3514 } 3515 3516 if ((double) pLinePoints[j].x >= pdCenter.x) { 3517 dGamma = dGamma + Math.PI; 3518 } 3519 3520 dTheta = dRotate + dGamma; 3521 y = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.sin(dTheta); 3522 x = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.cos(dTheta); 3523 pLinePoints[j].y = pdCenter.y + y; 3524 pLinePoints[j].x = pdCenter.x + x; 3525 } //end for 3526 3527 return; 3528 } //end if 3529 } catch (Exception exc) { 3530 ErrorLogger.LogException(_className, "RotateGeometryDouble", 3531 new RendererException("Failed inside RotateGeometryDouble", exc)); 3532 } 3533 } // end 3534 3535 /** 3536 * Returns the point on line (pt0 to pt1) closest to ptRelative 3537 * 3538 * @param pt0 the first point on line 3539 * @param pt1 the second point on line 3540 * @param ptRelative the second point on line 3541 * @return the point closest to ptRelative on the line 3542 */ 3543 public static POINT2 ClosestPointOnLine(POINT2 pt0, POINT2 pt1, POINT2 ptRelative) { 3544 if (pt0.x == ptRelative.x && pt0.y == ptRelative.y) 3545 return new POINT2(pt0); 3546 else if (pt1.x == ptRelative.x && pt1.y == ptRelative.y) 3547 return new POINT2(pt1); 3548 else if (pt0.x == pt1.x && pt0.y == pt1.y) 3549 return new POINT2(pt0); 3550 3551 POINT2 atob = new POINT2(pt1.x - pt0.x, pt1.y - pt0.y ); 3552 POINT2 atop = new POINT2(ptRelative.x - pt0.x, ptRelative.y - pt0.y ); 3553 double len = atob.x * atob.x + atob.y * atob.y; 3554 double dot = atop.x * atob.x + atop.y * atob.y; 3555 double t = Math.min( 1, Math.max( 0, dot / len ) ); 3556 3557 return new POINT2(pt0.x + atob.x * t, pt0.y + atob.y * t); 3558 } 3559 3560 /** 3561 * Returns the intersection between two line segments or null if it doesn't exist 3562 * 3563 * @param pt1 3564 * @param pt2 3565 * @param pt3 3566 * @param pt4 3567 * @return 3568 */ 3569 private static POINT2 getIntersectionPoint(POINT2 pt1, POINT2 pt2, POINT2 pt3, POINT2 pt4) { 3570 double denom = (pt4.y - pt3.y) * (pt2.x - pt1.x) - (pt4.x - pt3.x) * (pt2.y - pt1.y); 3571 3572 if (denom == 0.0) { // Lines are parallel or collinear 3573 return null; 3574 } 3575 3576 double ua = ((pt4.x - pt3.x) * (pt1.y - pt3.y) - (pt4.y - pt3.y) * (pt1.x - pt3.x)) / denom; 3577 double ub = ((pt2.x - pt1.x) * (pt1.y - pt3.y) - (pt2.y - pt1.y) * (pt1.x - pt3.x)) / denom; 3578 3579 if (ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0) { 3580 // Intersection point lies within both segments 3581 double intersectX = pt1.x + ua * (pt2.x - pt1.x); 3582 double intersectY = pt1.y + ua * (pt2.y - pt1.y); 3583 return new POINT2(intersectX, intersectY); 3584 } 3585 3586 return null; // Segments do not intersect 3587 } 3588 3589 /** 3590 * Returns the intersection between a polygon and a line or null if it doesn't exist 3591 * 3592 * @param polyPts 3593 * @param pt0 3594 * @param pt1 3595 * @return 3596 */ 3597 public static POINT2 intersectPolygon(POINT2[] polyPts, POINT2 pt0, POINT2 pt1) { 3598 for (int i = 0; i < polyPts.length; i++) { 3599 POINT2 temp = getIntersectionPoint(polyPts[i], polyPts[(i + 1) % polyPts.length], pt0, pt1); 3600 if (temp != null) return temp; 3601 } 3602 return null; 3603 } 3604 3605 /** 3606 * Returns the point perpendicular to the line (pt0 to pt1) at the midpoint 3607 * the same distance from (and on the same side of) the the line as 3608 * ptRelative. 3609 * 3610 * @param pt0 the first point 3611 * @param pt1 the second point 3612 * @param ptRelative the point to use for computing the return point 3613 * 3614 * @return the point perpendicular to the line at the midpoint 3615 */ 3616 protected static POINT2 PointRelativeToLine(POINT2 pt0, 3617 POINT2 pt1, 3618 POINT2 ptRelative) { 3619 POINT2 ptResult = new POINT2(pt0); 3620 try { 3621 int bolVertical = 0; 3622 ref<double[]> m = new ref(); 3623 POINT2 midPt = MidPointDouble(pt0, pt1, 0); 3624 double b1 = 0, b2 = 0; 3625 //end declarations 3626 3627 bolVertical = CalcTrueSlopeDouble(pt0, pt1, m); 3628 if (bolVertical == 0) //line is vertical 3629 { 3630 ptResult.x = ptRelative.x; 3631 ptResult.y = midPt.y; 3632 } 3633 if (bolVertical != 0 && m.value[0] == 0) { 3634 ptResult.x = midPt.x; 3635 ptResult.y = ptRelative.y; 3636 } 3637 if (bolVertical != 0 && m.value[0] != 0) { 3638 b1 = midPt.y + (1 / m.value[0]) * midPt.x; //the line perp to midPt 3639 b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line ptRelative with the slope of pt1-pt2 3640 ptResult = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0); 3641 } 3642 } catch (Exception exc) { 3643 ErrorLogger.LogException(_className, "PointRelativeToLine", 3644 new RendererException("Failed inside PointRelativeToLine", exc)); 3645 } 3646 return ptResult; 3647 } 3648 3649 /** 3650 * shift the control point to match the shift that occurs in 3651 * Channels.GetAXADDouble for CATKBYFIRE. This is because the rotary feature 3652 * arrow tip must align with the anchor point 3653 * 3654 * @param linetype 3655 * @param pLinePoints the anchor points including the control point 3656 * @param dist the minimum required distance from the front of the rotary 3657 * arrow 3658 */ 3659 public static void adjustCATKBYFIREControlPoint(int linetype, 3660 ArrayList<POINT2> pLinePoints, 3661 double dist) { 3662 try { 3663 if (linetype != TacticalLines.CATKBYFIRE) { 3664 return; 3665 } 3666 3667 double dist2 = lineutility.CalcDistanceDouble(pLinePoints.get(0), pLinePoints.get(1)); 3668 if (dist2 <= dist) { 3669 return; 3670 } 3671 3672 POINT2 pt = null; 3673 int count = pLinePoints.size(); 3674 POINT2 pt0 = new POINT2(pLinePoints.get(0)); 3675 POINT2 pt1 = new POINT2(pLinePoints.get(1)); 3676 POINT2 controlPt = new POINT2(pLinePoints.get(count - 1)); 3677 POINT2 pt4 = PointRelativeToLine(pt0, pt1, pt1, controlPt); 3678 pt = lineutility.ExtendLineDouble(pt4, controlPt, dist); 3679 pLinePoints.set(count - 1, pt); 3680 } catch (Exception exc) { 3681 ErrorLogger.LogException(_className, "adjustCATKBYFIREControlPoint", 3682 new RendererException("Failed inside adjustCATKBYFIREControlPoint", exc)); 3683 } 3684 } 3685 3686 /** 3687 * Returns the point perpendicular to the line (pt0 to pt1) at atPoint the 3688 * same distance from (and on the same side of) the the line as ptRelative. 3689 * 3690 * @param pt0 the first point 3691 * @param pt1 the second point 3692 * @param atPoint the point on the line at which to compute the extended 3693 * point 3694 * @param ptRelative the point to use for computing the return point 3695 * 3696 * @return the point perpendicular to the line at ptRelative 3697 */ 3698 public static POINT2 PointRelativeToLine(POINT2 pt0, 3699 POINT2 pt1, 3700 POINT2 atPoint, 3701 POINT2 ptRelative) { 3702 POINT2 ptResult = new POINT2(pt0); 3703 try { 3704 int bolVertical = 0; 3705 ref<double[]> m = new ref(); 3706 double b1 = 0, b2 = 0; 3707 3708 bolVertical = CalcTrueSlopeDouble(pt0, pt1, m); 3709 if (bolVertical == 0) //line is vertical 3710 { 3711 ptResult.x = ptRelative.x; 3712 ptResult.y = atPoint.y; 3713 } 3714 if (bolVertical != 0 && m.value[0] == 0) { 3715 ptResult.x = atPoint.x; 3716 ptResult.y = ptRelative.y; 3717 } 3718 if (bolVertical != 0 && m.value[0] != 0) { 3719 b1 = atPoint.y + (1 / m.value[0]) * atPoint.x; //the line perp to midPt 3720 b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line ptRelative with the slope of pt1-pt2 3721 ptResult = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0); 3722 } 3723 } catch (Exception exc) { 3724 ErrorLogger.LogException(_className, "PointRelativeToLine", 3725 new RendererException("Failed inside PointRelativeToLine", exc)); 3726 } 3727 return ptResult; 3728 } 3729 3730 /** 3731 * Returns in pt2 and pt3 the line segment parallel to segment pt0-pt1 which 3732 * would contain ptRelative. pt2 corresponds to pt0 and pt3 corresponds to 3733 * pt1. 3734 * 3735 * @param pt0 first line point 3736 * @param pt1 second line point 3737 * @param ptRelative relative line point 3738 * @param pt2 OUT - first computed relative line point 3739 * @param pt3 OUT - second computed relative line point 3740 */ 3741 public static void LineRelativeToLine(POINT2 pt0, 3742 POINT2 pt1, 3743 POINT2 ptRelative, 3744 POINT2 pt2, 3745 POINT2 pt3) { 3746 try { 3747 int bolVertical = 0; 3748 ref<double[]> m = new ref(); 3749 double b1 = 0, b2 = 0; 3750 POINT2 pt2Temp = null; 3751 POINT2 pt3Temp = null; 3752 3753 bolVertical = CalcTrueSlopeDouble(pt0, pt1, m); 3754 if (bolVertical == 0) //line is vertical 3755 { 3756 pt2.x = ptRelative.x; 3757 pt2.y = pt0.y; 3758 pt3.x = ptRelative.x; 3759 pt3.y = pt1.y; 3760 } 3761 if (bolVertical != 0 && m.value[0] == 0) //line is horizontal 3762 { 3763 pt2.x = pt0.x; 3764 pt2.y = ptRelative.y; 3765 pt3.x = pt1.x; 3766 pt3.y = ptRelative.y; 3767 } 3768 if (bolVertical != 0 && m.value[0] != 0) { 3769 b1 = pt0.y + (1 / m.value[0]) * pt0.x; //the line perp to pt0 3770 b2 = ptRelative.y - m.value[0] * ptRelative.x; //the line the ptRelative with the slope of pt0-pt1 3771 pt2Temp = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0); 3772 3773 b1 = pt1.y + (1 / m.value[0]) * pt1.x; //the line perp to pt1 3774 //b2=ptRelative.y-m*ptRelative.x; //the line the ptRelative with the slope of pt0-pt1 3775 pt3Temp = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0); 3776 3777 pt2.x = pt2Temp.x; 3778 pt2.y = pt2Temp.y; 3779 pt3.x = pt3Temp.x; 3780 pt3.y = pt3Temp.y; 3781 } 3782 } catch (Exception exc) { 3783 ErrorLogger.LogException(_className, "LineRelativeToLine", 3784 new RendererException("Failed inside LineRelativeToLine", exc)); 3785 } 3786 } 3787 3788 private static void CalcMBR(POINT2[] pLinePoints, 3789 int numpts, 3790 ref<double[]> ulx, 3791 ref<double[]> uly, 3792 ref<double[]> lrx, 3793 ref<double[]> lry) { 3794 try { 3795 int j = 0; 3796 //initialize the MBR 3797 ulx.value = new double[1]; 3798 uly.value = new double[1]; 3799 lrx.value = new double[1]; 3800 lry.value = new double[1]; 3801 ulx.value[0] = Double.MAX_VALUE;//was 99999 3802 uly.value[0] = Double.MAX_VALUE;//was 99999 3803 lrx.value[0] = -Double.MAX_VALUE;//was -99999 3804 lry.value[0] = -Double.MAX_VALUE;//was -99999 3805 for (j = 0; j < numpts; j++) { 3806 if (pLinePoints[j].x > lrx.value[0]) { 3807 lrx.value[0] = pLinePoints[j].x; 3808 } 3809 if (pLinePoints[j].y > lry.value[0]) { 3810 lry.value[0] = pLinePoints[j].y; 3811 } 3812 if (pLinePoints[j].x < ulx.value[0]) { 3813 ulx.value[0] = pLinePoints[j].x; 3814 } 3815 if (pLinePoints[j].y < uly.value[0]) { 3816 uly.value[0] = pLinePoints[j].y; 3817 } 3818 } 3819 } catch (Exception exc) { 3820 ErrorLogger.LogException(_className, "CalcMBR", 3821 new RendererException("Failed inside CalcMBR", exc)); 3822 } 3823 return; 3824 } 3825 3826 public static void CalcMBRPoints(POINT2[] pLinePoints, 3827 int numpts, 3828 POINT2 ul, 3829 POINT2 lr) { 3830 try { 3831 int j = 0; 3832 ul.x = Double.MAX_VALUE; 3833 ul.y = Double.MAX_VALUE; 3834 lr.x = -Double.MAX_VALUE; 3835 lr.y = -Double.MAX_VALUE; 3836 for (j = 0; j < numpts; j++) { 3837 if (pLinePoints[j].x > lr.x) { 3838 lr.x = pLinePoints[j].x; 3839 } 3840 if (pLinePoints[j].y > lr.y) { 3841 lr.y = pLinePoints[j].y; 3842 } 3843 if (pLinePoints[j].x < ul.x) { 3844 ul.x = pLinePoints[j].x; 3845 } 3846 if (pLinePoints[j].y < ul.y) { 3847 ul.y = pLinePoints[j].y; 3848 } 3849 } 3850 } catch (Exception exc) { 3851 ErrorLogger.LogException(_className, "CalcMBRPoints", 3852 new RendererException("Failed inside CalcMBRPoints", exc)); 3853 } 3854 } 3855 3856 /** 3857 * Computes the distance in pixels from upper left to lower right of the 3858 * minimum bounding rectangle for the first numpts of pLinePoints 3859 * 3860 * @param pLinePoints the inpupt point array 3861 * @param numpts the number of points to use 3862 * 3863 * @return the distance in pixels 3864 */ 3865 protected static double MBRDistance(POINT2[] pLinePoints, 3866 int numpts) { 3867 double result = 0; 3868 try { 3869 ref<double[]> ulx = new ref(), uly = new ref(), lrx = new ref(), lry = new ref(); 3870 CalcMBR(pLinePoints, numpts, ulx, uly, lrx, lry); 3871 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])); 3872 //sanity check 3873 3874 //return x or y distance if returnValue is 0 or infinity 3875 double xdist = Math.abs(lrx.value[0] - ulx.value[0]); 3876 double ydist = Math.abs(lry.value[0] - uly.value[0]); 3877 double max = xdist; 3878 if (ydist > xdist) { 3879 max = ydist; 3880 } 3881 3882 if (result == 0 || Double.isInfinite(result)) { 3883 if (max > 0) { 3884 result = max; 3885 } 3886 } 3887 3888 } catch (Exception exc) { 3889 ErrorLogger.LogException(_className, "MBRDistance", 3890 new RendererException("Failed inside MBRDistance", exc)); 3891 } 3892 return result; 3893 } 3894 3895 /** 3896 * Swaps two points. 3897 * 3898 * @param pt1 OUT - first point 3899 * @param pt2 OUT - second point 3900 * 3901 */ 3902 protected static void Reverse2Points(POINT2 pt1, POINT2 pt2) { 3903 try { 3904 POINT2 tempPt = new POINT2(); 3905 //store pt1 3906 tempPt.x = pt1.x; 3907 tempPt.y = pt1.y; 3908 pt1.x = pt2.x; 3909 pt1.y = pt2.y; 3910 pt2.x = tempPt.x; 3911 pt2.y = tempPt.y; 3912 } catch (Exception exc) { 3913 ErrorLogger.LogException(_className, "Reverse2Points", 3914 new RendererException("Failed inside Reverse2Points", exc)); 3915 } 3916 } 3917 /** 3918 * Creates a GeneralPath from a Path2D 3919 * 3920 * @param shape 3921 * @return 3922 */ 3923 public static Shape createStrokedShape(Shape shape) { 3924 GeneralPath newshape = new GeneralPath(); // Start with an empty shape 3925 try { 3926 // Iterate through the specified shape, perturb its coordinates, and 3927 // use them to build up the new shape. 3928 double[] coords = new double[6]; 3929 for (PathIterator i = shape.getPathIterator(null); !i.isDone(); i.next()) { 3930 int type = i.currentSegment(coords); 3931 switch (type) { 3932 case PathIterator.SEG_MOVETO: 3933 //perturb(coords, 2); 3934 newshape.moveTo(coords[0], coords[1]); 3935 break; 3936 case PathIterator.SEG_LINETO: 3937 //perturb(coords, 2); 3938 newshape.lineTo(coords[0], coords[1]); 3939 break; 3940 case PathIterator.SEG_QUADTO: 3941 //perturb(coords, 4); 3942 newshape.quadTo(coords[0], coords[1], coords[2], coords[3]); 3943 break; 3944 case PathIterator.SEG_CUBICTO: 3945 //perturb(coords, 6); 3946 newshape.curveTo(coords[0], coords[1], coords[2], coords[3], 3947 coords[4], coords[5]); 3948 break; 3949 case PathIterator.SEG_CLOSE: 3950 newshape.closePath(); 3951 break; 3952 } 3953 3954 } 3955 } catch (Exception exc) { 3956 ErrorLogger.LogException(_className, "createStrokedShape", 3957 new RendererException("Failed inside createStrokedShape", exc)); 3958 } 3959 return newshape; 3960 } 3961 //These functions were added to create a minimum bounding polygon 3962 /** 3963 * @deprecated Returns the determinant of the point matrix This determinant 3964 * tells how far p3 is from vector p1p2 and on which side it is 3965 * @param p1 3966 * @param p2 3967 * @param p3 3968 * @return 3969 */ 3970 static private int distance(Point p1, Point p2, Point p3) { 3971 try { 3972 int x1 = p1.x; 3973 int x2 = p2.x; 3974 int x3 = p3.x; 3975 int y1 = p1.y; 3976 int y2 = p2.y; 3977 int y3 = p3.y; 3978 return x1 * y2 + x3 * y1 + x2 * y3 - x3 * y2 - x2 * y1 - x1 * y3; 3979 } catch (Exception exc) { 3980 ErrorLogger.LogException(_className, "distance", 3981 new RendererException("Failed inside distance", exc)); 3982 } 3983 return 0; 3984 } 3985 3986 /** 3987 * @deprecated Returns the determinant of the point matrix This determinant 3988 * tells how far p3 is from vector p1p2 and on which side it is 3989 * @param p1 3990 * @param p2 3991 * @param p3 3992 * @return 3993 */ 3994 static private double distance2(POINT2 p1, POINT2 p2, POINT2 p3) { 3995 try { 3996 double x1 = p1.x; 3997 double x2 = p2.x; 3998 double x3 = p3.x; 3999 double y1 = p1.y; 4000 double y2 = p2.y; 4001 double y3 = p3.y; 4002 return x1 * y2 + x3 * y1 + x2 * y3 - x3 * y2 - x2 * y1 - x1 * y3; 4003 } catch (Exception exc) { 4004 ErrorLogger.LogException(_className, "distance2", 4005 new RendererException("Failed inside distance2", exc)); 4006 } 4007 return 0; 4008 } 4009 4010 /** 4011 * @deprecated @param points 4012 * @param l 4013 * @param r 4014 * @param path 4015 */ 4016 static private void cHull(ArrayList<Point> points, Point l, Point r, ArrayList<Point> path) { 4017 4018 if (points.size() < 3) { 4019 return; 4020 } 4021 4022 int maxDist = 0; 4023 int tmp; 4024 Point p = null; 4025 4026 for (Point pt : points) { 4027 if (pt != l && pt != r) { 4028 tmp = distance(l, r, pt); 4029 4030 if (tmp > maxDist) { 4031 maxDist = tmp; 4032 p = pt; 4033 } 4034 } 4035 } 4036 4037 ArrayList<Point> left = new ArrayList<Point>(); 4038 ArrayList<Point> right = new ArrayList<Point>(); 4039 left.add(l); 4040 right.add(p); 4041 4042 for (Point pt : points) { 4043 if (distance(l, p, pt) > 0) { 4044 left.add(pt); 4045 } else if (distance(p, r, pt) > 0) { 4046 right.add(pt); 4047 } 4048 } 4049 4050 left.add(p); 4051 right.add(r); 4052 cHull(left, l, p, path); 4053 path.add(p); 4054 cHull(right, p, r, path); 4055 } 4056 4057 /** 4058 * @deprecated @param points 4059 * @param l 4060 * @param r 4061 * @param path 4062 */ 4063 static private void cHull2(ArrayList<POINT2> points, POINT2 l, POINT2 r, ArrayList<POINT2> path) { 4064 4065 if (points.size() < 3) { 4066 return; 4067 } 4068 4069 double maxDist = 0; 4070 double tmp; 4071 POINT2 p = null; 4072 4073 for (POINT2 pt : points) { 4074 if (pt != l && pt != r) { 4075 tmp = distance2(l, r, pt); 4076 4077 if (tmp > maxDist) { 4078 maxDist = tmp; 4079 p = pt; 4080 } 4081 } 4082 } 4083 4084 ArrayList<POINT2> left = new ArrayList<POINT2>(); 4085 ArrayList<POINT2> right = new ArrayList<POINT2>(); 4086 left.add(l); 4087 right.add(p); 4088 4089 for (POINT2 pt : points) { 4090 if (distance2(l, p, pt) > 0) { 4091 left.add(pt); 4092 } else if (distance2(p, r, pt) > 0) { 4093 right.add(pt); 4094 } 4095 } 4096 4097 left.add(p); 4098 right.add(r); 4099 cHull2(left, l, p, path); 4100 path.add(p); 4101 cHull2(right, p, r, path); 4102 } 4103 //Returns the points of convex hull in the correct order 4104 /** 4105 * @deprecated @param array 4106 * @return 4107 */ 4108 static public ArrayList<Point> cHull(ArrayList<Point> array) { 4109 int size = array.size(); 4110 if (size < 2) { 4111 return null; 4112 } 4113 4114 Point l = array.get(0); 4115 Point r = array.get(size - 1); 4116 ArrayList<Point> path = new ArrayList<Point>(); 4117 path.add(l); 4118 cHull(array, l, r, path); 4119 path.add(r); 4120 cHull(array, r, l, path); 4121 return path; 4122 } 4123 4124 /** 4125 * @deprecated @param array 4126 * @return 4127 */ 4128 static public ArrayList<POINT2> cHull2(ArrayList<POINT2> array) { 4129 try { 4130 int size = array.size(); 4131 if (size < 2) { 4132 return null; 4133 } 4134 4135 POINT2 l = array.get(0); 4136 POINT2 r = array.get(size - 1); 4137 ArrayList<POINT2> path = new ArrayList<POINT2>(); 4138 path.add(l); 4139 cHull2(array, l, r, path); 4140 path.add(r); 4141 cHull2(array, r, l, path); 4142 return path; 4143 } catch (Exception exc) { 4144 ErrorLogger.LogException(_className, "cHull2", 4145 new RendererException("Failed inside cHull2", exc)); 4146 } 4147 return null; 4148 } 4149 4150 public static void getExteriorPoints(POINT2[] pLinePoints, 4151 int vblCounter, 4152 int lineType, 4153 boolean interior 4154 ) { 4155 int j; 4156 int index; 4157 POINT2 pt0, pt1, pt2; 4158 ref<double[]> m01 = new ref(), m12 = new ref(); 4159 int direction; 4160 POINT2 intersectPt; 4161 //ref<double[]> m1 = new ref(), m2 = new ref(); 4162 ArrayList<POINT2> intersectPoints = new ArrayList(); 4163 double b01, b12; //the y intercepts for the lines corresponding to m1,m2 4164 double dist = pLinePoints[0].style; 4165 for (j = 0; j < vblCounter; j++) { 4166 if (j == 0 || j == vblCounter - 1) { 4167 pt0 = new POINT2(pLinePoints[vblCounter - 2]); 4168 pt1 = new POINT2(pLinePoints[0]); 4169 pt2 = new POINT2(pLinePoints[1]); 4170 } else { 4171 pt0 = new POINT2(pLinePoints[j - 1]); 4172 pt1 = new POINT2(pLinePoints[j]); 4173 pt2 = new POINT2(pLinePoints[j + 1]); 4174 } 4175 if (pt1.style > 0) { 4176 dist = pt1.style; 4177 } 4178 //the exterior/interior points 4179 POINT2 pt00, pt01, pt10, pt11; 4180 4181 index = j - 1; 4182 if (index < 0) { 4183 index = vblCounter - 1; 4184 } 4185 POINT2[] pts = new POINT2[pLinePoints.length]; 4186 int n=pLinePoints.length; 4187 //for (int k = 0; k < pLinePoints.length; k++) 4188 for (int k = 0; k < n; k++) 4189 { 4190 pts[k] = pLinePoints[k]; 4191 } 4192 4193 direction = arraysupport.GetInsideOutsideDouble2(pt0, pt1, pts, vblCounter, index, lineType); 4194 //reverse the direction if these are interior points 4195 if (interior == true) { 4196 direction = reverseDirection(direction); 4197 } 4198 //pt00-pt01 will be the interior line inside line pt0-pt1 4199 //pt00 is inside pt0, pt01 is inside pt1 4200 pt00 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, direction, dist); 4201 pt01 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, direction, dist); 4202 4203 //pt10-pt11 will be the interior line inside line pt1-pt2 4204 //pt10 is inside pt1, pt11 is inside pt2 4205 index = j; 4206 if (j == vblCounter - 1) { 4207 index = 0; 4208 } 4209 direction = arraysupport.GetInsideOutsideDouble2(pt1, pt2, (POINT2[]) pts, vblCounter, index, lineType); 4210 //reverse the direction if these are interior points 4211 if (interior == true) { 4212 direction =reverseDirection(direction); 4213 } 4214 pt10 = lineutility.ExtendDirectedLine(pt1, pt2, pt1, direction, dist); 4215 pt11 = lineutility.ExtendDirectedLine(pt1, pt2, pt2, direction, dist); 4216 //intersectPt=new POINT2(null); 4217 //get the intersection of pt01-p00 and pt10-pt11 4218 //so it it is the interior intersection of pt0-pt1 and pt1-pt2 4219 4220 //first handle the case of vertical lines. 4221 if (pt0.x == pt1.x && pt1.x == pt2.x) { 4222 intersectPt = new POINT2(pt01); 4223 intersectPoints.add(intersectPt); 4224 continue; 4225 } 4226 //it's the same situation if the slopes are identical, 4227 //simply use pt01 or pt10 since they already uniquely define the intesection 4228 lineutility.CalcTrueSlopeDouble2(pt00, pt01, m01); 4229 lineutility.CalcTrueSlopeDouble2(pt10, pt11, m12); 4230 //if(m01.dbl==m12.dbl) 4231 if (m01.value[0] == m12.value[0]) { 4232 intersectPt = new POINT2(pt01); 4233 intersectPoints.add(intersectPt); 4234 continue; 4235 } 4236 //now we are assuming a non-trivial intersection 4237 //calculate the y-intercepts using y=mx+b (use b=y-mx) 4238 b01 = pt01.y - m01.value[0] * pt01.x; 4239 b12 = pt11.y - m12.value[0] * pt11.x; 4240 intersectPt = lineutility.CalcTrueIntersectDouble2(m01.value[0], b01, m12.value[0], b12, 1, 1, 0, 0); 4241 intersectPoints.add(intersectPt); 4242 }//end for 4243 int n=intersectPoints.size(); 4244 //for (j = 0; j < intersectPoints.size(); j++) 4245 for (j = 0; j < n; j++) 4246 { 4247 pLinePoints[j] = intersectPoints.get(j); 4248 } 4249 } 4250 public static ArrayList<POINT2> getDeepCopy(ArrayList<POINT2>pts) 4251 { 4252 ArrayList<POINT2>deepCopy=null; 4253 try 4254 { 4255 if(pts == null || pts.isEmpty()) 4256 return pts; 4257 deepCopy=new ArrayList(); 4258 int j=0; 4259 POINT2 pt=null; 4260 for(j=0;j<pts.size();j++) 4261 { 4262 pt=new POINT2(pts.get(j).x,pts.get(j).y,pts.get(j).style); 4263 deepCopy.add(pt); 4264 } 4265 } 4266 catch (Exception exc) { 4267 ErrorLogger.LogException(_className, "getDeepCopy", 4268 new RendererException("Failed inside getDeepCopy", exc)); 4269 } 4270 return deepCopy; 4271 } 4272 4273 public static int reverseDirection(int direction) { 4274 switch (direction) { 4275 case extend_left: 4276 return extend_right; 4277 case extend_right: 4278 return extend_left; 4279 case extend_above: 4280 return extend_below; 4281 case extend_below: 4282 return extend_above; 4283 default: 4284 return direction; 4285 } 4286 } 4287}//end lineutility