[c++] Diagramma cartesiano con librerie SDL

valentino861
Mi sto studiando le librerie SDL per poter fare un diagramma cartesiano aggiornato in real time. Praticamente ho il programma che acquisisce dei dati e li dovrei diagrammare.
Qualche idea su come fare? Qualche link su cosa dovrei studiare in particolare?
Ho visto solo come poter muovere un'immagine con i tasti della tastiera.

Grazie

Risposte
valentino861
mi sono scaricato questa libreria ma non capisco come farlo in real time

http://www.softintegration.com/docs/ch/plot/

Riesco a plottare i dati ma non li aggiorna in real time, e non riesco a chiudere automaticamente la finestra dopo un certo numero di secondi. Come posso fare?

Pensavo di fare un ciclo dove mi stampa ogni 10 secondi una schermata dei dati, e la schermata rimane tale per tipo 2 secondi. Sarebbe perfetto anche senza real time. Ma una volta aperta la finestra la devo chiudere manualmente...dove posso intervenire?

apatriarca
Che intendi con un diagramma in realtime? Vuoi inserire sulla destra sempre nuovi valori e far spostaregli altri a sinistra? Il modo migliore in questo caso è di rifare ad ogni frame il grafico. Questo dovrebbe valere sia per la libreria che stai usando, sia scrivendo direttamente il codice per farlo in SDL o altra libreria grafica.

akiross1
Allora, ti dico con le SDL, che' le altre librerie che indichi non le conosco.

Innanzi tutto procurati qualcosa di decente che vada su SDL per disegnare le curve... SDL manipola pixel, ti assicuro che non e' divertente disegnare linee e curve direttamente :D su libsdl.org nella sezione librerie trovi di sicuro qualcosa.

Poi, per chiudere la finestra basta che esci dal programma (?) con exit()... Altrimenti SDL_Quit (http://www.libsdl.org/cgi/docwiki.cgi/SDL_Quit) eventualmente puoi terminare solo il subsystem grafico se usi altre componenti della SDL che restano attivi. Comunque considera che SDL non sono un toolkit (visto il genere di lavoro, forse ti consiglierei di usare QT anziche' SDL, che ha tutti i componenti gia' pronti e portabili e facili da usare per il lavoro che vuoi fare).

Prima di tutto devi definire come avviene l'aggiornamento in realtime: lo stream di dati e' continuo nel tempo? Utilizzi un range fisso o ti interessa fare plotting rispetto al tempo? Insomma, con "realtime" intendi che ti do ogni istante le coppie (x,y) di TUTTA la curva, o che man mano che te ne do una le altre "scrollano" indietro?

Fortunatamente per entrambe le strategie vanno bene le stesse strutture dati e lo stesso algoritmo di plotting: usi una std::list per tenerti i dati in input, solo che: se il realtime avviene "a frame" allora devi cancellare ogni volta la lista e rimettere tutti i dati in sequenza (vedi input stream iterator), altrimenti ti basta fare lista.pop_front() e lista.push_back(nuova_coordinata) qualora si presentasse un nuovo dato da inserire.

Algoritmo di plotting: questo dipende dalla libreria su cui ti appoggi e dai metodi che ti interessano... Fondamentalmente devi solo passargli i punti da disegnare, viene scandita la sequenza e lei fa il resto.
Il modo in cui lo fai e' solo scelto da te. Puoi disegnare i punti, linee spezzate, poligoni e curve con poca differenza di codice.

... Altrimenti c'e' gnuplot :D
Ciao

valentino861
Allora a me serve che grafica punto per punto dei dati in funzione del tempo e che gli altri valori "scrollino" indietro. Sto dando un'occhiata a gnuplot e qt ma non capisco come fare

akiross1
Ok. Gnuplot e' gia' fatto e puo' ricevere dei dati mediante file, ma non credo supporti la funzione in realtime. Diciamo che andrebbe bene se dovessi passargli un blocco di dati statico e via.

Con le Qt e' abbastanza semplice: senza coinvolgere sistemi piu' complicati, puoi disegnare punto per punto su un widget usando QPainter.
Ti faccio una breve sinossi.
Qt utilizza i widget per mostrare cose a schermo. Ogni oggetto che disegni e' di norma un QWidget. Li organizzi in modo gerarchico: creando un widget gli indichi il padre, e lui verra' disegnato all'interno del padre. Il primo widget che crei ovviamente non ha un padre e quindi verra' disegnato come una finestra sullo schermo.
Si, non esiste un oggetto "finestra" come nelle sdl. Questo significa che se hai un solo widget, diciamo un bottone, nelle Qt avrai una finestra con dentro un bottone enorme :)

