De ce contează?
Ai un teren cu colțuri marcate prin țăruși, iar pentru fiecare țăruș cunoști coordonatele pe o hartă. Cum afli suprafața, fără să-l împarți în dreptunghiuri și fără să măsori unghiuri? Există o formulă care primește doar lista colțurilor, în ordine pe contur, și îți scoate aria direct. O numim formula șiretului (shoelace), pentru că se calculează încrucișând coordonatele exact ca atunci când îți legi șireturile.
Aria triunghiului prin produsul vectorial
Pleci de la trei puncte A, B, C cu coordonate întregi. Produsul vectorial
al laturilor AB și AC, calculat ca scalar în plan, este:
cross(A, B, C) = (xB - xA)*(yC - yA) - (yB - yA)*(xC - xA)Acest număr este chiar dublul ariei orientate a triunghiului. De ce? cross
măsoară aria paralelogramului construit pe vectorii AB și AC; triunghiul este
exact jumătatea acelui paralelogram. Așadar aria triunghiului este:
arie = |cross(A, B, C)| / 2Iei modulul fiindcă cross poate fi negativ (depinde de ordinea punctelor), dar
aria este mereu pozitivă. Dacă cross iese 0, punctele sunt coliniare.
Formula shoelace pentru poligon
Pentru un poligon oarecare cu n vârfuri date în ordine pe contur,
P0, P1, ..., P(n-1), aria se obține însumând câte un produs încrucișat pentru
fiecare latură:
2 * arie = | sum (xi * y(i+1) - x(i+1) * yi) |, i = 0 .. n-1unde, la ultimul termen, P(n) înseamnă P0 — adică închizi poligonul
legând ultimul vârf cu primul. Fiecare latură contribuie cu un mic cross față
de origine, iar suma lor dă dublul ariei.
Înainte de modul, semnul sumei îți spune orientarea: dacă suma este pozitivă, ai parcurs vârfurile în sens trigonometric (antiorar); dacă este negativă, în sens orar. Aceasta este aria cu semn. Pentru mărimea propriu-zisă a suprafeței, iei modulul și împarți la 2 la final.
Exemplu pas cu pas
Începem cu triunghiul A(0,0), B(4,0), C(0,3). Aplici direct produsul
vectorial:
cross = (4 - 0)*(3 - 0) - (0 - 0)*(0 - 0) = 4*3 - 0 = 12arie = |12| / 2 = 6
Verifici cu shoelace, închizând conturul A -> B -> C -> A:
- latura
A->B:0*0 - 4*0 = 0 - latura
B->C:4*3 - 0*0 = 12 - latura
C->A:0*0 - 0*3 = 0 - suma
= 0 + 12 + 0 = 12, deciarie = |12| / 2 = 6. Identic.
Acum un patrulater mic, pătratul (0,0), (2,0), (2,2), (0,2), parcurs antiorar:
0*0 - 2*0 = 02*2 - 2*0 = 42*2 - 0*2 = 40*0 - 0*2 = 0- suma
= 8, pozitivă (orientare trigonometrică),arie = 8 / 2 = 4. Corect, pătratul cu latura 2 are aria 4.
Implementare C++
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
struct Punct {
long long x, y;
};
// dublul ariei orientate a triunghiului ABC (poate fi negativ)
long long cross(Punct A, Punct B, Punct C) {
return (B.x - A.x) * (C.y - A.y) - (B.y - A.y) * (C.x - A.x);
}
// shoelace: dublul ariei orientate a poligonului (poate fi negativ)
long long dublulAriei(const vector<Punct>& p) {
long long s = 0;
int n = (int)p.size();
for (int i = 0; i < n; i++) {
int j = (i + 1) % n; // inchide poligonul: ultimul cu primul
s += p[i].x * p[j].y - p[j].x * p[i].y;
}
return s; // semnul = orientarea
}
int main() {
Punct A = {0, 0}, B = {4, 0}, C = {0, 3};
long long dt = llabs(cross(A, B, C));
cout << dt / 2; // 6
if (dt % 2 == 1) cout << ".5"; // arie semi-intreaga
cout << "\n";
vector<Punct> patrat = {{0, 0}, {2, 0}, {2, 2}, {0, 2}};
long long d = dublulAriei(patrat); // 8 (orientare antiorara)
long long dp = llabs(d);
cout << dp / 2; // 4
if (dp % 2 == 1) cout << ".5";
cout << "\n";
return 0;
}Ții peste tot dublul ariei ca întreg pe long long, fără să împarți pe
parcurs. Abia la final împarți la 2; dacă restul împărțirii este 1, aria are o
jumătate (de exemplu 6.5). Înainte de modul, semnul sumei îți dă gratis
orientarea: pozitiv = trigonometric, negativ = orar.
- Uiți
/2sau modulul:crossși suma shoelace dau dublul ariei cu semn. Fără modul poți obține arie negativă; fără/2obții un rezultat de două ori prea mare. - Nu închizi poligonul: ultima latură trebuie să lege ultimul vârf cu primul.
Dacă sari peste termenul
P(n-1) -> P0, aria iese greșită. Foloseștej = (i + 1) % n. - Overflow fără
long long: produselexi * y(i+1)pot depășiintcând coordonatele sunt mari. Ține suma pelong long. - Folosești
floatsaudouble: pierzi precizie când aria e de fapt întreagă. Lucrează pe întregi, păstrând dublul ariei.
| varf | (0 | 0) | (4 | 0) | (0 | 3) |
A | B | C | ||||
start | final |
Vizualizare
Vezi distanța și aria calculate pe plan; folosește ← / → pentru a avansa pas cu pas.
Recapitulare
- Aria unui triunghi este
|cross(A,B,C)| / 2, undecrosseste dublul ariei orientate dat de produsul vectorial al laturilor. - Formula shoelace generalizează ideea: însumezi
xi*y(i+1) - x(i+1)*yipe toate laturile, închizând poligonul, iei modulul și împarți la 2. - Pe coordonate întregi ții dublul ariei ca
long long; semnul sumei dă orientarea, iar împărțirea la 2 vine la final ca să nu pierzi precizia.