Line2D.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using System;
  2. namespace BBIWARG.Utility
  3. {
  4. /// <summary>
  5. /// Values for describing if something is on, above or below a line.
  6. /// </summary>
  7. public enum LineSide
  8. {
  9. onLine = 0,
  10. above = 1,
  11. below = 2
  12. }
  13. /// <summary>
  14. /// Line lass which represents a infinity line in 2 dimensional space.
  15. /// </summary>
  16. public class Line2D
  17. {
  18. /// <summary>
  19. /// direction vector of the line
  20. /// </summary>
  21. public Vector2D Direction { get; private set; }
  22. /// <summary>
  23. /// one point on the line
  24. /// </summary>
  25. public Vector2D PointOnLine { get; private set; }
  26. /// <summary>
  27. /// Standard constructor which sets the essential attributes.
  28. /// </summary>
  29. /// <param name="pointOnLine">a point on the line</param>
  30. /// <param name="direction">the direction of the line</param>
  31. public Line2D(Vector2D pointOnLine, Vector2D direction)
  32. {
  33. PointOnLine = pointOnLine;
  34. Direction = direction.normalize();
  35. }
  36. /// <summary>
  37. /// Computes angle between current and an second line in degrees.
  38. /// </summary>
  39. /// <param name="line">second line</param>
  40. /// <returns>angle between this and line in degrees</returns>
  41. public float getAngleBetween(Line2D line)
  42. {
  43. float angle = Direction.getAngleBetween(line.Direction);
  44. return Math.Min(angle, 180 - angle);
  45. }
  46. /// <summary>
  47. /// Computes the intersection of two lines, iff the lines do not intersect it returns null.
  48. /// </summary>
  49. /// <param name="line">the second line</param>
  50. /// <returns>the intersection or null iff the lines do not intersect</returns>
  51. public Vector2D getIntersection(Line2D line)
  52. {
  53. Vector2D p = PointOnLine;
  54. Vector2D r = Direction;
  55. Vector2D q = line.PointOnLine;
  56. Vector2D s = line.Direction;
  57. float r_cross_s = r.crossProduct(s);
  58. float q_p_cross_s = (q - p).crossProduct(s);
  59. if (r_cross_s == 0.0)
  60. return null;
  61. float t = q_p_cross_s / r_cross_s;
  62. return p + t * r;
  63. }
  64. /// <summary>
  65. /// Calculates whether a point is above, below or on this line.
  66. /// </summary>
  67. /// <param name="point">point which is used to compute the side</param>
  68. /// <returns>LineSide.above iff point is above this, LineSide.below iff point is below this, LineSide.onLine iff point is on this line</returns>
  69. public LineSide onSide(Vector2D point)
  70. {
  71. float ratio = Direction.Y / Direction.X;
  72. float horizontalDifference = point.X - PointOnLine.X;
  73. float newY = PointOnLine.Y + ratio * horizontalDifference;
  74. if (newY < point.Y) return LineSide.above;
  75. else if (newY > point.Y) return LineSide.below;
  76. else return LineSide.onLine;
  77. }
  78. /// <summary>
  79. /// Projects a point on this line.
  80. /// </summary>
  81. /// <param name="point">point which is projected</param>
  82. /// <returns>the point on the line with minimal distance to input point</returns>
  83. public Vector2D projectToLine(Vector2D point)
  84. {
  85. float px = point.X, py = point.Y, dx = Direction.X, dy = Direction.Y, ox = PointOnLine.X, oy = PointOnLine.Y;
  86. float diffx = px - ox;
  87. float diffy = py - oy;
  88. float diff_d = diffx * dx + diffy * dy;
  89. float d_d = dx * dx + dy * dy;
  90. float q = diff_d / d_d;
  91. float newX = ox + q * dx;
  92. float newY = oy + q * dy;
  93. return new Vector2D(newX, newY);
  94. }
  95. }
  96. }