#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <iostream>
#include <cmath>
namespace bg = boost::geometry;
typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree>> point_type;
typedef bg::model::linestring<point_type> linestring_type;
// Конвертация географических координат в ECEF (Earth-Centered, Earth-Fixed)
void geo_to_ecef(double lat, double lon, double& x, double& y, double& z) {
const double R = 6378137.0; // Радиус Земли в метрах
const double lat_rad = lat * M_PI / 180.0;
const double lon_rad = lon * M_PI / 180.0;
x = R * cos(lat_rad) * cos(lon_rad);
y = R * cos(lat_rad) * sin(lon_rad);
z = R * sin(lat_rad);
}
bool are_collinear(const linestring_type& line1, const linestring_type& line2) {
if (line1.size() < 2 || line2.size() < 2) {
return false;
}
// Получаем начальную и конечную точки каждой линии
const point_type& A = line1.front();
const point_type& B = line1.back();
const point_type& C = line2.front();
const point_type& D = line2.back();
// Конвертируем в ECEF координаты
double Ax, Ay, Az, Bx, By, Bz, Cx, Cy, Cz, Dx, Dy, Dz;
geo_to_ecef(bg::get<0>(A), bg::get<1>(A), Ax, Ay, Az);
geo_to_ecef(bg::get<0>(B), bg::get<1>(B), Bx, By, Bz);
geo_to_ecef(bg::get<0>(C), bg::get<1>(C), Cx, Cy, Cz);
geo_to_ecef(bg::get<0>(D), bg::get<1>(D), Dx, Dy, Dz);
// Вычисляем векторы направлений
double ABx = Bx - Ax;
double ABy = By - Ay;
double ABz = Bz - Az;
double CDx = Dx - Cx;
double CDy = Dy - Cy;
double CDz = Dz - Cz;
// Нормализуем векторы
double len_AB = sqrt(ABx*ABx + ABy*ABy + ABz*ABz);
double len_CD = sqrt(CDx*CDx + CDy*CDy + CDz*CDz);
ABx /= len_AB; ABy /= len_AB; ABz /= len_AB;
CDx /= len_CD; CDy /= len_CD; CDz /= len_CD;
// Вычисляем векторное произведение
double crossx = ABy*CDz - ABz*CDy;
double crossy = ABz*CDx - ABx*CDz;
double crossz = ABx*CDy - ABy*CDx;
double cross_mag = sqrt(crossx*crossx + crossy*crossy + crossz*crossz);
// Если величина векторного произведения близка к нулю, линии колинеарны
return cross_mag < 1e-9;
}
int main() {
linestring_type line1, line2;
// Инициализация первой линии с заданными координатами
bg::append(line1, point_type(45.094734, 37.565922));
bg::append(line1, point_type(45.094696, 37.566153));
// Инициализация второй линии
// Для примера используем другую линию, которую можно заменить
bg::append(line2, point_type(45.094972, 37.565076));
bg::append(line2, point_type(45.094934, 37.565307));
// Проверка колинеарности
if (are_collinear(line1, line2)) {
std::cout << "Линии колинеарны." << std::endl;
} else {
std::cout << "Линии не колинеарны." << std::endl;
}
return 0;
}
I2luY2x1ZGUgPGJvb3N0L2dlb21ldHJ5LmhwcD4KI2luY2x1ZGUgPGJvb3N0L2dlb21ldHJ5L2dlb21ldHJpZXMvcG9pbnQuaHBwPgojaW5jbHVkZSA8Ym9vc3QvZ2VvbWV0cnkvZ2VvbWV0cmllcy9saW5lc3RyaW5nLmhwcD4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y21hdGg+CgpuYW1lc3BhY2UgYmcgPSBib29zdDo6Z2VvbWV0cnk7Cgp0eXBlZGVmIGJnOjptb2RlbDo6cG9pbnQ8ZG91YmxlLCAyLCBiZzo6Y3M6Omdlb2dyYXBoaWM8Ymc6OmRlZ3JlZT4+IHBvaW50X3R5cGU7CnR5cGVkZWYgYmc6Om1vZGVsOjpsaW5lc3RyaW5nPHBvaW50X3R5cGU+IGxpbmVzdHJpbmdfdHlwZTsKCi8vINCa0L7QvdCy0LXRgNGC0LDRhtC40Y8g0LPQtdC+0LPRgNCw0YTQuNGH0LXRgdC60LjRhSDQutC+0L7RgNC00LjQvdCw0YIg0LIgRUNFRiAoRWFydGgtQ2VudGVyZWQsIEVhcnRoLUZpeGVkKQp2b2lkIGdlb190b19lY2VmKGRvdWJsZSBsYXQsIGRvdWJsZSBsb24sIGRvdWJsZSYgeCwgZG91YmxlJiB5LCBkb3VibGUmIHopIHsKICAgIGNvbnN0IGRvdWJsZSBSID0gNjM3ODEzNy4wOyAvLyDQoNCw0LTQuNGD0YEg0JfQtdC80LvQuCDQsiDQvNC10YLRgNCw0YUKICAgIGNvbnN0IGRvdWJsZSBsYXRfcmFkID0gbGF0ICogTV9QSSAvIDE4MC4wOwogICAgY29uc3QgZG91YmxlIGxvbl9yYWQgPSBsb24gKiBNX1BJIC8gMTgwLjA7CiAgICAKICAgIHggPSBSICogY29zKGxhdF9yYWQpICogY29zKGxvbl9yYWQpOwogICAgeSA9IFIgKiBjb3MobGF0X3JhZCkgKiBzaW4obG9uX3JhZCk7CiAgICB6ID0gUiAqIHNpbihsYXRfcmFkKTsKfQoKYm9vbCBhcmVfY29sbGluZWFyKGNvbnN0IGxpbmVzdHJpbmdfdHlwZSYgbGluZTEsIGNvbnN0IGxpbmVzdHJpbmdfdHlwZSYgbGluZTIpIHsKICAgIGlmIChsaW5lMS5zaXplKCkgPCAyIHx8IGxpbmUyLnNpemUoKSA8IDIpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgLy8g0J/QvtC70YPRh9Cw0LXQvCDQvdCw0YfQsNC70YzQvdGD0Y4g0Lgg0LrQvtC90LXRh9C90YPRjiDRgtC+0YfQutC4INC60LDQttC00L7QuSDQu9C40L3QuNC4CiAgICBjb25zdCBwb2ludF90eXBlJiBBID0gbGluZTEuZnJvbnQoKTsKICAgIGNvbnN0IHBvaW50X3R5cGUmIEIgPSBsaW5lMS5iYWNrKCk7CiAgICBjb25zdCBwb2ludF90eXBlJiBDID0gbGluZTIuZnJvbnQoKTsKICAgIGNvbnN0IHBvaW50X3R5cGUmIEQgPSBsaW5lMi5iYWNrKCk7CgogICAgLy8g0JrQvtC90LLQtdGA0YLQuNGA0YPQtdC8INCyIEVDRUYg0LrQvtC+0YDQtNC40L3QsNGC0YsKICAgIGRvdWJsZSBBeCwgQXksIEF6LCBCeCwgQnksIEJ6LCBDeCwgQ3ksIEN6LCBEeCwgRHksIER6OwogICAgZ2VvX3RvX2VjZWYoYmc6OmdldDwwPihBKSwgYmc6OmdldDwxPihBKSwgQXgsIEF5LCBBeik7CiAgICBnZW9fdG9fZWNlZihiZzo6Z2V0PDA+KEIpLCBiZzo6Z2V0PDE+KEIpLCBCeCwgQnksIEJ6KTsKICAgIGdlb190b19lY2VmKGJnOjpnZXQ8MD4oQyksIGJnOjpnZXQ8MT4oQyksIEN4LCBDeSwgQ3opOwogICAgZ2VvX3RvX2VjZWYoYmc6OmdldDwwPihEKSwgYmc6OmdldDwxPihEKSwgRHgsIER5LCBEeik7CgogICAgLy8g0JLRi9GH0LjRgdC70Y/QtdC8INCy0LXQutGC0L7RgNGLINC90LDQv9GA0LDQstC70LXQvdC40LkKICAgIGRvdWJsZSBBQnggPSBCeCAtIEF4OwogICAgZG91YmxlIEFCeSA9IEJ5IC0gQXk7CiAgICBkb3VibGUgQUJ6ID0gQnogLSBBejsKICAgIGRvdWJsZSBDRHggPSBEeCAtIEN4OwogICAgZG91YmxlIENEeSA9IER5IC0gQ3k7CiAgICBkb3VibGUgQ0R6ID0gRHogLSBDejsKCiAgICAvLyDQndC+0YDQvNCw0LvQuNC30YPQtdC8INCy0LXQutGC0L7RgNGLCiAgICBkb3VibGUgbGVuX0FCID0gc3FydChBQngqQUJ4ICsgQUJ5KkFCeSArIEFCeipBQnopOwogICAgZG91YmxlIGxlbl9DRCA9IHNxcnQoQ0R4KkNEeCArIENEeSpDRHkgKyBDRHoqQ0R6KTsKICAgIEFCeCAvPSBsZW5fQUI7IEFCeSAvPSBsZW5fQUI7IEFCeiAvPSBsZW5fQUI7CiAgICBDRHggLz0gbGVuX0NEOyBDRHkgLz0gbGVuX0NEOyBDRHogLz0gbGVuX0NEOwoKICAgIC8vINCS0YvRh9C40YHQu9GP0LXQvCDQstC10LrRgtC+0YDQvdC+0LUg0L/RgNC+0LjQt9Cy0LXQtNC10L3QuNC1CiAgICBkb3VibGUgY3Jvc3N4ID0gQUJ5KkNEeiAtIEFCeipDRHk7CiAgICBkb3VibGUgY3Jvc3N5ID0gQUJ6KkNEeCAtIEFCeCpDRHo7CiAgICBkb3VibGUgY3Jvc3N6ID0gQUJ4KkNEeSAtIEFCeSpDRHg7CiAgICBkb3VibGUgY3Jvc3NfbWFnID0gc3FydChjcm9zc3gqY3Jvc3N4ICsgY3Jvc3N5KmNyb3NzeSArIGNyb3Nzeipjcm9zc3opOwoKICAgIC8vINCV0YHQu9C4INCy0LXQu9C40YfQuNC90LAg0LLQtdC60YLQvtGA0L3QvtCz0L4g0L/RgNC+0LjQt9Cy0LXQtNC10L3QuNGPINCx0LvQuNC30LrQsCDQuiDQvdGD0LvRjiwg0LvQuNC90LjQuCDQutC+0LvQuNC90LXQsNGA0L3RiwogICAgcmV0dXJuIGNyb3NzX21hZyA8IDFlLTk7Cn0KCmludCBtYWluKCkgewogICAgbGluZXN0cmluZ190eXBlIGxpbmUxLCBsaW5lMjsKCiAgICAvLyDQmNC90LjRhtC40LDQu9C40LfQsNGG0LjRjyDQv9C10YDQstC+0Lkg0LvQuNC90LjQuCDRgSDQt9Cw0LTQsNC90L3Ri9C80Lgg0LrQvtC+0YDQtNC40L3QsNGC0LDQvNC4CiAgICBiZzo6YXBwZW5kKGxpbmUxLCBwb2ludF90eXBlKDQ1LjA5NDczNCwgMzcuNTY1OTIyKSk7CiAgICBiZzo6YXBwZW5kKGxpbmUxLCBwb2ludF90eXBlKDQ1LjA5NDY5NiwgMzcuNTY2MTUzKSk7CgogICAgLy8g0JjQvdC40YbQuNCw0LvQuNC30LDRhtC40Y8g0LLRgtC+0YDQvtC5INC70LjQvdC40LgKICAgIC8vINCU0LvRjyDQv9GA0LjQvNC10YDQsCDQuNGB0L/QvtC70YzQt9GD0LXQvCDQtNGA0YPQs9GD0Y4g0LvQuNC90LjRjiwg0LrQvtGC0L7RgNGD0Y4g0LzQvtC20L3QviDQt9Cw0LzQtdC90LjRgtGMCiAgICBiZzo6YXBwZW5kKGxpbmUyLCBwb2ludF90eXBlKDQ1LjA5NDk3MiwgMzcuNTY1MDc2KSk7CiAgICBiZzo6YXBwZW5kKGxpbmUyLCBwb2ludF90eXBlKDQ1LjA5NDkzNCwgMzcuNTY1MzA3KSk7CgogICAgLy8g0J/RgNC+0LLQtdGA0LrQsCDQutC+0LvQuNC90LXQsNGA0L3QvtGB0YLQuAogICAgaWYgKGFyZV9jb2xsaW5lYXIobGluZTEsIGxpbmUyKSkgewogICAgICAgIHN0ZDo6Y291dCA8PCAi0JvQuNC90LjQuCDQutC+0LvQuNC90LXQsNGA0L3Riy4iIDw8IHN0ZDo6ZW5kbDsKICAgIH0gZWxzZSB7CiAgICAgICAgc3RkOjpjb3V0IDw8ICLQm9C40L3QuNC4INC90LUg0LrQvtC70LjQvdC10LDRgNC90YsuIiA8PCBzdGQ6OmVuZGw7CiAgICB9CgogICAgcmV0dXJuIDA7Cn0=