Distanța de la punct la dreaptă — cea mai scurtă cale

Greu~16 min9 pași

De ce contează?

Stai lângă un copac și vrei să ajungi cât mai repede la un gard lung și drept. Nu mergi oblic spre un capăt al gardului — mergi drept spre el, pe direcția perpendiculară. Acea perpendiculară este cea mai scurtă cale, iar lungimea ei este distanța de la tine (punctul) la gard (dreapta).

Formula

O dreaptă se scrie sub forma generală a·x + b·y + c = 0, unde a, b, c sunt numere fixe. Pentru un punct P(x0, y0), distanța de la P la dreaptă este:

d = |a·x0 + b·y0 + c| / sqrt(a^2 + b^2)

De unde vine? Perechea (a, b) este vectorul normal la dreaptă — un vector perpendicular pe ea. Expresia a·x0 + b·y0 + c proiectează poziția punctului pe direcția acestui normal: cât de „departe” e punctul față de dreaptă, măsurat pe perpendiculară. Dar rezultatul e scalat cu lungimea normalului, care e sqrt(a^2 + b^2). Împărțind la ea, normalizezi și obții distanța reală.

Modulul |...| apare fiindcă distanța nu poate fi negativă: nu ne interesează pe ce parte a dreptei stă punctul, ci doar cât de aproape e.

Legătura cu aria și produsul vectorial

Există o a doua cale, mai geometrică. Dacă dreapta trece prin punctele A și B, iar P e punctul nostru, atunci A, B, P formează un triunghi. Aria lui se poate calcula cu produsul vectorial:

2·arie = |(B - A) × (P - A)|

Pe de altă parte, aria oricărui triunghi este (bază · înălțime) / 2. Dacă luăm ca bază segmentul AB, atunci înălțimea coborâtă din P este exact distanța de la P la dreapta AB. Deci:

d = 2·arie / bază = |(B - A) × (P - A)| / |AB|

Aceasta este aceeași formulă: produsul vectorial joacă rolul numărătorului (e legat de a·x0 + b·y0 + c), iar lungimea bazei |AB| joacă rolul lui sqrt(a^2 + b^2). Două drumuri, același rezultat.

Exemplu pas cu pas

Fie dreapta care trece prin A(0, 0) și B(4, 2), și punctul P(1, 3).

Întâi scriem dreapta sub forma generală. Coeficienții se obțin din cele două puncte: a = yB - yA, b = xA - xB, c = -(a·xA + b·yA).

  • a = 2 - 0 = 2
  • b = 0 - 4 = -4
  • c = -(2·0 + (-4)·0) = 0

Deci dreapta este 2x - 4y = 0. Verificăm că A și B o satisfac: pentru B(4, 2) avem 2·4 - 4·2 = 8 - 8 = 0. Corect.

Acum aplicăm formula pentru P(1, 3):

  • numărător: |2·1 + (-4)·3 + 0| = |2 - 12| = |-10| = 10
  • numitor: sqrt(2^2 + (-4)^2) = sqrt(4 + 16) = sqrt(20)
  • d = 10 / sqrt(20) ≈ 2.236

Observă semnul înainte de modul: 2 - 12 = -10 e negativ, deci P se află pe o anumită parte a dreptei. Modulul îl face pozitiv pentru distanță.

Implementare C++

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    // dreapta prin doua puncte A si B
    long long xA = 0, yA = 0;
    long long xB = 4, yB = 2;

    // punctul P fata de care masuram
    long long x0 = 1, y0 = 3;

    // forma generala a*x + b*y + c = 0 din A si B
    long long a = yB - yA;          // 2
    long long b = xA - xB;          // -4
    long long c = -(a * xA + b * yA); // 0

    // numaratorul pe long long, ca sa nu pierdem precizie / overflow
    long long numarator = a * x0 + b * y0 + c; // -10 (cu semn)

    // numitorul si distanta finala in double, doar la sfarsit
    double numitor = sqrt((double)(a * a + b * b)); // sqrt(20)
    double d = llabs(numarator) / numitor;          // |-10| / sqrt(20)

    cout << "a=" << a << " b=" << b << " c=" << c << "\n"; // a=2 b=-4 c=0
    cout << "numarator (cu semn) = " << numarator << "\n"; // -10
    cout << "distanta = " << d << "\n";                    // ~2.236068

    return 0;
}
Observația-cheie

Numărătorul a·x0 + b·y0 + c fără modul îți spune pe ce parte a dreptei stă punctul: pozitiv într-un semiplan, negativ în celălalt, zero exact pe dreaptă. Aceeași expresie cu modul, împărțită la sqrt(a^2 + b^2), devine distanța. Așa că poți afla și poziția, și distanța dintr-un singur calcul.

Greșeli frecvente
  • Uiți modulul și raportezi o distanță negativă. Distanța e mereu ≥ 0; pune llabs(...) pe numărător înainte de împărțire.
  • Uiți să normalizezi — adică împărțirea la sqrt(a^2 + b^2). Fără ea ai doar produsul vectorial (de două ori aria), nu distanța în unități.
  • Overflow la numărător: a·x0 poate depăși int la coordonate mari. Ține a, b, c și a·x0 + b·y0 + c pe long long; sqrt (double) doar la final.
  • Confuzi distanța la dreaptă cu distanța la segment: dreapta e infinită, deci perpendiculara cade mereu pe ea. La un segment [AB], dacă piciorul perpendicularei iese în afara segmentului, cea mai apropiată distanță e până la un capăt (A sau B), nu formula de mai sus.

Vizual, distanța e segmentul perpendicular dintre P și dreaptă:

puncte
A(0
0)
B(4
2)
P(1
3)
P este evidențiat; dreapta trece prin A și B. Distanța = perpendiculara din P pe dreapta AB.

Recapitulare

  • Distanța de la P(x0, y0) la a·x + b·y + c = 0 este |a·x0 + b·y0 + c| / sqrt(a^2 + b^2): proiecție pe normal, apoi normalizare.
  • Geometric e același lucru cu d = 2·arie / bază, unde aria vine din produsul vectorial al laturilor triunghiului.
  • Ține numărătorul pe long long, pune modulul și împarte la lungimea normalului; folosește sqrt (double) doar la final.

Întrebarea 1 / 3

Pentru dreapta `2x - y + 1 = 0` și punctul `P(3, 2)`, cât este numărătorul `|a·x0 + b·y0 + c|`?