[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
no! Ho messo la cartella di gnuplot (scaricata da qui http://archives.math.utk.edu/software/m ... lot/msdos/) sul desktop.
Poi ho messo nella stessa cartella questi due file presi da qui per fare una prova http://www.quantfinancejobs.org/modules ... hp?faqid=5

Anche se faccio partire gnuplot.exe e poi scrivo load 'mycmdfile.txt' non parte....mmmm

valentino861
"akiross":
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).


mmmm....come faccio?! :oops:

akiross1
int valore = system("comando");
if (valore != 0)
printf("Errore! %d\n", valore);

valentino861
errore 1

valentino861
comando non è riconoscibile come un file interno o esterno, programma eseguibile o un file patch. Errore! 1


Però con system ("wgnuplot.exe") me lo apre, che significa?

valentino861
nel frattempo sto capendo gnuplot, e ho capito come plottare dei grafici partendo da file esterni.

akiross1
Significa che probabilmente system() cerca di lanciare il comando "gnuplot file" anziche' lanciare "gnuplot" passandogli "file" come parametro... Probabilmente il contenuto di system deve essere il nome di un comando valido, parametri esclusi.

valentino861
??????mi sono perso

apatriarca
Il seguente codice mi funziona correttamente su Windows (compilato con Visual Studio):
#include <stdlib.h>

int main()
{
    system("wgnuplot.exe simple.dem");
}

Quindi secondo me il problema è semplicemente dovuto ad un problema di path. Hai provato a lanciare quel comando dalla stessa cartella in cui hai l'eseguibile? system non permette però di mandare messaggi al processo che hai creato, cosa che credo sia necessaria per poter modificare i dati in real-time. Dovresti dare un occhiata alla funzione _swapnl e simili.

Che compilatore stai usando?

valentino861
bhe per lo meno è la prima volta che sono riuscito ad avere un grafico come dico io.
Praticamente ho fatto partire l'analisi del mio programma c++ e gli ho fatto mettere i dati in un file. Poi ho aperto gnuplot e gli ho fatto aprire un file di testo con scritto:
plot 'C:\Users\Valerio\Documents\Visual Studio 2005\Projects\unione\unione\dati.dat' with linespoints
pause 3
reread

praticamente ogni 3 secondi mi fa un aggiornamento dei dati :-D :-D :-D :-D :-D :-D :-D :-D

Solo che è un pò rozzetto come impostazione, e in più non riesco a farlo partire direttamente da c++ (quel dannato system).

valentino861
"apatriarca":
Il seguente codice mi funziona correttamente su Windows (compilato con Visual Studio):
#include <stdlib.h>

int main()
{
    system("wgnuplot.exe simple.dem");
}

Quindi secondo me il problema è semplicemente dovuto ad un problema di path. Hai provato a lanciare quel comando dalla stessa cartella in cui hai l'eseguibile? system non permette però di mandare messaggi al processo che hai creato, cosa che credo sia necessaria per poter modificare i dati in real-time. Dovresti dare un occhiata alla funzione _swapnl e simili.

Che compilatore stai usando?



ok ok funziona anche a me...forse si sbagliavo le patch.

Adesso mi esce in real time ma si impalla subito, come posso fare :evil:

apatriarca
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

Intendevo proprio quella pecca. per usarla al meglio è necessario studiarla a fondo e ci vuole del tempo. È vero che l'ereditarietà non è una funzionalità molto complicata, ma sui libri sul C++ le classi e la programmazione ad oggetti vengono spesso trattati abbastanza tardi. Non è quindi detto che valentino86 ne sappia qualcosa della programmazione ad oggetti in C++. Vista l'inclusione delle librerie C usando la sintassi invece che immagino stia usando delle fonti abbastanza datate o tutorial in rete che prediligono una formazione iniziale legata al C. Non ho comunque niente contro Qt, si tratta senza dubbio di una libreria molto potente.

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 :)

Avendo risposto alla sua precedente discussione immaginavo fosse solo un aggiunta e non il vero scopo dell'applicazione. È principalmente per quello che ritenevo migliore SFML rispetto a Qt. SFML ha scopi e funzionalità simili a quelle di SDL, anche se è scritto in C++ ed è quindi ad oggetti. Non è quindi adatta allo sviluppo di una GUI (anche se può essere integrata con Qt, wxWidget, Win32...). Ma se lo scopo è solo quello di visualizzare dei dati allora è più che sufficiente e forse più semplice da usare (ma è probabilmente solo una questione di gusti in ogni caso).

Anche io non avrei usato il C++ per questo comunque. Avrei probabilmente valutato l'uso di Python o i linguaggi .NET.


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.

