← Все вопросы

Как найти точку пересечения двух прямых, заданных парами точек?

Задан 26 месяцев назад657 просмотров2 ответа
7

Отрезки уже умею пересекать по факту да/нет. Теперь нужны сами координаты точки пересечения двух прямых (каждая задана двумя точками). Как вывести формулу через косые произведения и что делать с параллельными прямыми?

2 ответа

11
✓ Принятый ответ — помог автору

Удобнее всего через косые произведения. Пусть прямые заданы точками A,B и C,D. Параметризуем первую прямую как A + t*(B-A). Тогда:

// возвращает true и точку пересечения; false если прямые параллельны
bool lineInter(const P& a, const P& b, const P& c, const P& d, pair<double,double>& res) {
    long long d1 = (b - a).cross(d - c); // знаменатель
    if (d1 == 0) return false;           // параллельны (или совпадают)
    long long t_num = (c - a).cross(d - c);
    double t = (double)t_num / d1;
    res = { a.x + t * (b.x - a.x), a.y + t * (b.y - a.y) };
    return true;
}

Идея: знаменатель (B-A) × (D-C) равен нулю ровно когда направляющие векторы прямых коллинеарны, то есть прямые параллельны. Если он не ноль, параметр t находится одним делением, и точка пересечения — линейная комбинация.

Числитель и знаменатель считаются в long long точно; деление переводит в double только в самом конце. Сложность O(1). Если нужна точная рациональная точка — храни числитель и знаменатель отдельно и не делай деление вовсе.

5

Два уточнения. Первое: d1 == 0 означает параллельность, но прямые могут ещё и совпадать — тогда пересечение бесконечно. Чтобы их различить, при нулевом знаменателе проверь orient(a, b, c) == 0: если да — прямые совпадают, иначе просто параллельны и не пересекаются.

Второе: эта формула даёт пересечение прямых, а не отрезков. Если нужно пересечение именно отрезков, после нахождения t проверь 0 <= t <= 1 и аналогичный параметр для второй прямой. Для отрезков чаще удобнее сначала вызвать segInter (да/нет), и только при true — считать координаты.

Ваш ответ

Войдите, чтобы ответить на вопрос.