Line2D.cs 3.7 KB

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