Descriere
Implementare
Aplicatii
|
|
A.Descriere
1. Transformari grafice ale obiectelor
Transformarea unui obiect grafic implica
transformarea obiectelor grafice de baza care il compun. Aceste elemente
fiind definite printr-un set de puncte, transformarea se va aplica asupra
tuturor punctelor de definitie. In urma transformarii, punctele de definitie
isi vor modifica coordonatele, iar imaginea obiectului transformat se va
obtine prin reexecutarea primitivelor grafice asociate elementelor grafice
de baza care il compun.
2. Instantierea obiectelor
grafice
Atunci cand se utilizeaza pachetul
grafic pentru reprezentarea, de exemplu a unui circuit electric,
unele simboluri sunt necesare de mai multe ori. Fiecare simbol distinct
poate fi considerat un obiect grafic. Diversele aparitii ale unui simbol sunt noi realizari ale acestuia, aparand
insa (posibil) in pozitii variate si avand alte dimensiuni. Crearea mai
multor copii (realizari) ale aceluiasi obiect grafic se numeste instantiere
a obiectului grafic iar plasarea lor intr-o scena grafica se realizeaza
cu ajutorul transformarii de instantiere, obtinuta prin concatenarea transformarilor
grafice elementare (rotatia, scalarea si translatia). Obiectele grafice
sunt definite in sistemele de coordonate proprii al obiectelor.
Metoda generala pentru realizarea
copiilor obiectelor grafice este de a incarca obiectul grafic curent, de
a aplica transformarea de instantiere necesara si apoi de a apela procedura
display_obiect. Pentru a plasa in scena grafica cea de a doua copie a obiectului
grafic curent, este necesar de a anula toate transformarile efectuate pentru
peima copie astfel incat obiectul grafic initial sa fie disponibil pentru
noile transformari necesare. Datorita transformarilor de tip activ utilizate,
informatiile din obiectul grafic original vor fi modificate. Pentru a pastra
informatiile din obiectul grafic initial, este necesara proiectarea unei
proceduri de copiere a acestuia (de retinere). De asemenea este necesara
o procedura pentru restaurarea obiectului grafic curent, dupa reprezentarea
obiectului transformat. In acest scop se poate prevedea o variabila:
tip_obiect_grafic copie;
void retine_obiect()
{
copie = ob_gr_crt;
}
void restaurare ()
{
ob_gr_crt = copie;
}
Aceste 2 proceduri permit implementarea
unei structuri de stiva cu un singur nivel; o noua operatie “retine_obiect”
va sterge deci obiectul grafic original. Totusi acesta metoda este in general
suficienta pentru implementarea mecanismului de instantiere.
Vom considera in continuare
ca obiectele grafice care compun o scena grafica sunt descrise intr-un
fisier de simboluri (de tip .SYM). Pentru fiecare obiect grafic din acest
fisier (in ordine strict secventiala) se vor inscrie intr-un nou fisier
text (avand extensia .CMD) urmatoarele informatii:
- numarul de instante (copii)
- parametrii transformarilor care se aplica asupra
obiectului pentru a-l aduce in pozitia necesara.
Daca un obiect grafic din fisierul
de obiecte nu trebuie selectat, in fisierul .CMD se va inscrie in pozitia
corespunzatoare 0 (zero) pentru numarul de instante.
In scena grafica pot fi introduse
obiecte din mai multe fisiere de simboluri, ale caror denumiri se vor specifica
in fisierul .CMD.
Structura fisierului .CMD va
fi deci:
nume fisier_simboluri_1 (.SYM)
{pentru fiecare simbol din fisier}
numar de instante
{pentru fiecare instanta}
t sx sy tx ty cx cy
{ t - unghiul de rotatie
sx,sy – factori de scalare
tx,ty – factori de translatie
cx,cy – centrul rotatie si scalarii }
B. Implementare
In cadrul acestei lucrari se
vor realiza proceduri si functii necesare pentru urmatoarele operatii:
- transformarea obiectelor grafice
- instantierea obiectelor grafice
Aceste operatii vor completa
modulul G2Dobiecte dupa cum urmeaza:
/*======================================================================*/
/* G2Dobiecte.h.plus */
/*======================================================================*/
/*
* Translateaza obiectul grafic curent cu parametrii tx pe Ox
* respectiv ty pe Oy
*/
extern void translatie_obiect (double tx, double ty);
/*
* Roteste obiectul grafic curent cu un unghi de t grade
* in jurul centrului curent al transformarilor grafice
* in sens trigonometric
*/
extern void rotatie_obiect (double t);
/*
* Scaleaza obiectul grafic curent cu factorii de scara
* sx in directia axei Ox, respectiv sy in directia axei Oy,
* relativ la centrul curent al scalarii
*/
extern void scalare_obiect (double sx, double sy);
/*
* Incarca si executa un fisier de comenzi .CMD
*/
extern void display_cmd (char* fisier_cmd);
extern void retine_obiect (void);
extern void restaureaza (void);
/*======================================================================*/
/* End of G2Dobiecte.h.plus */
/*======================================================================*/
/*======================================================================*/
/* G2Dobiecte.c.plus */
/*======================================================================*/
#include <stdio.h>
#include <math.h>
#include "G2Dtransformari.h"
/* Tipuri si Structuri Private -----------------------------------------*/
static tip_obiect_grafic copie;
/* Rutine private ------------------------------------------------------*/
/*
* Aplica matricea de transformare m asupra tuturor punctelor
* obiectului grafic curent
*/
void transforma_obiect (MAT2D m)
{
int i;
double x,y;
for (i = 0; i < ob_gr_crt.nr_seg; i++)
{
transforma_punct (ob_gr_crt.seg[i].x1, ob_gr_crt.seg[i].y1, m,
&ob_gr_crt.seg[i].x1, &ob_gr_crt.seg[i].y1);
transforma_punct (ob_gr_crt.seg[i].x2, ob_gr_crt.seg[i].y2, m,
&ob_gr_crt.seg[i].x2, &ob_gr_crt.seg[i].y2);
}
for (i = 0; i < ob_gr_crt.nr_cerc; i++)
{
transforma_punct (ob_gr_crt.crc[i].x1, ob_gr_crt.crc[i].y1, m,
&ob_gr_crt.crc[i].x1, &ob_gr_crt.crc[i].y1);
transforma_punct (ob_gr_crt.crc[i].x2, ob_gr_crt.crc[i].y2, m,
&ob_gr_crt.crc[i].x2, &ob_gr_crt.crc[i].y2);
}
for (i = 0; i < ob_gr_crt.nr_arc; i++)
{
transforma_punct (ob_gr_crt.arce[i].x1, ob_gr_crt.arce[i].y1, m,
&ob_gr_crt.arce[i].x1, &ob_gr_crt.arce[i].y1);
transforma_punct (ob_gr_crt.arce[i].x2, ob_gr_crt.arce[i].y2, m,
&ob_gr_crt.arce[i].x2, &ob_gr_crt.arce[i].y2);
transforma_punct (ob_gr_crt.arce[i].x3, ob_gr_crt.arce[i].y3, m,
&ob_gr_crt.arce[i].x3, &ob_gr_crt.arce[i].y3);
}
}
/* Rutine publice ------------------------------------------------------*/
/*
* Translateaza obiectul grafic curent cu parametrii tx pe Ox
* respectiv ty pe Oy
*/
void translatie_obiect (double tx, double ty)
{
MAT2D tmat;
tran_mat(tx, ty, tmat);
transforma_obiect(tmat);
}
/*
* Roteste obiectul grafic curent cu un unghi de t grade
* in jurul centrului curent al transformarilor grafice
* in sens trigonometric
*/
void rotatie_obiect (double t)
{
MAT2D rmat;
rot_mat_centru(t, rmat);
transforma_obiect(rmat);
}
/*
* Scaleaza obiectul grafic curent cu factorii de scara
* sx in directia axei Ox, respectiv sy in directia axei Oy,
* relativ la centrul curent al scalarii
*/
void scalare_obiect (double sx, double sy)
{
MAT2D smat;
scal_mat_centru(sx, sy, smat);
transforma_obiect(smat);
}
/*
* Incarca si executa un fisier de comenzi .CMD
*/
void display_cmd (char* fisier_cmd)
{
FILE *fcmd;
int i,nrc;
char sym[80];
double t, sx, sy, tx, ty, cx, cy;
/* incearca deschidere in citire */
fcmd = fopen (fisier_cmd, "r");
if (NULL == fcmd)
{
fprintf (stderr, "\nNu pot deschide in citire ");
perror (fisier_cmd);
return ;
}
while (!feof(fcmd))
{
/* citire nume fisier sym */
if(fscanf(fcmd,"%s",sym) != 1)
{
fprintf (stderr, "\nNu pot citi nume fis. sym ");
fclose(fcmd);
return ;
}
deschide_fisier_intrare (sym);
while (!feof( fisier_intrare ))
{
incarca_obiect();
if(fscanf(fcmd,"%d",&nrc) != 1)
{
fprintf (stderr, "\nNu pot citi numar instante pt. obj %s",
sym);
fclose(fcmd);
return ;
}
for (i = 0; i < nrc; i++)
{
retine_obiect ();
if (fscanf (fcmd, "%lf%lf%lf%lf%lf%lf%lf",
&t, &sx, &sy, &tx, &ty, &cx, &cy)
!= 7)
{
fprintf (stderr, "\nNu pot citi param. pt. obj %s",sym);
fclose(fcmd);
return ;
}
centru(cx, cy); /* seteaza centrul rotatiei si scalarii */
/* aplica transformarea de instantiere */
rotatie_obiect(t*M_PI/180.0);
scalare_obiect(sx, sy);
translatie_obiect(tx, ty);
/* reprezentarea obiectului pe ecran */
display_obiect();
restaureaza();
} /* for */
} /* while */
inchide_fisier_intrare();
} /* while */
fclose(fcmd);
} /* display_cmd() */
void retine_obiect ()
{
/* Definirea procedurii retine obiect */
}
void restaureaza ()
{
/* Definirea procedurii restaureaza obiect */
}
/*======================================================================*/
/* End of G2Dobiecte.c.plus */
/*======================================================================*/
C. Aplicatii
In continuare se prezinta un exemplu pentru reprezentarea
ordinogramei din figura :
Fisier simboluri ORD.SYM Fisier structura ORD.CMD
ORD.SYM ord.sym
n start_stop 2 {bloc start_stop}
c 0 2 4 2 0.0 1.0 1.0 16.0 28.0 0 0
e 0.0 1.0 1.0 27.0 3.0 0 0
n calcul 2 {bloc calcul}
s 0 0 6 0 0.0 1.0 1.0 15.0 22.0 0 0
s 6 0 6 4 0.0 1.0 1.0 6.0 16.0 0 0
s 6 4 0 4 1 {bloc decizie}
s 0 4 0 0 0.0 1.0 1.0 14.0 10.0 0 0
e 1 {bloc intrare}
n decizie 0.0 1.0 1.0 15.0 16.0 0 0
p 5 0 2 4 0 8 2 4 4 0 2 1 {bloc iesire}
e 0.0 1.0 1.0 26.0 10.0 0 0
n intrare 7 {simbol sageata}
p 6 0 0 6 0 6 3 1 3 0 2 0 0 0.0 1.0 1.0 18.0 26.0 0 0
e 0.0 1.0 1.5 18.0 19.0 0 0
n iesire 0.0 1.0 1.0 18.0 14.0 0 0
s 0 1 0 4 90.0 2.0 1.0 26.0 12.0 0 0
s 0 1 6 4 90.0 4.5 1.05 18.0 21.0 0 0
s 6 4 6 1 0.0 1.0 2.0 29.0 7.0 0 0
a 0 1 2 0 3 1 180.0 1.0 2.0 9.0 16.0 0 0
a 3 1 4 2 6 1 2 {simbol segment}
e 0.0 1.0 0.5 9.0 20.0 0 0
n sageata -90.0 2.5 1.0 9.0 12.0 0 0
s 0 0 0 2
s 0 0 -0.3 0.3
s 0 0 0.3 -0.3
e
n segment
s 0 0 0 2
e
Observatie : Caracterul p introduce primitiva
grafica polilinie. #include "G2Dnucleu.h"
#include "G2Dobiecte.h"
int
my_main (int argc, char *argv[])
{
/* stabilire fereastra si port de vedere */
display_cmd ('ord.cmd');
}
1. Completati unitatea G2Dobiecte conform cu specificatiile
din lucrare.
2. Completati procedura incarca_obiect astfel incat
aceasta sa recunoasca si primitiva polilinie. In momentul incarcarii se
va transforma sirul de coordonate ale varfurilor liniei poligonale intr-o
secventa de segmente de dreapta, pentru a nu modifica structura de
date a obiectului grafic.
3. Sa se defineasca un obiect grafic reprezentand
un patrar cu latura de 100 de unitati. Sa se genereze o imagine formata
din 60 de patrate obtinute prin rotirea patratului initial, cu o unghiul
t=6 grade in jurul:
- originii
- centrului patratului
- coltului stanga jos al patratului
Exemplu :
#include <math.h>
#include "G2Dnucleu.h"
#include "G2Dtransformari.h"
#include "G2Dobiecte.h"
int my_main (int argc, char *argv[])
{
int i;
double t;
/* stabileste fereastra si portul de vedere */
deschide_fisier_intrare ('patrat.sym');
incarca_obiect ();
t = 6 * M_PI / 180;
centru (0, 0); /* rotatie in jurul originii */
for (i = 0; i < 60; i++)
{
retine_obiect ();
rotatie_obiect (t * i);
display_obiect ();
restaureaza_obiect ();
};
inchide_fisier_intrare ();
} /* my_main */
4. Sa se reexecute programul de la punctul 2 aplicand
fiecarui nou patrat o scalare cu factorul 0.95 pe ambele directii fata
de centrul patratului.
5. Construiti fisierele .SYM si .CMD pentru descrierea
unei ordinograme si scrieti un program de aplicatie pentru generarea ei
pe ecran.
6. Se considera fisierul ELEC.SYM continand simboluri
electronice definite in sistemul de coordonate propriu al obiectului. Definiti
fisierul ELEC.CMD pentru realizarea circuitului urmator si scrieti un program
de aplicatie care executa fisierul ELEC.CMD.
|