Qt e' molto ampia, ma quando necessiti di qualcosa di nuovo (tipo un widget che disegni qualcosa di particolare), devi fare subclassing e scrivere il tuo metodo per disegnare quello che ti interessa. Poi usi quel widget normalmente e Qt fara' il resto.

Ecco cosa devi fare: crei un widget Plot che usa QWidget come base. Al suo interno magari puoi metterci una QList privata in cui terrai i punti del grafico.
Poi sovrascrivi il metodo paintEvent() che e' protected virtual.
Al suo interno, utilizzi l'oggetto QPainter per disegnare i punti che hai nella tua lista, e hai finito :)
Per tua fortuna, QPainter contiene tutti i metodi per disegnare usando pennelli, punti, linee curve e non, cerchi, etc etc. Insomma e' una cosa potentissima.

Ti consiglio di guardarti questo tutorial; il principio di quello che devi fare e' lo stesso, ma devi disegnare il grafico anziche' l'orologio
http://doc.trolltech.com/4.5/widgets-analogclock.html

Divertiti :)

apatriarca
È abbastanza facile da fare con qualsiasi libreria che permette di disegnare linee e altri elementi grafici. Per ogni frame devi principalmente fare le seguenti operazioni (supponendo tu stia lavorando in double buffering):
1. Cancellare il back buffer
2. Disegnare gli elementi aggiuntivi (di sfondo) del grafico (per esempio gli assi cartesiani o alcune scritte)
3. Disegnare una riga per ogni di coppia di punti (che variano da frame a frame)
4. Disegnare gli elementi aggiuntivi che possono stare sopra al grafico come la legenda
5. Scambiare i due buffer
Per quasi tutte queste operazioni devi leggere il manuale della libreria che hai scelto. I punti li puoi memorizzare in una lista come consigliato da akiross o in qualsiasi altra struttura dati che permette di memorizzare i dati in sequenza e permette inserimento in testa e cancellazione dei vecchi valori. Io utilizzerei un buffer circolare. Posso scriverti un esempio di codice se ne hai bisogno.

valentino861
Mamma mia che casino...:)
Scusate ma io fino a 3 settimane fa non sapevo neanche cosa fosse c++. Ok allora mi studio Qt che mi sembra il più adatto al mio scopo.

Un codice di esempio?? Magariiiiii

apatriarca
Io non credo che Qt sia la libreria migliore a questo scopo. È molto vasta ed essendo principalmente un framework per lo sviluppo di GUI richiede di strutturare l'applicazione in un modo particolare. Inoltre mi sembra richieda un procedimento particolare per compilare i programmi (è cambiato? ricordo male?).

Si tratta di un programma molto semplice e utilizzerei qualcosa di più semplice da usare. Credo la mia scelta cadrebbe sulla SFML (http://www.sfml-dev.org/). Ha obiettivi simili a quelli della SDL ma è più moderna e in C++.

valentino861
stavo per dirlo io. Mi sono installato qt e me lo sto studiando ma è davvero enorme e a me non serve assolutamente. Anzi in realtà la visualizzazione in real time neanche mi è fondamentale nel progetto la voglio io per vedere cosa accade, ma non è fondamentale, e quindi non mi va di torturarmi su un programma cosi vasto.

SFML com'è? Ma non esiste un'applicazione che faccia proprio questa cosA?

akiross1
Sulla enormita' di Qt mi viene un po' da ridere... A parte che Qt e' ben fatta e nativa su ogni sistema (e quindi e' molto veloce), ma il fatto che sia "un sacco di cose assieme" non vuol dire che non se ne possa usare una parte minuscola :D D'altronde quando si compila il codice, viene linkato solo il necessario.
Qt vengono usate per sviluppare applicazioni per cellulari... Dovrebbe dare l'idea di cosa intendo :D

