Descriere
Implementare
Aplicatii
|
|
Lucrarea nr. 3
Primitive grafice
A.Descriere
1.Definitii:
Se numeste element geometric de baza o entitate geometrica simpla, necesara in mod frecvent in descrierea scenelor grafice. O realizare a unui element geometric de baza intr-un sistem grafic (implementarea acestuia) se numeste element grafic de baza.
Cele mai simple elemente grafice de baza sunt: punctul, segmentul de dreapta, arcul de cerc, cercul. Elementele grafice de baza sunt recunoscute de sistem fie prin ecuatii analitice, fie printr-un set reprezentativ de puncte din care se pot deduce ecuatii analitice. De exemplu, un cerc poate fi generat pe dispozitivul de iesire pornind de la ecuatia:
x2 + y2 = r2
sau precizand doua puncte diametral opuse A(x1, y1) , B(x2, y2).
Pentru fiecare element grafic de baza, in sistem este prevazuta o rutina grafica (procedura) a carei executie poate produce imaginea sa pe dispozitivul de iesire (ecran). Aceste rutine grafice vor fi numite in continuare primitive grafice de iesire (pe scurt, primitive grafice). Deoarece in procesul reprezentarii scenelor grafice aceste primitive se executa de un numar considerabil de ori (ele stand la baza celorlalte elemente grafice) este necesar ca ele sa fie realizate eficient din punct de vedere a timpilor de executie. Din acest considerent ele se implementeaza in limbaj de asamblare, utilizand algoritmi specializati. In cadrul lucrarii vom considera ca primitivele grafice pentru punct si segmentul de dreapta sunt disponibile sub forma procedurilor PUTPIXEL si LINE din unitatea GRAPH. In afara acestor proceduri, vom defini si implementa rutine grafice pentru urmatoarele elemente grafice de baza:
- linia poligonala
- dreptunghiul
- cercul
- arcul de cerc
Acest set de primitive grafice poate fi extins dupa necesitati.
2.Reprezentarea curbelor plane.
Implementarea primitivelor grafice poate porni de la ecuatiile analitice ale elementelor grafice de baza. Este doesebit de util ca sistemul grafic sa prevada si procedura generala pentru reprezentarea curbelor plane descrise analitic.
Ecuatia unei curbe plane poate fi data in una din formele:
- forma explicita y=f(x) in coordonate carteziene sau polare. In acest caz pentru fiecare valoare a lui x se poate gasi o singura valoare y. Curbele inchise sau cu mai multe variabile nu pot fi descrise printr-o singura ecuatie explicita.
- forma implicita f(x, y)=0 descrie atat curbele deschise cat si pe cele inchise sau cu mai multe ramuri, dar sunt dificil de utilizat.
- forma parametrica, in care fiecare coordonata a unui punct p(x, y) al curbei este data ca o functie dependenta de un parametru:
x=x(t)
y=y(t)
cu parametrul t in intervalul [a,b].
Vectorul de pozitie al unui punct al curbei este
p(t) = [x(t), y(t)]
Reprezentarea parametrica a unui segment de dreapta definit de punctele
P1(x1, y1) si P2(x2, y2) este:
P(t) = P1 + (P2 - P1)*t,
sau
x(t) = x1 + (x2 - x1)*t
y(t) = y1 + (y2 – y1)*t
cu t in intervalul [0,1]
iar pentru un cerc cu centrul in origine si raza R:
P(t) = [R*cos(t), R*sin(t)]
sau
x(t) = R*cos(t)
y(t) = R*sin(t)
cu t in [0,2PI].
Reprezentarea curbelor se poate face prin aproximare cu o secventa de segmente de dreapta. Aceste segmente sunt determinate de cresteri egale ale parametrului. Numarul de segmente utilizate se alege tinand cont de aspectul grafic al imagini rezultate.
Procedura generala pentru trasarea curbelor parametrice are ca parametri cele doua functii care descriu ecuatiile:
x = x(t)
y = y(t)
si limitele variatiei parametrului.
B. Implementare
In cadrul acestei lucrari se vor
implementa procedurile si functiile necesare pentru:
- trasarea curbelor
parametrice
- trasarea cercurilor, arcelor
de cerc
- trasarea liniilor poligonale
- trasarea dreptunghiurilor
Aceste proceduri si functii se
includ in modulul G2Dprimitive.
/*======================================================================*/
/* G2Dprimitive.h */
/*======================================================================*/
/* Numarul maxim de varfuri permis pentru o linie poligonala */
#define NVMAX 50
/* lista varfurilor unei linii poligonale deschise */
typedef struct _lista_puncte
{
int n;
double x[NVMAX];
double y[NVMAX];
} lista_puncte;
/* pentru transmiterea functiilor parametru */
typedef double (*functie)(double);
/*
* Stabileste numarul de segmente prin care se vor
* aproxima curbele generate prin procedura curba ().
*/
extern void set_nr_segm (int n);
/*
* traseaza curba cu ecuatiile parametrice date de xfn, yfn,
* pe domeniul de variatie (t1,t2) al parametrului.
*/
extern void curba (functie xfn, functie yfn, double t1, double t2);
/*
* Traseaza o linie poligonala ale carei varfuri sunt precizate in
* variabila lista.
*/
extern void polilinie (lista_puncte lista);
/*
* Produce un dreptunghi cu coltul stanga jos x1,y1, iar
* coltul dreapta sus x2,y2.
*/
extern void dreptunghi (double x1, double y1, double x2, double y2);
/*
* Produce un cerc cu centrul in x,y si raza 'raza'
*/
extern void cerc (double x, double y, double raza);
/*
* Calculeaza centrul si raza unui cerc cunoscand coordonatele
* a doua puncte diametral opuse de pe cerc.
*/
extern void conversie_cerc (double x1, double y1, double x2, double y2,
double *xc, double *yc, double *r);
/*
* Produce un arc de cerc cu centrul in x,y si raza 'raza'.
* Punctul de start este fixat de unghiul t1, iar cel final
* de unghiul t2, in sens trigonometric.
*/
extern void arc (double x, double y, double raza, double t1, double t2);
/*
* Calculeaza elementele necesare trasarii unui arc de cerc,
* cunoscand trei puncte reprezentative ale arcului.
*/
extern void conversie_arc (double x1, double y1,
double x2, double y2, double x3, double y3,
double *xc, double *yc, double *r,
double *t1, double *t2);
/*======================================================================*/
/* End of G2Dprimitive.h */
/*======================================================================*/
/*======================================================================*/
/* G2Dprimitive.c */
/*======================================================================*/
#include <stdio.h>
#include <math.h>
#include "G2Dprimitive.h"
#include "G2Dnucleu.h"
/* Structuri private ---------------------------------------------------*/
/* numar de segmente utilizat de curba() pentru trasare */
static int nrseg = 50;
static double xc, yc;
static double ra, r;
static double ta, tb;
/* Prototipuri Private -------------------------------------------------*/
static double theta (double x, double y, double xc, double yc);
static double xfn (double t);
static double yfn (double t);
/* Rutine publice ------------------------------------------------------*/
/*
* Produce un dreptunghi cu coltul stanga jos x1,y1, iar
* coltul dreapta sus x2,y2.
*/
void
dreptunghi (double x1, double y1, double x2, double y2)
{
linie_2d (x1, y1, x1, y2);
linie_2d (x1, y2, x2, y2);
linie_2d (x2, y2, x2, y1);
linie_2d (x2, y1, x1, y1);
} /* dreptunghi */
/*
* Stabileste numarul de segmente prin care se vor
* aproxima curbele generate prin procedura curba ().
*/
void
set_nr_segm (int n)
{
nrseg = n;
} /* set_nr_segm */
/*
* traseaza curba cu ecuatiile parametrice date de xfn, yfn,
* pe domeniul de variatie (t1,t2) al parametrului.
*/
void
curba (functie xfn, functie yfn, double t1, double t2)
{
double delta_t;
double x1, y1;
double x2, y2;
double t;
int i;
delta_t = (t2 - t1) / nrseg;
x1 = xfn (t1); y1 = yfn (t1);
t = t1;
for (i = 0; i < nrseg; i++)
{
t += delta_t;
x2 = xfn (t); y2 = yfn (t);
linie_2d (x1, y1, x2, y2);
x1 = x2; y1 = y2;
}
} /* curba */
/*
* Traseaza o linie poligonala ale carei varfuri sunt precizate in
* variabila lista.
*/
void
polilinie (lista_puncte lista)
{
/* Definitia procedurii polilinie */
} /* polilinie */
/*
* Produce un cerc cu centrul in x,y si raza 'raza'
*/
void
cerc (double x, double y, double raza)
{
xc = x; yc = y;
r = raza;
curba (xfn, yfn, 0.0, M_2PI);
} /* cerc */
/*
* Calculeaza centrul si raza unui cerc cunoscand coordonatele
* a doua puncte diametral opuse de pe cerc.
*/
void
conversie_cerc (double x1, double y1, double x2, double y2,
double *xc, double *yc, double *r)
{
*xc = (x1 + x2) / 2.0;
*yc = (y1 + y2) / 2.0;
*r = sqrt ((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) / 2.0;
} /* conversie_cerc */
/*
* Produce un arc de cerc cu centrul in x,y si raza 'raza'.
* Punctul de start este fixat de unghiul t1, iar cel final
* de unghiul t2, in sens trigonometric.
*/
void
arc (double x, double y, double raza, double t1, double t2)
{
xc = x; yc = y;
r = raza;
curba (xfn, yfn, t1, t2);
} /* arc */
/*
* Calculeaza elementele necesare trasarii unui arc de cerc,
* cunoscand trei puncte reprezentative ale arcului.
*/
void
conversie_arc (double x1, double y1,
double x2, double y2, double x3, double y3,
double *xc, double *yc, double *r,
double *t1, double *t2)
{
double det1;
double det2;
double det;
det1 = (x2*x2 - x1*x1 + y2*y2 - y1*y1) * (y3 - y1) -
(x3*x3 - x1*x1 + y3*y3 - y1*y1) * (y2 - y1);
det2 = (x3*x3 - x1*x1 + y3*y3 - y1*y1) * (x2 - x1) -
(x2*x2 - x1*x1 + y2*y2 - y1*y1) * (x3 - x1);
det = (x2-x1) * (y3-y1) - (y2-y1)*(x3-x1);
*xc = det1 / det / 2.0;
*yc = det2 / det / 2.0;
*r = sqrt ((x1 - *xc)*(x1 - *xc) * (y1 - *yc)*(y1 - *yc));
*t1 = theta (x1, y1, *xc, *yc);
*t2 = theta (x3, y3, *xc, *yc);
if (*t1 > *t2)
*t2 += M_2PI;
} /* conversie_arc */
/* Rutine Private ------------------------------------------------------*/
static double
xfn (double t)
{
return (xc + r*cos(t));
} /* xfn */
static double
yfn (double t)
{
return (yc + r*sin(t));
} /* yfn */
/*
* Determina unghiul format de segmentul (xc,yc),(x,y) cu
* sensul pozitiv al axei Ox.
*/
static double
theta (double x, double y, double xc, double yc)
{
double dx, dy;
double th;
double k;
dx = x - xc; dy = y - yc;
if (0.0 == dx)
{
if (dy > 0.0)
th = M_PI_2;
else
th = 3 * M_PI_2;
}
else
{
th = atan (dy/dx);
if (dx < 0.0)
k = 1.0;
else
{
if (dy >= 0.0)
k = 0.0;
else
k = 2.0;
}
th += k * M_PI;
}
return (th);
} /* theta */
/*======================================================================*/
/* End of G2Dprimitive.c */
/*======================================================================*/
Download G2Dprimitive.h,
G2Dprimitive.c.
C. Aplicatii
1. Realizati unitatea G2D_PRIMITIVE.
2. Scrieti programe de aplicatie pentru generarea urmatoarelor curbe:
x(t) = a*cos(t)
y(t) = b*sin(t),
0<= t <=2*PI, a, b = numere reale
x(t) = a*cos3(t)
y(t) = b*sin3(t),
0<= t <=2*PI, a, b = numere reale
x(t) = a*cos(t)+b*cos(c*t)
y(t) = a*sin(t)+b*sin(c*t),
0<= t <=5*PI, a, b, c = numere reale
Observatie: Pentru fiecare curba se va stabili o fereastra corespunzatoare.
3. Scrieti un program de aplicatie care realizeaza urmatoarea schita:
Observatie: Cercul si
arcul de cerc se definesc cunoscand 2, respectiv 3 puncte reprezentative. In acest
caz este necesara conversia parametrilor de definitie in parametrii acceptati de
procedurile pentru trasarea cercului respectiv arcului de cerc, utilizand in acest
scop procedurile conversie_cerc respectiv conversie_arc.
Exemplu:
conversie_cerc(x1, y1, x2, y2, xc, yc,r);
/* parametrii de intrare reprezinta coordonatele
a doua puncte diametral opuse */
cerc(xc, yc,r);
|