[Graphics Lab Logo Image]  

Home  Up  Feedback  Contents  Search 

Lucrarea nr.10: Descrierea Scenelor Grafice 2D cu ajutorul Obiectelor Grafice

[ Prev ] Lucrarea 10 [ Next ]

[Under Construction]

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;
  • doua proceduri
   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.

                    

 

 

Home ][ Up ][ Previous ][ Next ]

Send mail to sorin@aspc.cs.utt.ro with questions or comments about this web site.
Copyright © 2000 Graphics Laboratory
Last modified: January 25, 2000