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 = 2b = 0 - 4 = -4c = -(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;
}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.
- Uiți modulul și raportezi o distanță negativă. Distanța e mereu
≥ 0; punellabs(...)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·x0poate depășiintla coordonate mari. Ținea,b,cșia·x0 + b·y0 + cpelong 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 (AsauB), 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) |
Recapitulare
- Distanța de la
P(x0, y0)laa·x + b·y + c = 0este|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ștesqrt(double) doar la final.