Geometry.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. namespace Terminal.Gui.TextEffects;
  2. public static class GeometryUtils
  3. {
  4. public static List<Coord> FindCoordsOnCircle (Coord origin, int radius, int coordsLimit = 0, bool unique = true)
  5. {
  6. var points = new List<Coord> ();
  7. var seenPoints = new HashSet<Coord> ();
  8. if (coordsLimit == 0)
  9. coordsLimit = (int)Math.Ceiling (2 * Math.PI * radius);
  10. double angleStep = 2 * Math.PI / coordsLimit;
  11. for (int i = 0; i < coordsLimit; i++)
  12. {
  13. double angle = i * angleStep;
  14. int x = (int)(origin.Column + radius * Math.Cos (angle));
  15. int y = (int)(origin.Row + radius * Math.Sin (angle));
  16. var coord = new Coord (x, y);
  17. if (unique && !seenPoints.Contains (coord))
  18. {
  19. points.Add (coord);
  20. seenPoints.Add (coord);
  21. }
  22. else if (!unique)
  23. {
  24. points.Add (coord);
  25. }
  26. }
  27. return points;
  28. }
  29. public static List<Coord> FindCoordsInCircle (Coord center, int diameter)
  30. {
  31. var coordsInEllipse = new List<Coord> ();
  32. int radius = diameter / 2;
  33. for (int x = center.Column - radius; x <= center.Column + radius; x++)
  34. {
  35. for (int y = center.Row - radius; y <= center.Row + radius; y++)
  36. {
  37. if (Math.Pow (x - center.Column, 2) + Math.Pow (y - center.Row, 2) <= Math.Pow (radius, 2))
  38. coordsInEllipse.Add (new Coord (x, y));
  39. }
  40. }
  41. return coordsInEllipse;
  42. }
  43. public static List<Coord> FindCoordsInRect (Coord origin, int distance)
  44. {
  45. var coords = new List<Coord> ();
  46. for (int column = origin.Column - distance; column <= origin.Column + distance; column++)
  47. {
  48. for (int row = origin.Row - distance; row <= origin.Row + distance; row++)
  49. {
  50. coords.Add (new Coord (column, row));
  51. }
  52. }
  53. return coords;
  54. }
  55. public static Coord FindCoordAtDistance (Coord origin, Coord target, double distance)
  56. {
  57. double totalDistance = FindLengthOfLine (origin, target) + distance;
  58. double t = distance / totalDistance;
  59. int nextColumn = (int)((1 - t) * origin.Column + t * target.Column);
  60. int nextRow = (int)((1 - t) * origin.Row + t * target.Row);
  61. return new Coord (nextColumn, nextRow);
  62. }
  63. public static Coord FindCoordOnBezierCurve (Coord start, List<Coord> controlPoints, Coord end, double t)
  64. {
  65. // Implementing De Casteljau's algorithm for Bezier curve
  66. if (controlPoints.Count == 1) // Quadratic
  67. {
  68. double x = Math.Pow (1 - t, 2) * start.Column +
  69. 2 * (1 - t) * t * controlPoints [0].Column +
  70. Math.Pow (t, 2) * end.Column;
  71. double y = Math.Pow (1 - t, 2) * start.Row +
  72. 2 * (1 - t) * t * controlPoints [0].Row +
  73. Math.Pow (t, 2) * end.Row;
  74. return new Coord ((int)x, (int)y);
  75. }
  76. else if (controlPoints.Count == 2) // Cubic
  77. {
  78. double x = Math.Pow (1 - t, 3) * start.Column +
  79. 3 * Math.Pow (1 - t, 2) * t * controlPoints [0].Column +
  80. 3 * (1 - t) * Math.Pow (t, 2) * controlPoints [1].Column +
  81. Math.Pow (t, 3) * end.Column;
  82. double y = Math.Pow (1 - t, 3) * start.Row +
  83. 3 * Math.Pow (1 - t, 2) * t * controlPoints [0].Row +
  84. 3 * (1 - t) * Math.Pow (t, 2) * controlPoints [1].Row +
  85. Math.Pow (t, 3) * end.Row;
  86. return new Coord ((int)x, (int)y);
  87. }
  88. throw new ArgumentException ("Invalid number of control points for bezier curve");
  89. }
  90. public static Coord FindCoordOnLine (Coord start, Coord end, double t)
  91. {
  92. int x = (int)((1 - t) * start.Column + t * end.Column);
  93. int y = (int)((1 - t) * start.Row + t * end.Row);
  94. return new Coord (x, y);
  95. }
  96. public static double FindLengthOfBezierCurve (Coord start, List<Coord> controlPoints, Coord end)
  97. {
  98. double length = 0.0;
  99. Coord prevCoord = start;
  100. for (int i = 1; i <= 10; i++)
  101. {
  102. double t = i / 10.0;
  103. Coord coord = FindCoordOnBezierCurve (start, controlPoints, end, t);
  104. length += FindLengthOfLine (prevCoord, coord);
  105. prevCoord = coord;
  106. }
  107. return length;
  108. }
  109. public static double FindLengthOfLine (Coord coord1, Coord coord2)
  110. {
  111. return Math.Sqrt (Math.Pow (coord2.Column - coord1.Column, 2) +
  112. Math.Pow (coord2.Row - coord1.Row, 2));
  113. }
  114. public static double FindNormalizedDistanceFromCenter (int maxRow, int maxColumn, Coord otherCoord)
  115. {
  116. double center_x = maxColumn / 2.0;
  117. double center_y = maxRow / 2.0;
  118. double maxDistance = Math.Sqrt (Math.Pow (maxColumn, 2) + Math.Pow (maxRow, 2));
  119. double distance = Math.Sqrt (Math.Pow (otherCoord.Column - center_x, 2) +
  120. Math.Pow (otherCoord.Row - center_y, 2));
  121. return distance / (maxDistance / 2);
  122. }
  123. }