A dire il vero mi occupo principalmente di grafica 3D e non uso mai librerie con funzioni tipo line e circle. Ma questa applicazione è molto semplice da realizzare con qualsiasi libreria che fornisca quelle funzionalità (quindi non SDL). Mi vengono per esempio in mente anche cairo o GDI.
Non ho mai detto che nelle OpenGL avrei usato l'immediate mode. Non vedo sinceramente nessun vantaggio di questo metodo rispetto ai vertex arrays. I VBO richiedono certamente un po' più di codice ma alla fine la differenza riguarda più che altro l'inizializzazione dei vari stati. Non volevo consigliarla comunque, ho parlato delle OpenGL solo perché il codice per disegnare il grafico non sarebbe molto più lungo nonostante sia di livello molto più basso (quello che cambia è principalmente la lunghezza del resto del codice).

apatriarca
"valentino86":
[quote="apatriarca"]Il seguente codice mi funziona correttamente su Windows (compilato con Visual Studio):
#include <stdlib.h>

int main()
{
    system("wgnuplot.exe simple.dem");
}

Quindi secondo me il problema è semplicemente dovuto ad un problema di path. Hai provato a lanciare quel comando dalla stessa cartella in cui hai l'eseguibile? system non permette però di mandare messaggi al processo che hai creato, cosa che credo sia necessaria per poter modificare i dati in real-time. Dovresti dare un occhiata alla funzione _swapnl e simili.

Che compilatore stai usando?



ok ok funziona anche a me...forse si sbagliavo le patch.

Adesso mi esce in real time ma si impalla subito, come posso fare :evil:[/quote]
Quel file viene modificato dal tuo programma? Potresti postare il tuo programma in C++ in modo da testarlo?

valentino861
il mio programma non potresti testarlo cmq perche prendo i dati da un accelerometro attaccato all'usb.

Però adesso posto quello che ho fatto che mi sembra ragionevole. Metto i dati in un file e li faccio leggere a gnuplot, e lui li aggiorna ogni 3 secondi.

valentino861
Mi raccomando non vi spaventate :-D :-D :-D


HO ELIMINATO LE VARIE PROVE CHE AVEVO FATTO

/*Il dispositivo ha una frequenza di campionamento di 0,06 (eventi/ms) e quindi un periodo di 16,667 (ms/evento), 
da manuale sono 60(samples/s).
*/

#include <chplot.h>
#include <math.h>
#include "stdafx.h"
#include "phidget21.h"
#include <time.h>
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;


//Include il file iso631.cpp, con la sua funzione iso2631()
extern int iso2631();


//VARIABILI PER L'ACCELEROMETRO
#define MAX_INT 16384 
int millis;
int t=0;
double accz[MAX_INT];
double tempo[MAX_INT];


FILE* dati= fopen("dati.dat","w");


//Chiamata che registra una variazione di accelerazione (è un loop)
int __stdcall accel_AccelChangeHandler(CPhidgetAccelerometerHandle WGT, void *userptr, int Index, double Value)
{

	
	//Filtro per un solo asse dell'accelerometro
	if(Index==0){	
			
		//Condizione per cui esegue l'analisi dell'rms
			if(t==MAX_INT)
			    {
				//Perchè nell'else l'ultima istruzione è t++
				t--;

				 fclose (dati);


			          system("wgnuplot.exe prova.txt");


				dati= fopen("dati.dat","w");
				//IMPORTA LA FUNZIONE ISO2631
				iso2631();
				
				//Riporta a 0 il contatore dell'array accez e tempo
				t=0;
			    }
			else		
			    {
				//Funzione della libreria time.h
				clock_t clock();	
				//Quanti cilci fa il PC in un millesimo di secondo		
				millis=CLOCKS_PER_SEC/1000;					
				//Scrive in accz[] il valore dell'accelerazione
				accz[t]=Value;
				//Tempo in secondi
				tempo[t]=0.001*(clock()/millis);

				fprintf (dati,"%f %f\n",tempo[t],accz[t]);
		
				//Stampa a video il contatore degli array, tempo, l'asse e l'accelerazione
				printf("t= %i Secondi: %f Asse: %i Accel: %6f\n",t,tempo[t], Index,accz[t] );
				//Incrementa il contatore degli array
				t++;				
			}
	}
	//Chiusura dell'if per l'indice accelerometro
	}
return 0;

//Chiusura chiamata accel_AccelChangeHandler
}

