Costruire un tipo di dato astratto che fornisca servizi per disegnare triangoli, rettangoli, quadrati e cerchi



Scaricare 50 Kb.
23.05.2018
Dimensione del file50 Kb.

CAPPELLI FEDERICO MATR 107405 TERZA ESPERIENZA DI PROGETTO
PROBLEMA 1.

Costruire un tipo di dato astratto che fornisca servizi per disegnare triangoli, rettangoli, quadrati e cerchi.


Si dispone già dell’astrazione SimpleDrawPad, di cui è fornita documentazione e tutti i metodi che sfrutta, ma non i file sorgente. Creare un componente software che testi la funzionalità dell’astrazione realizzata.
PROBLEMA 2.

Data la classe astratta Shape, derivare nuove classi concrete relative alle figure che si vogliono avere (triangoli, rettangoli, cerchi,…), ognuna che specifichi come disegnarsi.



ANALISI 1.

DrawPad


Prima cosa importante da tenere conto è che per poter riusare entità gia esistenti è necessario far conoscere alla macchina dove si trovano tali entità. SimpleDrawPad è un’astrazione che permette di realizzare linee e punti su di una finestra, è una semplicissima applicazione di grafica, con opzioni sui colori e la spessore delle linee. Lo scopo da raggiungere è quello di costruire un’entità di tipo ADT che deve essere in grado di costruire figure geometriche piane. Chiamiamo questo dato astratto DrawPad. Come deve essere DrawPad? Sicuramente condizione necessaria per la costruzione di figure geometriche è la capacità di questo strumento di tracciare delle linee e segnare dei punti. Tali operazioni sono proprio i servizi che offre SimpleDrawPad che sarà quindi esteso da DrawPad. Utilizzando una notazione di tipo insiemistica significa che DrawPad è un sottoinsieme di SimpleDrawPad e che quindi ha delle caratteristiche comuni ad esso. Basta pensare che ogni figura geometrica è la combinazione di più linee e punti. Quindi DrawPad eredita da SimpleDrawPad le funzioni principali ( linee, punti), e i dati; oltre a ereditare DrawPad definisce poi altre funzioni e dati che non sono presenti in SimpleDrawPad che risulterà estesa. All’interno di DrawPad che è derivato da, o che estende, SimpleDrawPad, bisogna specificare che dati, funzioni, funzioni modificate, ha il primo rispetto al secondo. In ogni caso però all’atto della costruzione di un DrawPad avrà caratteristiche compatibili ad un SimpleDrawPad.Le funzioni di DrawPad per la creazione di figure dovranno opportunamente sfruttare i servizi di tracciatura linee gestiti da SimpleDrawPad. All’interno della finestra che verrà creata per la visualizzazione delle immagini ci si può orientare secondo un sistema di coordinate dove l’origine (0,0) è in alto a sinistra. Per la realizzazione delle figure si creano delle funzioni che siano in grado di tracciare le linee da un punto notevole delle figura stessa ad un altro punto d’interesse e cosi via specificando le coordinate dei punti. Questo in maniera del tutto generale: va bene per un triangolo e per un generico quadrilatero. Nel caso di un rettangolo sarebbe utile realizzare una funzione che permetta di tracciare tale figura dando come informazioni le coordinate del primo vertice in alto a sinistra e poi la lunghezza dalla base e della altezza; tramite la base e l’altezza si possono dedurre, all’interno della funzione stessa, le coordinate degli altri punti. Il primo punto se ha coordinate (x,y) il secondo procedendo in senso antiorario avrà coordinate (x,y+altezza), il terzo (x+base,y+altezza), il quarto (x+base,y). Analogamente per un quadrato dove però è sufficiente specificare coordinate del vertice in alto a sinistra e la lunghezza di un lato, le coordinate dei vertici saranno quindi: 1°(x,y);2°(x,y+lato);3°(x+lato,y+lato);4°(x+lato,y); sempre procedendo in senso antiorario.

La funzione che disegna il cerchio anch’essa dovrà richiedere 3 dati, le cordinate del centro e la lunghezza del raggio. Per la realizza del cerchio sa fa ricorso alla trigonometria basilare, in quanto si fa una conversione da coordinate polari di cui raggio e angolo sono i due parametri, a coordinate cartesiane tenendo conto anche della possibile traslazione del centro del cerchio rispetto l’origine.

Quindi l’ascissa assoluta risulterà: xp = x +(raggio*sen (angolo)): dove x indica la differenza di ascissa di un centro O’ diverso da O. l’ordinata assoluta sarà allora: yp = y+(raggio*sen(angolo)): dove y indica la differenza di ordinta di un centro O’ diverso da O. L’entità DrawPad può anche disporre di una funzione che gli permetta di selezionare con un unico comando tutte le opzioni del caso, ovvero colore delle linee e loro spessore.
Componente software.