apatriarca, qt usa qmake per compilare, ma non e' necessario. Io lo uso con scons, ma si puo' usare anche il classico -l e scegliere le librerie a mano se si vuole :) ovviamente, usare un sistema automatico ha i suoi enormi vantaggi. Il MOC e' necessario solo per alcune applicazioni, ma anche qui... Non mi pare sia un grosso problema.

Io la vedo cosi': Qt e' ben fatta, e' veloce, e' portabile e ti permette di fare questa applicazione in 200 righe di codice - con relativo guadagno di tempo, minor tempo di debug, facilita' di mantenimento e numero di bachi potenzialmente ridotto. Diciamo che da quando uso Qt, ho buttato via SDL (non che non siano valide, ma e' solo un fatto di struttura e bonta'). Il ruolo di una libreria e' facilitarti il compito. Dall'esperienza che ho, posso dire che Qt e' ottima per fare questo lavoro (e Moooooolti altri). Se vuoi posso aiutarti anche con le SDL, le OpenGL e probabilmente altro, ma puntavo a sprecare il minor tempo possibile, sia mio che tuo (vostro).

Dico solo che a meno che non ci siano problemi di licenze o di strumenti obsoleti, Qt e' una scelta ideale (svariati programmi di grafica usano Qt e Qt + OpenGL).
Poi la scelta non sta a me :D

Mi spiace, non conosco applicazioni che stampino un grafico in movimento.

valentino861
200 righe di codice :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock:

Ok non sarò mai in grado di farlo, soprattutto perchè è la parte meno importante del progetto, la volevo utilizzare solo per tenere sotto controllo l'esecuzione del programma, mamma mia :shock:, credo che neanche tutto il progetto sono 200 righe :-D

ok ragazzi andando molto molto sul più semplice la libreria che ho ora chplot.h mi posta una schermata con il grafico ma mi interrompe il programma, conoscete un modo per non far fermare l'esecuzione del programma? Cosi ogni 16384 valori mi si aggiorna il grafico e a me va benissimo cosi :-D :-D

akiross1
Ah bhe ok, pensavo che il tuo scopo fosse fare quello :D Visto che sei partito dalle SDL... Buona fortuna con chplot!

valentino861
sto vedendo ora che chplot mi apre semplicemente una schermata di gnuplot. Su gnuplot non posso impostare un aggiornamento, oppure un tempo per il quale deve rimanere aperto e poi chiudersi da solo?

valentino861
come faccio a comandare gnuplot da c++? Sto seguendo questa guida e a quanto leggo se faccio un if con l'istruzione reread, e gli faccio leggere un file dove metto i dati, credo dovrebbe stampare continuamente no?
Ma queste sono istruzione per la command line di gnuplot giusto?

http://t16web.lanl.gov/Kawano/gnuplot/misc1-e.html#9.1a

apatriarca
"akiross":
Sulla enormita' di Qt mi viene un po' da ridere... A parte che Qt e' ben fatta e nativa su ogni sistema (e quindi e' molto veloce), ma il fatto che sia "un sacco di cose assieme" non vuol dire che non se ne possa usare una parte minuscola :D D'altronde quando si compila il codice, viene linkato solo il necessario.
Qt vengono usate per sviluppare applicazioni per cellulari... Dovrebbe dare l'idea di cosa intendo :D