//Entrata principale del programma
int main(int argc, char* argv[])
{
	int result;
	const char *err;



	//Declare an accelerometer handle
	CPhidgetAccelerometerHandle accel = 0;
   
	//create the accelerometer object
	CPhidgetAccelerometer_create(&accel);

	//Impostando -1 apre il primo dispositivo disponibile
	CPhidget_open((CPhidgetHandle)accel, -1);

	//get the program to wait for an accelerometer device to be attached
	printf("Waiting for accelerometer to be attached.... \n\n");

	//Aspetta 10 secondi che venga connesso il dispositivo
	if((result = CPhidget_waitForAttachment((CPhidgetHandle)accel, 10000)))
		{	CPhidget_getErrorDescription(result, &err);
			printf("Problem waiting for attachment: %s\n", err);
			//Interruzione, spingere invio per continuare
			getchar();
			return 0;}

	//Imposta la sensibilità
	CPhidgetAccelerometer_setAccelerationChangeTrigger(accel, 0, 0.00);
	CPhidgetAccelerometer_setAccelerationChangeTrigger(accel, 1, 0.00);
	CPhidgetAccelerometer_setAccelerationChangeTrigger(accel, 2, 0.00);

	

	//Registra un evento se l'accelerazione cambia oltre una certa soglia.
	CPhidgetAccelerometer_set_OnAccelerationChange_Handler(accel, accel_AccelChangeHandler, NULL);

	//Interruzione
	getchar();

	//Chiude il dispositivo e l'oggetto
	printf("Closing...\n");
	CPhidget_close((CPhidgetHandle)accel);
	CPhidget_delete((CPhidgetHandle)accel);

	//Interruzione
	getchar();

	return 0;
}




non so dove mettere il system

valentino861
E se usassi una cosa del genere??

http://www.oscilloscope-lib.com/


PS: cmq uso visual c++ 2005 express edition

valentino861
ho consumato google questi giorni :)

http://ttsiodras.googlepages.com/gnuplotStreaming.html


Mi aiutate a capire come ha fatto?

akiross1
"apatriarca":
A dire il vero mi occupo principalmente di grafica 3D e non uso mai librerie con funzioni tipo line e circle.

Ecco, anche io l'ho fatto per anni, pertanto saprai quanto me che ogni libreria ha i suoi modi :D Si certo, usando l'immediate mode in OGL non e' molto diverso, ma concorderai che fare un grafico in stile punti-linee BGI e' un po' diverso che usare i VBO ;) Anche perche' se usi QPainter le curve Bezier te le calcola lui (mi pare), se usi le OpenGL... Bhe, da quello che ricordo le curve non sono una gioia da usare con le OGL :)

Per il resto delle questioni, sei stato chiarissimo :D


valentino86, gnuplot puo' anche ricevere i dati in input da console: hai pensato a stampare direttamente i comandi gnuplot dal tuo programma e lanciare il tutto usando la redirezione? tuoprogramma | gnuplot

In questo modo l'output del tuo programma viene messo in ingresso a gnuplot, che funzionerebbe come se fossi tu a scrivere a mano ogni istruzione.
(Sempre se esiste la redirezione su windows :D)

La oscilloscope lib non sembra male! E non sembrava male neanche quella che usavi prima...

akiross1
"valentino86":
ho consumato google questi giorni :)

http://ttsiodras.googlepages.com/gnuplotStreaming.html

Mi aiutate a capire come ha fatto?


Fantastico, proprio quello che intendevo dire :D

Bhe, come vedi usa uno script perl per eseguire i comandi di impostazione di gnuPlot. Se hai possibilita' di usare perl fai prima ad usare quello script :)
Comunque non e' necessario (credo). Da quel che vedo lo usa per configurare gnuplot.

Il succo del discorso e' che usa le pipe (cioe' redirezione dell'output) come ti ho detto prima.
Se non usi perl, puoi scrivere la configurazione che ti interessa dal tuo programma:
print("set range") etc etc, come fa nel file perl
poi semplicemente scrivi i punti come fa nell'esempio riportato:
while(1) {
  print sin($offset)."\n";
  print cos($offset)."\n";


Fatto questo il tuo programma lo lanci con: tuoprog | gnuplot

Il programma stampera' i comandi e i dati necessari che verranno letti da gnuplot e stampati.

Ora devo andare, sono di fretta, ma i dettagli su cosa fa son tutti nello script!

Ciao

apatriarca
"akiross":
[quote="apatriarca"]A dire il vero mi occupo principalmente di grafica 3D e non uso mai librerie con funzioni tipo line e circle.

Ecco, anche io l'ho fatto per anni, pertanto saprai quanto me che ogni libreria ha i suoi modi :D Si certo, usando l'immediate mode in OGL non e' molto diverso, ma concorderai che fare un grafico in stile punti-linee BGI e' un po' diverso che usare i VBO ;) Anche perche' se usi QPainter le curve Bezier te le calcola lui (mi pare), se usi le OpenGL... Bhe, da quello che ricordo le curve non sono una gioia da usare con le OGL :)[/quote]
Ma i grafici non si fanno usando le curve di Bézier... I punti di controllo di una curva di Bézier non si trovano sulla curva mentre i samples che valentino86 cattura lo sono. Credo sia quindi più opportuno l'uso di una semplice linea spezzata o una catmull-rom spline. La prima è ovviamente molto semplice da implementare, mentre per la seconda è più complicata e non sempre presente. Io pensavo di disegnare il grafico facendo semplicemente una linea spezzata.

Sfortunatamente in Windows la shell è molto meno potente e credo sia quindi necessario usare le API di Windows.

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