Line2D.cs 3.8 KB

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