Questa entità deve testare la funzionalità del DrawPad, quindi dovrà creare un oggetto di tale tipo e andare a disegnare varie figure utilizzando le funzioni da noi sviluppate. La chiamo Test1.


ANALISI 2.

Shape.

Si dispone di una categoria concettuale chiamata Shape la quale rappresenta un tipo di dato astratto in particolare una figura. Da questo dato si vogliono poi derivare altre entità, questa volta concrete che rappresentano diverse figure. L’oggetto Shape che è una figura può essere realizzato su un SimpleDrawPad mediante una funzione apposita. Creando un dato Shape bisogna specificare il colore delle linee che verranno tracciate e il loro spessore, vi sono poi funzioni che restituiscono queste informazioni. Per quanto riguarda il settaggio del colore avviene tramite tre dati che indicano la percentuale dei tre colori base, rosso,verde,blu. Ogni specifica figura geometrica specializza il concetto di shape; è vero che ogni figura è formata da linee, ma ognuna ha caratteristiche proprie. Quindi ogni singola figura estende il concetto di shape. Come costruiamo le figure: la figura che vogliamo costruire è sicuramente un dato concreto derivato da quello più generico di figura geometrica. Quando vogliamo creare una nuova figura geometrica dobbiamo specificare i parametri caratteristici della figura, il colore e lo spessore del contorno, automaticamente viene creato un oggetto shape con le sue caratteristiche di colore e spessore del tratto. Nel punto 1 dell’analisi sono specificati i ragionamenti attuati per poter stabilire le coordinate notevoli delle figure geometriche e quindi come poterle disegnare. Questi ragionamenti poi vengono effettivamente sfruttati nel codice sia nella prima sia nella seconda soluzione presentata. Quando una figura verrà rappresentata su schermo la funzione che si occupa di questo deve andare a vedere la configurazione di Shape e assegnare di conseguenza alla figura da creare delle predeterminate caratteristiche di colore e tratto.


Componente software.

Deve testare la funzionalità di ogni oggetto concreto realizzato, quindi andrà a disegnare a video le figure interessate. Test2.


PROGETTO 1.

DrawPad.

DrawPad è una classe public che come abbiamo visto estende il concetto di SimpleDrawPad che è una classe che ci è stata fornita assieme ad altri tools. È necessario dare al calcolatore le informazioni per reperire queste classi che sono nel package tool, importa quindi tutto il contenuto di questo package mediante un percorso specificato all’inizio del codice. Il costruttore di DrawPad è lo stesso identico costruttore di SimpleDrawPad che non necessita di alcun parametro. Quindi risulta essere DrawPad() che al suo interno deve invocare il costruttore della superclasse. Si definisce il metodo public void drawTriangle(int x0, int y0, int x1, int y1 ,int x2, int y2) : tale metodo fornisce la possibilità di disegnare un qualsiasi tipo di triangolo passandogli come parametri le coordinate dei tre vertici del triangolo. Non restituisce alcun valore ed è utilizzabile da qualsiasi utente.

public void drawQuadrilater(int x0, int y0,int x1, int y1, int x2, int y2, int x3, int y3) : questo metodo disegna un quadrilatero ed richiede come parametri le coordinate dei quattro vertici, anche questo è pubblico e non restituisce alcun valore.

public void drawCircle(int x,int y, int raggio) : metodo per tracciare una circonferenza passandogli come parametri le coordinate del centro e la lunghezza del raggio, sfrutta due varibili intere d’appoggio xp e yp che rappresentano le coordinate assolute dei punti della circonferenza. Anche questo è un metodo accessibile a chiunque e non restituisce alcun valore.

public void perfectBox(int x, int y, int base, int height): i parametri sono, le coordinate del vertice in alto a sinistra, la base, l’altezza, di un rettangolo che viene realizzato da questo metodo che è public e non restituisce alcun valore. Altro metodo delle stesse caratteristiche di accessibilità è:

public void drawSquare(int x, int y, int h), il quale disegna un quadrato richiedendo come parametri le coordinate del vertice in alto a sinistra e la lunghezza del lato. Anche l’ultimo metodo definito da DrawPad è di tipo public e non restituisce alcun valore: public void setPad(int thickness, float r, float g, float b), permette di settare in un comando anziché due le caratteristiche delle figure in quanto spessore e colore delle linee.


Componente software.

Il componente software è modellato nella classe Test2, che contiene il main e non restituisce alcun tipo di valore. Una volta creato un oggetto di tipo DrawPad e averlo chiamato pad, su di esso va a invocare i metodi per la realizzazione di figure, dopodiché aspetta un tempo prefissato in millisecondi durante il quale si può vedere il risultato delle funzioni invocate sull’oggetto pad.


PROGETTO2.

