Arii — produsul vectorial și formula shoelace

Greu~17 min9 pași

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)| / 2

Iei 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-1

unde, 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 = 12
  • arie = |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, deci arie = |12| / 2 = 6. Identic.

Acum un patrulater mic, pătratul (0,0), (2,0), (2,2), (0,2), parcurs antiorar:

  • 0*0 - 2*0 = 0
  • 2*2 - 2*0 = 4
  • 2*2 - 0*2 = 4
  • 0*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;
}
Observația-cheie

Ț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.

Greșeli frecvente
  • Uiți /2 sau modulul: cross și suma shoelace dau dublul ariei cu semn. Fără modul poți obține arie negativă; fără /2 obț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ște j = (i + 1) % n.
  • Overflow fără long long: produsele xi * y(i+1) pot depăși int când coordonatele sunt mari. Ține suma pe long long.
  • Folosești float sau double: 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
Triunghiul exemplu, parcurs A -> B -> C si inchis spre A. cross = 12, aria = 6.

Vizualizare

Indiciu

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, unde cross este dublul ariei orientate dat de produsul vectorial al laturilor.
  • Formula shoelace generalizează ideea: însumezi xi*y(i+1) - x(i+1)*yi pe 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.

Întrebarea 1 / 3

Pentru triunghiul A(0,0), B(4,0), C(0,3), cât e `cross(A,B,C)` și cât e aria?