fork download
  1. #include <boost/geometry.hpp>
  2. #include <boost/geometry/geometries/point.hpp>
  3. #include <boost/geometry/geometries/linestring.hpp>
  4. #include <iostream>
  5. #include <cmath>
  6.  
  7. namespace bg = boost::geometry;
  8.  
  9. typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree>> point_type;
  10. typedef bg::model::linestring<point_type> linestring_type;
  11.  
  12. // Конвертация географических координат в ECEF (Earth-Centered, Earth-Fixed)
  13. void geo_to_ecef(double lat, double lon, double& x, double& y, double& z) {
  14. const double R = 6378137.0; // Радиус Земли в метрах
  15. const double lat_rad = lat * M_PI / 180.0;
  16. const double lon_rad = lon * M_PI / 180.0;
  17.  
  18. x = R * cos(lat_rad) * cos(lon_rad);
  19. y = R * cos(lat_rad) * sin(lon_rad);
  20. z = R * sin(lat_rad);
  21. }
  22.  
  23. double calculate_angle(const linestring_type& line1, const linestring_type& line2) {
  24. if (line1.size() < 2 || line2.size() < 2) {
  25. return 0.0; // Неверные линии
  26. }
  27.  
  28. // Получаем начальную и конечную точки каждой линии
  29. const point_type& A = line1.front();
  30. const point_type& B = line1.back();
  31. const point_type& C = line2.front();
  32. const point_type& D = line2.back();
  33.  
  34. // Конвертируем в ECEF координаты
  35. double Ax, Ay, Az, Bx, By, Bz, Cx, Cy, Cz, Dx, Dy, Dz;
  36. geo_to_ecef(bg::get<0>(A), bg::get<1>(A), Ax, Ay, Az);
  37. geo_to_ecef(bg::get<0>(B), bg::get<1>(B), Bx, By, Bz);
  38. geo_to_ecef(bg::get<0>(C), bg::get<1>(C), Cx, Cy, Cz);
  39. geo_to_ecef(bg::get<0>(D), bg::get<1>(D), Dx, Dy, Dz);
  40.  
  41. // Вычисляем векторы направлений
  42. double ABx = Bx - Ax;
  43. double ABy = By - Ay;
  44. double ABz = Bz - Az;
  45. double CDx = Dx - Cx;
  46. double CDy = Dy - Cy;
  47. double CDz = Dz - Cz;
  48.  
  49. // Нормализуем векторы
  50. double len_AB = sqrt(ABx*ABx + ABy*ABy + ABz*ABz);
  51. double len_CD = sqrt(CDx*CDx + CDy*CDy + CDz*CDz);
  52. ABx /= len_AB; ABy /= len_AB; ABz /= len_AB;
  53. CDx /= len_CD; CDy /= len_CD; CDz /= len_CD;
  54.  
  55. // Вычисляем скалярное произведение
  56. double dot_product = ABx*CDx + ABy*CDy + ABz*CDz;
  57.  
  58. // Обеспечиваем, чтобы значение dot_product было в диапазоне [-1, 1]
  59. dot_product = std::max(-1.0, std::min(1.0, dot_product));
  60.  
  61. // Вычисляем угол в радианах, затем конвертируем в градусы
  62. double angle_rad = acos(dot_product);
  63. double angle_deg = angle_rad * 180.0 / M_PI;
  64.  
  65. // Если угол больше 90 градусов, возвращаем острый угол
  66. if (angle_deg > 90.0) {
  67. angle_deg = 180.0 - angle_deg;
  68. }
  69.  
  70. return angle_deg;
  71. }
  72.  
  73. bool are_collinear(const linestring_type& line1, const linestring_type& line2) {
  74. // Линии колинеарны, если угол между ними близок к 0 или 180 градусов
  75. double angle = calculate_angle(line1, line2);
  76. return angle < 1e-6;
  77. }
  78.  
  79. int main() {
  80. linestring_type line1, line2;
  81.  
  82. // Инициализация первой линии с заданными координатами
  83. bg::append(line1, point_type(45.094734, 37.565922));
  84. bg::append(line1, point_type(45.094696, 37.566153));
  85.  
  86. // Инициализация второй линии
  87. // Пример другой линии, можно заменить на свою
  88. bg::append(line2, point_type(45.094972, 37.565076));
  89. bg::append(line2, point_type(45.194934, 37.565307));
  90. // Вычисление угла между линиями
  91. double angle = calculate_angle(line1, line2);
  92. std::cout << "Угол между линиями: " << angle << " градусов" << std::endl;
  93.  
  94. // Проверка колинеарности
  95. if (are_collinear(line1, line2)) {
  96. std::cout << "Линии колинеарны." << std::endl;
  97. } else {
  98. std::cout << "Линии не колинеарны." << std::endl;
  99. }
  100.  
  101. return 0;
  102. }
  103.  
Success #stdin #stdout 0.01s 5284KB
stdin
Standard input is empty
stdout
Угол между линиями: 76.9766 градусов
Линии не колинеарны.