Line2D.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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. class Line2D
  15. {
  16. public Vector2D P1 { get; private set; }
  17. public Vector2D P2 { get; private set; }
  18. public Vector2D Direction { get; private set; }
  19. public float Length { get { return P1.getDistanceTo(P2); }}
  20. public Line2D(Vector2D p1, Vector2D p2)
  21. {
  22. setPoints(p1, p2);
  23. }
  24. private void setPoints(Vector2D p1, Vector2D p2)
  25. {
  26. //endpoints
  27. P1 = p1;
  28. P2 = p2;
  29. //direction
  30. Direction = (P1 - P2).normalize();
  31. }
  32. public float getAngleBetween(Line2D line)
  33. {
  34. float angle = Direction.getAngleBetween(line.Direction);
  35. return Math.Min(angle, 180 - angle);
  36. }
  37. public float getParallelDistanceTo(Line2D line)
  38. {
  39. if (onSide(line.P1) != onSide(line.P2)) return 0;
  40. Vector2D a1 = projectToLine(line.P1);
  41. Vector2D a2 = projectToLine(line.P2);
  42. float distanceA1 = a1.getDistanceTo(line.P1);
  43. float distanceA2 = a2.getDistanceTo(line.P2);
  44. return Math.Min(distanceA1, distanceA2);
  45. }
  46. public float getVerticalDistanceTo(Line2D line)
  47. {
  48. Vector2D a1 = projectToLine(line.P1);
  49. Vector2D a2 = projectToLine(line.P2);
  50. if (P1.isInBox(a1, a2) || P2.isInBox(a1, a2)) return 0;
  51. float distanceP1A1 = P1.getDistanceTo(a1);
  52. float distanceP1A2 = P1.getDistanceTo(a2);
  53. float distanceP2A1 = P2.getDistanceTo(a1);
  54. float distanceP2A2 = P2.getDistanceTo(a2);
  55. return Math.Min(Math.Min(distanceP1A1, distanceP1A2), Math.Min(distanceP2A1, distanceP2A2));
  56. }
  57. public LineSide onSide(Vector2D point)
  58. {
  59. float yPerX = Direction.Y / Direction.X;
  60. float xDiff = point.X - P1.X;
  61. float newY = P1.Y + yPerX * xDiff;
  62. if (newY < point.Y) return LineSide.above;
  63. else if (newY > point.Y) return LineSide.below;
  64. else return LineSide.onLine;
  65. }
  66. public Vector2D projectToLine(Vector2D point)
  67. {
  68. float px = point.X, py = point.Y, dx = Direction.X, dy = Direction.Y, ox = P1.X, oy = P1.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. public Vector2D intersection(Line2D line)
  79. {
  80. Vector2D p = P1;
  81. Vector2D r = P2 - P1;
  82. Vector2D q = line.P1;
  83. Vector2D s = line.P2 - line.P1;
  84. float r_cross_s = r.cross(s);
  85. float q_p_cross_s = (q - p).cross(s);
  86. if (r_cross_s == 0.0)
  87. return null;
  88. float t = q_p_cross_s / r_cross_s;
  89. return p + t * r;
  90. }
  91. public override string ToString()
  92. {
  93. return (int)P1.X + "|" + (int)P1.Y + " --- " + (int)P2.X + "|" + (int)P2.Y;
  94. }
  95. }
  96. }