apatriarca, qt usa qmake per compilare, ma non e' necessario. Io lo uso con scons, ma si puo' usare anche il classico -l e scegliere le librerie a mano se si vuole :) ovviamente, usare un sistema automatico ha i suoi enormi vantaggi. Il MOC e' necessario solo per alcune applicazioni, ma anche qui... Non mi pare sia un grosso problema.

Io la vedo cosi': Qt e' ben fatta, e' veloce, e' portabile e ti permette di fare questa applicazione in 200 righe di codice - con relativo guadagno di tempo, minor tempo di debug, facilita' di mantenimento e numero di bachi potenzialmente ridotto. Diciamo che da quando uso Qt, ho buttato via SDL (non che non siano valide, ma e' solo un fatto di struttura e bonta'). Il ruolo di una libreria e' facilitarti il compito. Dall'esperienza che ho, posso dire che Qt e' ottima per fare questo lavoro (e Moooooolti altri). Se vuoi posso aiutarti anche con le SDL, le OpenGL e probabilmente altro, ma puntavo a sprecare il minor tempo possibile, sia mio che tuo (vostro).

Dico solo che a meno che non ci siano problemi di licenze o di strumenti obsoleti, Qt e' una scelta ideale (svariati programmi di grafica usano Qt e Qt + OpenGL).
Poi la scelta non sta a me :D

Mi spiace, non conosco applicazioni che stampino un grafico in movimento.


Con enorme non intendevo dire che era pesante, solo che richiedeva un po' di tempo per riuscire ad usarla al meglio. Visto che valentino86 usa il C++ da sole 3 settimane potrebbe non conoscere tutte le funzionalità del linguaggio necessarie per usarle. Non metto in dubbio che sia potente, ma non credo sia la scelta ideale per questo progetto.

Non vedo sinceramente come Qt fornisca un vantaggio contro SFML in questo caso comunque. Nessuna delle funzionalità di Qt è utile a diminuire il numero di righe essendo necessario creare semplicemente una finestra con dentro un singolo elemento grafico (esattamente la finestra che crea SFML) e disegnare al suo interno una semplice linea spezzata (e qualche altro elemento di contorno). La parte in cui si disegnano gli elementi è uguale con qualsiasi libreria (anche le OpenGL ad esempio) e il resto credo possa essere scritto in 10-20 righe di codice con SFML.

Per quanto riguarda l'uso di qmake. Io uso normalmente Visual Studio quando lavoro su Windows e trovo quindi scomodo dover ricorrere a strumenti esterni. Ho visto che esistono tutorial per migliorare l'integrazione ma le soluzioni non sono comunque ottimali. Quindi preferisco utilizzarla su Windows solo quando il suo uso è in qualche modo motivato, se devo creare solo una finestra ci metto poco anche usando le Win32 direttamente (l'IDE mi scrive il codice in automatico). Su linux ovviamente il discorso è un po' diverso.

valentino861
mi sto vedendo gnuplot che ormai ritengo il più accessibile per le mie capacità.
Non riesco però a fargli aprire un file da c++.
Praticamente cosi mi apre gnuplot

system("start C:\\wgnuplot.exe");

e ho trovato in rete che cosi dovrebbe aprire il txt con gnuplot e invece no:

system("start C:\\wgnuplot.exe C:\\mycmdfile.txt");

akiross1
"apatriarca":
Con enorme non intendevo dire che era pesante, solo che richiedeva un po' di tempo per riuscire ad usarla al meglio.

Il discorso e' che per disegnare un grafico va comunque bene: Qt e' facile da usare per fare molte cose e come ho detto, per disegnare basta fare subclassing ed ereditare un metodo. Non e' una funzione avanzata di C++ e anche a non conoscerla e' un concetto capibile in 5 minuti :)
L'unica "pecca" di Qt e' che per usarle al meglio dovresti conoscerle per intero, ed essendo grosse... Ma suppongo ci si possa fidare se dico che per lo scopo si possono usare facilmente :D

