/* Programa    campo_vet.c
   Assunto:		Solução aproximada de EDO - isoclinas
	Condicionantes: compile e rode campo_vet_exec.c
	
	Programa sem erros
         
	Descrição: 

	Palavras-chave: aproximacao, edo, solucao aproximada,	campo vetorial
	por Tarcisio Praciano Pereira - 10 lições para aprender C
	Sobral, Maio de 2003   - UVA
*/
                  
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "/home/tarcisio/tex/c/disco/ambiente.h"

typedef struct {float a; float b; float c; float d; 
		float passoX; float passoY; int papel;}
		malha; // (10) (20)

float	f(float x, float y); // equação diferencial
void	reta(float a, float b, float m);
malha	entrada_dados(malha u_malha);
void	cria_eixos(malha u_malha);
void	cria_transfere(int papel);
void	executa(malha u_malha);
void	apaga_arquivos();

int	main()
{
	malha	u_malha={-4,4,-4,4,0.3, 0.3, 0}; // valores padrão
        u_malha = entrada_dados(u_malha);
        cria_eixos(u_malha);
        cria_transfere(u_malha.papel); // (10) (20)
        executa(u_malha);
	//*** chama um processo externo, Gnuplot com linha de comandos
	system("gnuplot transfere");
	apaga_arquivos();	
	apetecof();        
	return(0);
}


malha	entrada_dados(malha u_malha)
{
        // valores padrão
        int	papel = 0; // (10) padrão - figura na tela
	limpa_janela();
	printf("\t Dê enter para aceitar o valor default - vale a pena numa \n");
	printf("experiência inicial !  \n");
	printf("\n ===============================================  \n");
	printf("Intervalo  [a,b] : \n");
	u_malha.a = entrada_float("O início do intervalo   a = ", u_malha.a);
	u_malha.b = entrada_float("Fim  do intervalo   b = " , u_malha.b);
	printf("Intervalo  [c,d] : \n");
	u_malha.c = entrada_float("O início do intervalo   c = ", u_malha.c);
	u_malha.d = entrada_float("Fim  do intervalo   d = ", u_malha.d);
	u_malha.passoY = entrada_float(
		"0.1 < delta < 0.5 delta = ",u_malha.passoY);
	printf("Você pode escolher que o gráfico vá para o papel \"teste.fig\"\n");
	printf("Escolha  0 (na tela  (default)) ou 1  para o papel \n"); 
	papel =  entrada_inteira("0 = tela (default) , 1 = papel ",papel);
	u_malha.passoX = u_malha.passoY;
	apeteco2(); limpa_janela();
	quatrolinhas();
	printf("===================== fim da  ===========================\n");
	printf("==============  entrada de dados  =====================\n");
	apeteco2();
	return(u_malha);	
}


void	cria_eixos(malha u_malha)
{
	// Os eixos dos X
	FILE	*data;
	data = fopen("XOY","w"); // (2)	
	fprintf(data,"%f %f \n",u_malha.a , 0.);
	fprintf(data,"%f %f \n",u_malha.b , 0.);		
	fprintf(data,"\n");
	fprintf(data,"\n");		
	fprintf(data,"%f %f \n", 0., u_malha.c);
	fprintf(data,"%f %f \n",0. , u_malha.d);		
	fclose(data);
	data = fopen("dados","w"); // (2)	
	fclose(data); // cria o arquivo "dados"
}

void	executa(malha u_malha)
{
	float  x,y,passoX, passoY;
	passoX=u_malha.passoX; passoY=u_malha.passoY;
	x = u_malha.a; 
	while(x < u_malha.b)
	{
		y = u_malha.c;
		while (y < u_malha.d)
		{
			reta(x,y,f(x,y));
			y = y + passoY;	
			printf("...");
		}
		x = x + passoX;
	}


}


// calcula o segmento de reta (pontos extremos do)
// (a,b) ---> a - rho*cos(theta), b - rho*sin(theta))
void	reta(float a, float b, float m)
{
	FILE	*data;
	float	rho=0, theta,delta=0.5;
	data=fopen("dados","a");
	theta = atan(m); 		// coef ang --->  ângulo
	// imprime dois pontos do segmento de reta
	// o "centro" do segmento de reta
	fprintf(data, "%f  %f \n",a - rho*cos(theta), b - rho*sin(theta));
	rho = delta; 	// altera o valor de rho
	// imprime o "extremo" do segmento de reta
	fprintf(data, "%f  %f \n",a + rho*cos(theta), b + rho*sin(theta));	
	fprintf(data, " \n"); // imprime duas linhas em branco
	fprintf(data, " \n");		
	fclose(data);
}

//  A variavel papel define se a figura vai para tela ou para papel
void	cria_transfere(int papel)
{
	FILE *data;
	data = fopen("transfere","w"); // (2)	
	//***	Sob LinuX esta primeira linha fara de "data-->"
	//***	um "arquivo de lote" para "/usr/bin/gnuplot"
	fprintf(data,"#! /usr/bin/gnuplot\n");
	fprintf(data, "set pointsize %f \n", 0.1);
	if (papel)
		{
			fprintf(data, "set terminal post portrait enhance color \n");
			fprintf(data, "set output \"teste.eps\" \n");
		}
	fprintf(data, "set size %f , %f \n",1.,1.0);
	fprintf(data, "plot \"dados\" with lines, \"XOY\" with lines \n");
	fprintf(data, "pause -2 \n");
	fclose(data);
}

void	apaga_arquivos()
{
        limpa_janela();
        printf("\n\nVocê pode optar por apagar os arquivos criados pelo \n");
        printf("programa ou não apagá-los. Se não apagar, poderá rodar  \n");
        printf("gnuplot e ver novamente os gráficos ou editar os arquivos   \n");
        printf("para fazer alguma experiência com os mesmos.        \n");
        printf("A resposta padrão é \"não\" dê enter para aceitá-la.\n");
        apeteco2();         
	printf("\nApaga os arquivos criados pelo programa ?");
	if (sim_nao()){
	        limpa_janela();
		printf("Arquivos apagados como você pediu...\n");
		system("rm -f transfere dados XOY");
	}
	else {
	limpa_janela();
	printf("\nOs arquivos não foram apagados e você pode ver o\n");
	printf("gráfico digitando\n\n gnuplot transfere\n\n  neste diretório.\n");   
	}
}

float f(float x, float y)
{
	return(x*x + x*y + y*y);
}

/* comentários:

(10) O programa pode mandar a figura para tela ou para papel (arquivo).
     Padrão  papel = 0  >> figura na tela
	     papel = 1  >> cria um arquivo  .eps 
     O último campo da malha guarda o valor de papel 
     
(20) Acrescentei um campo do tipo int em malha para transferir a opção
     papel \in {0, 1}  para decidir se a figura vai para papel (arquivo)

     ou para tela.     
*/