Două drepte sunt paralele când formează unghiuri egale cu orizontala, adică au pante
egale: sau
1: sau
Separarea planului
Evident, expresia ax + by + c va fi zero pentru toate punctele (x, y) de pe dreaptă (în mod
tautologic). Ce este interesant este că expresia are valori pozitive pentru toate punctele de
o parte a dreptei și valori negative pentru toate punctele de cealaltă parte a dreptei.
O întrebare frecventă este: dându-se trei puncte A, B, și C, sunt ele (a) date în ordine
trigonometrică sau (b) date în ordine orară sau (c) coliniare?
Cazuri particulare
O bună parte din arta implementării unui algoritm de geometrie computațională este
tratarea cazurilor particulare:
coliniaritate
intersecții exact la un capăt al segmentului
pante infinite (pentru drepte verticale)
Uneori puteți elimina cazurile particulare scriind bine formula. Exemplu: două
if (y1 / x1 == y2 / x2) {
...
}
Putem trata punctele de pe axa Ox printr-un caz particular, sau, mai simplu, putem înlocui
formula cu una echivalentă, dar fără împărțiri:
if (y1 * x2 == y2 * x1) {
...
}
Erori de calcul
În gcc, tipurile float, double și long double au 4, 8 și respectiv 16 octeți. Țineți minte aceste
numere ca să vă puteți face necesarul de memorie.
Indiferent de precizie, în funcție de problemă puteți ajunge la valori ușor diferite pentru
formule teoretic egale, în funcție de ordinea operațiilor. De aceea poate fi mai sănătos să
nu testați egalitatea cu
if (x == y) {
...
}
, ci cu
Operații costisitoare
Țineți minte că adunarea / scăderea, înmulțirea, împărțirea, sqrt, sin / cos, log / exp sunt
funcții tot mai costisitoare. Întrebați-vă mereu cum puteți rescrie o formulă pentru a folosi
operații cât mai de la începutul listei.
Pentru a exemplifica observațiile de mai sus, vom discuta algoritmul lui Bresenham. El
trasează un segment între doi pixeli (puncte de coordonate întregi) (x1, y1) și (x2, y2). Se
pune, deci, problema enumerării tuturor pixelilor segmentului.
Algoritmul naiv spune: datorită unghiului, toți pixelii au coordonata x diferită. Iterăm deci de
la x1 la x2 și calculăm coordonata y corectă pe acea coloană. Ea se obține rotunjind
coordonata y teoretică la cel mai apropiat întreg.
O variantă mai bună precalculează panta și face împărțiri și înmulțiri înainte de bucla
principală, iar în buclă face doar adunări. Ideea este că, de câte ori x crește cu 1, y crește
cu valoarea pantei. Apoi yeste rotunjit la cel mai apropiat inel.
int abatere = 0;
int y = y1;
for (int x = x1; x <= x2; x++) {
// afișează pixelul (x, y)
abatere += y2 - y1;
if (2 * abatere > x2 - x1) {
y++;
abatere -= x2 - x1;
}
}
Observăm că acum abaterea va fi mereu cuprinsă între . Pentru maximum de
eficiență, înmulțirea cu 2 poate fi exprimată ca shiftare, iar cantitățile x2 - x1 și y2 - y1 pot fi
precalculate în afara buclei.
1. Arii
Noţiunea de arie este una de bază în geometria analitică. Este necesară însă o
prezentare a diferitelor metode de a calcula ariile in contextul prelucrarii
datelor pe calculator.
Pentru un patrulater oarecare ABCD, putem considera M1, M2, M3, M4 mijloacele
laturilor acestuia. Se poate demonstra că patrulaterul M1M2M3M4 este un
paralelogram cu aria jumătate din aria lui ABCD:
Aria unui poligon
Pentru a calcula aria unui poligon oarecare A1A2A3..An, vom considera un punct
P arbitrar ales în plan. Vom "împărţi" poligonul în triunghiuri de
forma PAiAi+1 (considerăm că A1=An+1) şi vom calcula "aria cu semn" Ti a
fiecărui triunghi (în formula ariei nu vom folosi funcţia de valoare absolută).
Distingem în acest moment două cazuri:
Poligonul are vârfurile orientate trigonometric. Pentru fiecare latură
"spre dreapta", aria Ti corespunzătoare va fi negativă, iar pentru fiecare
latură "spre stânga", aria Ticorespunzătoare va fi pozitivă.
Poligonul are vârfurile orientate antitrigonometric. Pentru fiecare latură
"spre dreapta", aria Ti corespunzătoare va fi pozitivă, iar pentru fiecare
latură "spre stânga", aria Ticorespunzătoare va fi negativă.
În ambele cazuri, efectuând suma algebrică a ariilor Ti vom obţine aria
poligonului (deoarece ariile negative vor "anula" zonele corespunzătoare ariilor
pozitive care se află în afara poligonului).
Dacă alegem punctul P(0,0), fiecare arie Ti devine:
, unde
De asemenea, fiind date doua puncte A(x1, y1) si B(x2, y2), ecuatia dreptei
determinate de ele se poate scrie
Aceasta poate sa nu ne fie de prea mare ajutor, dar facand produsul mezilor cu
extremii si desfacand parantezele vom
sau
Proprietati:
• Doua drepte care au pantele egale sunt ori paralele ori confundate.
• Doua drepte care au produsul pantelor egal cu -1 sunt perpendiculare.
Distanta dintre un punct si o dreapta
Pentru a calcula distanta care ne trebuie noua vom calcula panta
dreptei d1 notata cu m1. Acum vrem sa construim o dreapta d2 perpendiculara
pe dreapta d1 care trece prin punctul A. Stim ca m1*m2=-1 si de aici aflam
usor m2 (panta dreptei d2). In acest moment avem panta dreptei d2 si un punct
care ii apartine. Avand aceste 2 informatii putem sa calculam usor ecuatia ei si
punctul de intersectie cu dreapta d1 (Vezi capitolul Drepte). Distanta dintre
dreapta si punct va fi egala cu distanta dintre punct si punctul de intersectie al
celor 2 drepte.
De asemenea exista si o formula pt a determina distanta de la un punct la o
dreapta: considerand punctul A(x0,y0) si dreapta d:ax+by+c=0, vom avea :
#include<fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
void afisare(interval x)
{
fout<<"["<<x.a<<","<<x.b<<"] ";
}
int main()
{
int n,i,max1=0,max2=0,k,ls,p;
interval x[100];
fin>>n;
for(i=1;i<=n;i++) citire(x[i]);
ordonarea(n,x);
k=1;
ls=x[1].b;
i=2;
while(i<=n)
{ if(x[i].a<=ls)
{
k++;
if(x[i].b<ls) ls=x[i].b;
}
else
{
if(k>max1) max1=k;
k=1;
p=i;
while(x[i-1].b>=x[p].a && i>=1) i--;
ls=x[i].b;
}
i++;
}
if(k>max1) max1=k;
fout<<max1;
fout<<endl;
ordonareb(n,x);
max2=1;
afisare(x[1]);
ls=x[1].b;
for(i=2;i<=n;i++)
if(x[i].a>ls)
{ max2++;
afisare(x[i]);
ls=x[i].b;
}
fout<<max2;
fin.close();
fout.close();
return 0;}
Descriere:
Fie într-un sistem cartezian de coordonate un punct p de coordonate (x, y). Deplasarea de
coordonate de-a lungul axei Ox cu o valoare dată a implică o modificare a coordonatelor punctului
conform formulelor:
Program
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <iostream.h>
#include <dos.h>
void initiere_rg()
{
int gdriver = DETECT, gmode, errorcode;
initgraph(&gdriver, &gmode, "");
}
void generate_points(int n)
{ randomize();
for (i=0;i<n;i++)
{ a[i].x=20+60*random(10); a[i].y=20+40*random(10); }
}
int main(void)
{
cout <<"numarul de puncte: " ; cin >>n;
cout << "deplasare X: "; cin >>dx;
cout << "deplasare Y: "; cin >>dy;
initiere_rg();
sistem_coordonate(3);
generate_points(n);
draw_set(n,15);
/* deplasarea */
if (dx>0) h=1; else h=-1;
for (j=0; j<abs(dx); j++)
{
draw_set(n,0);
for (i=0;i<n;i++) {a[i].x=a[i].x+h;
a[i].y=a[i].y+(dy/dx)*h;
}
draw_set(n,15); delay(100);
}
getch();
closegraph();
return 0;
}
Exemplul 1:
unde p1, p2 reprezintă punctele, care determină dreapta, iar A, B, C – coeficienţii ecuaţiei generale a
dreptei.
Introducerea şi afişarea datelor: datele se introduc din fişierul text date.in, cu următoarea structură:
x1 y1
x2 y2
x3 y3
x4 y4
fişierul conţine patru linii. Fiecare linie conţine coordonatele unui punct, separate prin spaţiu, în
ordinea x, y. Linia i a fişierului conţine descrierea punctului cu indicele i.
0 3
3 0
0 0
3 3
0 3
3 0
1 2
2 1