Ciao ragazzi mi chiamo Simone e ho bisogno di voi. Sto frequentando un corso di informatica e dobbiamo fare un'esercitazione che però io non riesco proprio a fare. Vi giuro che ci ho provato, tante tante volte anche con il debug e con carta e penna prima di impostare il lavoro sul compilatore. Non vi chiedo il programma schietto perchè non sarebbe giusto, ma solo degli avvii sulla strada per ogni punto così poi da concludere il lavoro e riguardarmelo più avanti nel tempo senza date di scadenza .
Il testo è: Il formato vettoriale che vogliamo gestire è vagamente riminiscente del formato SVG.
Gestiamo:
rettangoli pieni descritti da un punto principale (il vertice in alto a sinistra), dall'altezza e dalla larghezza
cerchi pieni descritti da un punto di centro e da un raggio
poligoni vuoti, di N vertici (descritti da una lista di punti)
Un tipo di dato che sarà utile realizzare è il point (che conterrà le coordinate x e y di un punto)
Ogni forma può subire trasformazioni, noi considereremo le seguenti:
move: sposto la forma specificando lo spostamento delle righe e delle colonne
rotate: ruoto la forma intorno al vertice principale (il primo)
scale: scalo la forma rispetto al vertice principale (il primo)
Una forma è descritta dal suo tipo, i valori iniziali e (l'eventuale) lista delle trasformazioni che applichiamo; tutto questo viene inserito tra parentesi acute < >
La sintassi del nostro formato vettoriale è descritta nel seguente esempio
< rect 0 0 10 10 rotate 90 >
< circle 50 50 10 move 20 20 scale 0.5 >
In questo nostro formato vettoriale possiamo anche effettuare copie multiple (eventualmente trasformate) di una forma "base". Per fare questo dobbiamo prima di tutto assegnare un identificatore ad una forma:
< rect 0 0 10 10 rotate 90 id rettangolo1 >
dopo di che possiamo richiamare la forma associata ad un identificatore esistente nel seguente modo
< repeat rettangolo1 15 move 10 30 scale 0.8 >
in questo modo, per esempio, possiamo ripetere il rettangolo1 15 volte spostando ogni volta il rettangolo di (10,30) pixel e riscalandolo ogni volta di 0.8
Il programma dovrà essere in grado di produrre un'immagine digitale in formato PGM a partire da un file vettoriale. Per fare questo il programma dovrà:
leggere il file vettoriale riga per riga, nell'ipotesi che ogni riga contenga un solo comando compreso tra parentesi acute < >.
interpretare i simboli di una riga e produrre una descrizione astratta della forma
tradurre questa forma in un'immagine digitale (raster), andando ad assegnare un valore fissato (per esempio 255) ad ogni elemento dell'immagine digitale che appartiene alla forma.
Importante:
assumiamo che il file vettoriale sia sintatticamente corretto e non ci interessa se le forme generate vengono sovrapposte nell'immagine raster risultante.
invece dobbiamo stare attenti che le forme non escano dall'immagine.
Organizzazione del programma
le strutture dati e le funzioni atte a descrivere le forme e le loro trasformazioni saranno incluse in un modulo shapes (comprensivo di due file, shapes.h e shapes.cpp)
le strutture dati e le funzioni relative alla produzione di un'immagine raster, all'inizializzazione della stessa e alla conversione di forme da formato vettoriale a raster saranno parte di un modulo raster (comprendivo di due file, raster.h e raster.cpp)
le funzioni di parsing dell'input (delle righe del file) saranno contenute in un modulo parse (comprensivo di due file, parse.h e parse.cpp)
Ecco il file main.cpp che si utilizzerà:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include "matrix.h"
#include "raster.h"
#include "parse.h"
using namespace std;
int main()
{
int nrow=100, ncol=100; // con una piccola modifica potete leggere le dimensioni dal file di input
matrix RI=matrixNew(nrow, ncol); // Raster Image (RI) - Un'immagine digitale che per semplicita' codifichiamo con int.
string line;
string dummy, shape;
ifstream in;
in.open("data.vec");
if (!in) {
cerr << "Error" << endl;
return(-1);
}
init_raster(RI,nrow,ncol); // funzione che inizializza un'immagine digitale assegnando 0 a tutti i pixel
getline(in,line);
while(in) {
stringstream lineStream(line);
// Parsing dell'input: immagazzino gli elementi in variabili del tipo opportuno
lineStream >> dummy >> shape;
if (shape=="rect") {
process_rectangle(lineStream,RI,nrow,ncol); //interpreto la riga e aggiorno RI
}
else if (shape=="circle") {
process_circle(lineStream,RI,nrow,ncol); //interpreto la riga e aggiorno RI
}
else if (shape=="poly") {
process_polygon(lineStream,RI,nrow,ncol); //interpreto la riga e aggiorno RI
}
else if (shape=="repeat") {
process_repeat(lineStream, RI, nrow, ncol); //interpreto la riga e aggiorno RI
}
else {
cout << "I don't recognize this tag, I'm skipping the line: " << lineStream.str() << endl;
}
getline(in,line);
}
write_image("raster.pgm",RI, nrow, ncol);
cout << "Conversion completed\n";
return(1);
}
Per la gestione dinamica di array bidimensionali si può usare il modulo matrix.
Sì lo sò è lungo, non ho fretta. Basta che mi avviate sulla strada di ogni punto così con calma posso farlo e vedermelo poi senza nessuno che mi corra dietro
Grazie in anticipo
Simone