È necessario importare il contenuto del package tool.

Bisogna definire e creare una classe per ogni figura geometrica, in particolare:

Quadrilater,Triangle,perfectBox,Square,Circle, tutte queste classi estendono la classe Shape e quindi l’intestazione sarà: public class NomeClasse extends Shape.

public Quadrilater(float r, float g, float b, int thickness, int x, int y, int x1,int y1, int x2, int y2, int x3, int y3); è il costruttore della figura Quadrilater dove gli interi sono le coordinate dei vertici e thickness rappresenta lo spessore del tratto, i float le componenti del colore (red,green,blue).

Public void draw(SimpleDrawPad); è il metodo che permette di disegnare la figura su un SimpleDrawPad passato come parametro, non restituisce alcun valore. Il discorso si ripete identicamente per le altre classi, le differenze stanno nel numero di parametri da specificare e piccole differenze nell’implementazione.

la classe Triangle, il suo costruttore: public Triangle (float r, float g, float b, int thickness, int x, int y, int x1,int y1,int x2, int y2). Identiche saranno le segnature del metodo draw.

La classe perfectBox, il suo costruttore: public PerfectBox (float r, float g, float b, int thickness, int x, int y, int base, int height). In questo caso è chiaro che basta conoscere un vertice, la base e l’altezza.

La classe Square, il suo costruttore: public Square (float r, float g, float b, int thickness, int x, int y, int h). basta oltre a un vertice, il lato.

La classe Circle, il suo costruttore: public Circle (float r, float g, float b, int thickness, int x,int y, int raggio). Basta il centro e il raggio della circonferenza.


IMPLEMENTAZIONE 1.

DrawPad.java

Per importare tutti le classi contenute nel package tools è necessario specificare all’inizio del codice da dove si importano questi “attrezzi”  import tools.*; .

Stessa cosa per quanto riguarda la libreria di matematica  import java.lang.Math.*; .

Il costruttore di DrawPad è lo stesso costruttore di SimpleDrawPad, quellod di default ( anche l’unico), viene invocato mediante la parola chiave super(); che indica il costruttore della superclasse. All’interno del metodo drawTriangle(parametri) viene sfruttato il metodo della classe base SimpleDrawPad per tracciare i lati del triangolo: drawLine(x0, y0, x1, y1); e così via per gli altri lati. drawQuadrilater(parametri) come sopra traccia le linee del quadrilatero tramite la drawLine della classe base. il metodo drawCircle(parametri) utilizza al suo interno l’altro metodo definito nella classe base drawPoint. È realizzato in maniera da assegnare mediante un ciclo di for, ad ogni ciclo due valori che sono le coordinate assolute del punto in tale ciclo. All’interno del ciclo vi è una variabile di tipo intera a che rappresenta l’angolo come un altro parametro oltre il raggio per un sistema di coordinate polari; a va da 0 a 360 compiendo perciò un angolo giro; ad ogni grado viene ricalcolata la posizione in coordinate cartesiane del punto da segnare.
for(int a=0;a<360;a++)

{xp=(int)(x+raggio*Math.sin(a));

yp=(int)(y+raggio*Math.cos(a));

………………….}


l’utilizzo della parola chiave int tra parentesi tonde serve per fare un casting del dato a tipo intero.

Si ritorna all’utilizzo di drawLine all’interno dei due metodi perfectBox(parametri) e drawSquare(parametri) dove le caratteristiche delle coordinate dei vertici sono state viste nella fase di analisi.


Componente software. file allegato Test1.java

Anche Test1 importa tools.* come DrawPad. Viene creato un oggetto di tipo DrawPad e chiamato pad, ogni metodo invocato, che sia definito nella classe base o nella classe derivata va specificato nel modo: pad.metodo(parametri). L’apertura della finestra di pad sullo schermo è un operazione di output che può essere affetta da errori, si usa allora un costrutto linguistico:

try{operazione critica}catch(Exepction eccezione){….}. che solleva un’eccezione. Vedremo più in dettaglio.

IMPLEMENTAZIONE 2.

Per importare tutti le classi contenute nel package tools è necessario specificare all’inizio del codice da dove si importano questi “attrezzi”  import tools.*.

Si predispongono dei dati privati che serviranno come variabili intere d’appoggio, dove depositare i parametri notevoli delle figure da realizzare: private int a,z,a1,b1,a2,b2,a3,b3 /**caso della classe Quadrilater*/. Il costruttore della classe concreta invoca tramite, super(r,g,b,thickness), il costruttore di Shape con i parametri caratteristici, componenti del colore e spessore del tratto. Sempre all’interno del costruttore vengono poi assegnate alle variabili d’appoggio le grandezze utili per la realizzazione della figura:

