Nella parte 13 abbiamo parlato delle modalità di mapping a scala fissa, ora esamineremo quelle a scala variabile.
Queste sono solo due: MM_ISOTROPIC ed MM_ANISOTROPIC ed entrambe permettono sia di cambiare il fattore di scala che l'orientamento degli assi.
La differenza tra le due è che con la modalità isotropica viene conservato un rapporto di 1:1 tra gli assi X e Y; in pratica un quadrato viene sempre disegnato come tale, può ad esempio essere riflesso, ma non può essere stirato per diventare un rettangolo.
Con la modalità MM_ANISOTROPIC invece il rapporto tra le coordinate X ed Y può variare ed in questo modo ad esempio un cerchio può essere trasformato in un ellisse.
Esaminate ad esempio il seguente codice:
void CPrg10View::OnDraw(CDC* pDC)
{
CPrg10Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rectClient;
GetClientRect (rectClient);
// 1. rectClient contiene le dimensioni in coord. di dispositivo dell'area della finestra
pDC->SetMapMode(ANISOTROPIC);
// 2. settiamo la modalità di mapping a scala variabile
pDC->SetWindowExt(100,100);
// 3. impostiamo l'area della finestra come una superficie di 100x100 unità logiche
pDC->SetViewportExt(rectClient.right, -rectClient.bottom);
// 4. setta le dimensioni del rettangolo di visualizzazione sulla finestra ( viewport )
pDC->SetViewportOrg(rectClient.right/2, rectClient.bottom/2);
// 5. setta l'origine del sistema di riferimento al centro dello schermo
pDC->Ellipse(CRect(-50,-50,50,50));
// 6. disegna l'ellisse ( notare i segni negativi ) in modo che riempia l'intero schermo
}
In questo snippet di codice vediamo come si utilizza una modalità di mappatura a scala variabile ( in assoluto la più ostica ).
Innanzitutto gli obiettivi: vogliamo disegnare un ellisse che riempia tutta la finestra e che venga disegnata utilizzando un nostro sistema di riferimento.
In 1 ( riferimento alla riga sopra il commento numerato ) recuperiamo le dimensioni della finestra della vista. Questa operazione fa si che la larghezza e l'altezza ( in pixel ) siano contenuti nei membri di dati right e bottom dell'oggetto rectClient passato per riferimento ( se non ci credete vedete il prototipo di GetClientRect ) alla funzione.
In 2 settiamo semplicemente la modalità MM_ANISOTROPIC, provate a vedere la differenza con MM_ISOTROPIC ( l'ellisse si trasformerà in un cerchio ).
In 3 indichiamo alla GDI ( tramite CDC ) che l'area della finestra dovrà essere rappresentata da un rettangolo di 100x100 unità logiche; in pratica settiamo le dimensioni logiche della finestra.
In 4 settiamo le dimensioni della Viewport, cioè l'area visibile della finestra; questa non ha alcuna relazione con le dimensioni logiche della finestra. Si pensi ad esempio ad una lente di ingrandimento che avviciniamo o allontaniamo dal foglio: se la avviciniamo la dimensione del foglio non cambia, ma a noi il suo contenuto sembrerà più grande
Ad esempio se settiamo la grandezza del foglio ( window ) a 100x100 unità e settiamo la grandezza della viewport a 100x100 allora vedremo che la nostra ellisse diventerà un cerchio al centro dello schermo, se invece settiamo la grandezza della viewport alle dimensioni della finestra ( rectClient ) allora vedremo una bella ellisse che riempie tutta la finestra.
Nel caso specifico dando un valore negativo al secondo parametro di SetViewportExt facciamo si che l'asse positivo delle Y sia verso il basso ( di default è il contrario ).
Ci può essere un po' di confusione tra la 3 e la 4, ma ricordate che un po' di prove risolveranno ogni dubbio!
In 5 settiamo la posizione dell'origine della viewport.
No comment per la 6.
Vorrei ora dirvi che esiste anche un'altra funzione per settare l'origine del sistema di coordinate: SetWindowOrg.
Potrebbe sorgervi qualche dubbio sulla sua utilità, ma spiego succintamente la differenza con SetViewportOrg.
Una chiamata a pDC-> SetViewportOrg (x,y) mette in corrispondenza il punto logico (x,y) con l'angolo in alto a sinistra dell'area di visualizzazione ( punto 0,0 del dispositivo ).
Una chiamata a pDC-> SetWindowOrg (x,y), fa il contrario, mette in corrispondenza il punto logico (0,0) con il punto di dispositivo (x,y).
Questo è tutto ciò che vi serve per iniziare con le modalità di mapping, è inutile approfondire ulteriormente l'argomento ( non banale ) dato che avrete bisogno già di un bel po' di tempo per digerire queste ultime due parti.
Torna all'indice Generale del corso di Corso di Visual C++ di Software Planet