// ..............................................................trasformata.cc
#include <curses.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "corso.h"

extern XVideoData xvd;

double func(double x,double w);

main()
{
	int biPoints,halfPoints,i,lg2n,nComm,nPar,nPoints,NuoviPunti,OldPoints,
	ridisegna,x0m,x0p,x1m,x1p,y0,y1;
	clock_t musec1,musec2;
	timespec ts1,ts2;
	double fOffs,fScale,oldW,tOffs,tScale,w,x,yMax,yMin;
	double *fun,*transf;
	char answ[122],buff[40];
	char **comandi,**ParName,**ParVal;
	FILE *hnd;
	
	// ........................................................... tempo di sonno
	ts1.tv_sec=0;
	ts1.tv_nsec=10000000;
	// ............................................................. modo grafico
	StartXWindow(800,600,0,0,"Trasformata",2);
	// .................................................................. comandi
	nComm=1;
	comandi=new char * [nComm];
	comandi[0]="Fine";
	// ................................................................ parametri
	nPar=2;
	ParName=new char * [nPar];
	ParVal=new char * [nPar];
	for (i=0;i<nPar;i++) ParVal[i]=new char [28];
	ParName[0]="Larghezza";
	ParName[1]="Numero di Punti";
	w=10.0;
	sprintf(ParVal[0],"%.5lf",w);
	OldPoints=0;
	nPoints=1024;
	sprintf(ParVal[1],"%d",nPoints);
	
	// .......................................................... disegna il menu
	XSync(xvd.display,TRUE);
	XWinPermMenu(1,"Trasformata",ParName,ParVal,nPar,28,comandi,nComm,0);
	// .................................................................... ciclo
	NuoviPunti=TRUE;
	ridisegna=TRUE;
	for (;;)
	{
		nanosleep(&ts1,&ts2);
		if (NuoviPunti)
		{
			if (OldPoints>0)
			{
				delete [] fun;
				delete [] transf;
			}
			biPoints=nPoints*2;
			halfPoints=nPoints/2;
			fun=new double [biPoints];
			transf=new double [biPoints];
		}
		if (ridisegna)
		{ // .................................................. calcola la funzione
			yMin=1.0e100;
			yMax=1.0e-100;
			for (i=0;i<halfPoints;i++)
			{
				x=double(i);
				fun[2*i]=fun[biPoints-2-2*i]=func(x,w);
				fun[2*i+1]=fun[biPoints-1-2*i]=0;
				if (fun[2*i]<yMin) yMin=fun[2*i];
				if (fun[2*i]>yMax) yMax=fun[2*i];
				fun[2*i+1]=0;
			}
			fScale=400.0/(yMax-yMin);
			fOffs=yMin;
			// ............................................... calcola la trasformata
			for (i=0;i<biPoints;i++) transf[i]=fun[i];
			fft(transf,nPoints,+1);
			yMin=1.0e100;
			yMax=1.0e-100;
			for (i=0;i<nPoints;i++)
			{
				if (transf[2*i]<yMin) yMin=transf[2*i];
				if (transf[2*i]>yMax) yMax=transf[2*i];
				fun[2*i+1]=0;
			}
			tScale=400.0/(yMax-yMin);
			tOffs=yMin;
			// .............................. seleziona e pulisci il contesto grafico
			XSetForeground(xvd.display,xvd.gc,xvd.white);
			XFillRectangle(xvd.display,xvd.backpix[0],xvd.gc,0,0,800,600);
			// .................................................. disegna la funzione
			XSetForeground(xvd.display,xvd.gc,xvd.black);
			y0=int((499.0-fScale*(fun[0]-fOffs))+0.5);
			x0m=x0p=400;
			for (i=0;i<halfPoints;i++)
			{
				y1=int((499.0-fScale*(fun[2*i]-fOffs))+0.5);
				x1m=x0m-1;
				x1p=x0p+1;
				XDrawLine(xvd.display,xvd.backpix[0],xvd.gc,x1p,y1,x0p,y0);
				XDrawLine(xvd.display,xvd.backpix[0],xvd.gc,x1m,y1,x0m,y0);
				y0=y1;
				x0p=x1p;
				x0m=x1m;
				if (x0m<0 || x0p>xvd.width[0]) break;
			}
			XPrintf(0,10,560,1,TRUE,"Funzione");
			// ............................................... disegna la trasformata
			XSetForeground(xvd.display,xvd.gc,xvd.red[0]);
			y0=int((499.0-tScale*(transf[0]-tOffs))+0.5);
			x0m=x0p=400;
			for (i=0;i<halfPoints;i++)
			{
				y1=int((499.0-tScale*(transf[2*i]-tOffs))+0.5);
				x1m=x0m-1;
				x1p=x0p+1;
				XDrawLine(xvd.display,xvd.backpix[0],xvd.gc,x1p,y1,x0p,y0);
				XDrawLine(xvd.display,xvd.backpix[0],xvd.gc,x1m,y1,x0m,y0);
				y0=y1;
				x0p=x1p;
				x0m=x1m;
				if (x0m<0 || x0p>xvd.width[0]) break;
			}
			XPrintf(0,10,580,1,TRUE,"Trasformata");
			XRedraw();
		}
		// ....................................................... chiama il menu
		for (;;)
		{
			nanosleep(&ts1,&ts2);
			XSync(xvd.display,FALSE);
			i=XWinPermMenu(1,"Trasformata",ParName,ParVal,nPar,28,comandi,nComm,1);
			if (i==0) break;
			nPoints=atoi(ParVal[1]);
			for(lg2n=1;;lg2n++) if ((nPoints>>lg2n)==1) break;
			if ((1<<lg2n)!=nPoints) snprintf(ParVal[1],40,"%d non va bene!",nPoints);
			else break;
			XRedraw();
		}
		if (i==0) break;
		w=atof(ParVal[0]);
		ridisegna=(w!=oldW || nPoints!=OldPoints);
		NuoviPunti=(nPoints!=OldPoints);
		OldPoints=nPoints;
		oldW=w;
		XSync(xvd.display,TRUE);
		XRedraw();
	}
	// ..........................................................................
	XWinPermMenu(1,"Trasformata",ParName,ParVal,nPar,28,comandi,nComm,2);
	// ................................................................. clean-up
	delete [] comandi;
	delete [] fun;
	delete [] transf;
	CloseXWindow();
}

// ------------------------------------------------------------------------

double func(double x,double w)
{ 
	return exp(-pow(x/w,2));
    //return w*w/(x*x+w*w);
}