"apatriarca":
Non vedo sinceramente come Qt fornisca un vantaggio contro SFML in questo caso comunque. (cut) La parte in cui si disegnano gli elementi è uguale con qualsiasi libreria (anche le OpenGL ad esempio) e il resto credo possa essere scritto in 10-20 righe di codice con SFML.

Non conosco SFML (ci ho dato un occhio in fretta), quindi non saprei davvero giudicare. Come ho detto, pero', pensavo che il suo scopo fosse fare il programma di plotting, non "usare" il programma di plotting. E' ovvio che usare una libreria completa di widget potrebbe risultare molto utile se decidesse di metterci, ad esempio, un semplice bottone per cancellare la schermata (sparo a caso). Non so se SFML lo fa. E' che quando inizio un progetto penso gia' a cosa si potrebbe voler fare in futuro, quindi cerco la completezza degli strumenti (e qui stava il "vantaggio"). Ma, come ho detto, ha detto che questa e' una cosa "marginale" nel progetto. Neanche avrei scomodato C++ per una cosa simile :)
Sul "disegnare gli elementi con qualsiasi libreria", non sono affatto d'accordo. Forse sei abituato a librerie dove si usa line(qui, li, la, lassu) e circle(qui, li, raggio), ma ti assicuro che non e' una cosa banale. Con le SDL, tanto per cominciare, tutto questo non si puo' fare e servono delle estensioni. Con le OpenGL e' una pratica sconsigliata e obsoleta. Anche per disegnare una spezzata si dovrebbero usare i vertex buffer.

"apatriarca":
Per quanto riguarda l'uso di qmake. (etc)

Ragione comprensibilissime :) Non so cosa tu intenda per "ottimale", so che molta gente usa qt con eclipse o visual studio e pare che il tutto funzioni... Anzi, dubito che la maggioranza degli utenti abituali faccia "qmake -project ; qmake ; make" da console :D
Comunque, a parte il MOC (che e' configurabile come un compilatore normale), qmake non e' affatto necessario... E' solo utile e veloce. Usarlo e' solo un optional.

A parte tutto questo, son convinto che una scelta possa valere l'altra in questo caso... Io opterei per le Qt perche' le conosco e trovo che siano migliori di molte altre librerie, tutto qui :)

Valentino86, gnuplot in batch si usa proprio cosi', come da manuale: http://www.gnuplot.info/docs/node46.html
"invece no", cosa vuol dire? Che te lo apre ma non ti esegue il file dei comandi? O che non ti avvia gnuplot?
Lo stesso comando da console ti funziona o neanche li?

Curiosita' mia, da ignorantone visto che non sono su windows: perche' ci metti "start" davanti al path del programma? In windows non basta mettere il percorso all'eseguibile? Non e' che serve una sintassi particolare di start per passare parametri al programma? (e.g. "start programma - parametri")

Ciao

valentino861
allora cosi mi si apre gnuplot (ho messo l'eseguibile nella directory del progetto):
#include <stdlib.h>
#include <stdio.h>

int main()
{
	system("wgnuplot.exe "); 


getchar();
return 0;
}



ma cosi non si apre ne file .txt ne gnuplot:
#include <stdlib.h>
#include <stdio.h>

int main()
{
	system("wgnuplot.exe mycmdfile.txt"); 


getchar();
return 0;
}


Io ho visto in rete che si potrebbe fare anche con gnuplot in real time

akiross1
"valentino86":
ma cosi non si apre ne file .txt ne gnuplot
system("wgnuplot.exe mycmdfile.txt");


Mmmmh mi sembra strano :E Mi vengono dubbi sul passaggio di parametri a system(), ma d'altronde ha un solo parametro...
Scrivendo direttamente a console quel comando gnuplot fa quel che deve?

akiross1
Ah, fai una cosa utile: controlla il valore di ritorno della system(): se e' diverso da 0 vuol dire che c'e' stato un errore (e magari si capisce meglio cosa non va).

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.