a=x;z=y;a1=x1;b1=y1;a2=x2;b2=y2;a3=x3;b3=y3;. Il metodo draw presuppone l’esistenza di un SimpleDrawPad che verrà accettato come parametro, all’interno del metodo si visualizzerà il pad mediante la riga pad.show(); .

pad.setCurrentThickness(getThickness()); setta lo spessore del tratto andando a vedere il valore precedentemente introdotto nel costruttore di Shape.

Analogamente per le componenti del colore:

pad.setCurrentColor(getColorRedComponent(),getColorGreenComponent(),getColorBlueComponent(); .

pad.drawLine(a, z, a1, b1);

pad.drawLine(a1, b1, a2, b2);

pad.drawLine(a2, b2, a3, b3);

pad.drawLine(a3, b3, a, z); le drawLine realizzano la figura. È chiaro che la differenza tra le classi così realizzate sta solo nel fatto che le grandezze da tener conto per realizzare diverse figure geometriche sono diverse e già state analizzate.

Componente softwareTest2


Anche Test2 importa tools.* . Viene creato un oggetto di tipo SimpleDrawPad e chiamato pad, ogni metodo invocato, che sia definito nella classe base o nella classe derivata va specificato nel modo: oggettocreato.metodo(pad). L’apertura della finestra di pad sullo schermo è un operazione di output che può essere affetta da errori, si usa allora un costrutto linguistico:

try{operazione critica}catch(Exepction eccezione){….}. che solleva un’eccezione. Vedremo più in dettaglio.




CONCETTI.
Quando esistono già ben definiti degli oggetti (da utenti o predefinite in java) nessuno mi vieta di usarli. In che maniera: creando oggetti composti come nella seconda esperienza di progetto, o derivando dalle classi in esame delle classi fortemente specializzate a seconda delle esigenze. Una classe derivata si può anche chiamare sottoclasse, e la classe base superclasse.

La classe derivata estende il concetto contenuto nella superclasse, ma da essa eredita tutti i dati e tutti i metodi. Quindi la classe derivata dovrà specificare quali dati ha in più rispetto alla superclasse, quali metodi ha in più o modifica rispetto alla superclasse. È indispensabile all’inizio del programma importare il package che contiene la superclasse altrimenti java non trova il percorso, a meno che tutte le volte che abbiamo bisogno di un metodo della classe base ci mettiamo a specificare tutto il percorso, cosa piuttosto scomoda.( questa operazione si esegue con import nomepackage.metodo, si può usare anche * che indica tutto il contenuto del package). I costruttori devono sempre essere definiti! Nel caso della classe DrawPad il costruttore definito senza alcun parametro perché il costruttore che viene realmente invocato, quello di SimpleDrawPad, richiede un solo parametro. L’esercitazione ha simulato a mio avviso una situazione che è molto diffusa, il fatto di disporre solo della classe SimpleDrawPad e della sua documentazione, da proprio l’idea di un qualcosa che non conosco all’interno ma che grazie alla documentazione posso capire dal punto di vista del suo comportamento verso l’esterno, studiando i servizi che esso può fornire ed adoperarli per poter disegnare. Come detto sopra la classe DrawPad eredita tutti i metodi di SimpleDrawPad, in particolare sfrutta drawLine all’interno delle nuove definizioni di metodi più specializzati, definiti solo in DrawPad, quelli per la creazione delle figure( drawCircle, drawTriangle, ecc.). Nel componente software che testa la funzionalità di DrawPad c’è da porre particolare attenzione a un costrutto linguistico nuovo : try{…}catch{….} che viene usato per trattare operazioni critiche in quanto solleva un’eccezione in caso che qualcosa vada storto e java prova a risolvere alcune di queste eccezioni.



Il caso del secondo problema presenta sempre la questione di importare da tools la classe Shape, una classe predefinita di tipo astratto dalla quale si dovrà costruire una gerarchia di figure appartenenti a Shape. Ogni figura geometrica sarà una classe concreta e come tale deve avere i propri costruttori con informazioni di colore, spessore, e coordinate; e il metodo draw di Shape modificato a seconda della figura da disegnare. Questa volta si sfruttano le metodologie già definite da Shape per poter realizzare le figure interessate, notare come all’interno del metodo draw, ridefinito opportunamente per ogni figura sono presenti invocazioni di metodi della superclasse, in questo caso Shape. Per quanto riguarda le regole cono cui si tracciano le righe rimangono identiche a quelle del primo approccio al problema (DrawPad).E’ importante notare come il metodo draw ereditato da Shape e modificato nelle classi concrete ha bisogno come parametro di invocazione un dato di tipo SimpleDrawPad e quindi si presuppone una previa creazione di tale oggetto altrimenti nessuna figura(shape) potrà essere disegnata.


Condividi con i tuoi amici:


©astratto.info 2019
invia messaggio

    Pagina principale