Hola, uno de los grandes problemas que tenemos los matemáticos cuando programamos en C/C++ es poder dibujar las funciones matemáticas que podamos estar utilizando en nuestros códigos. Podríamos solucionarlo utilizando las librerías OpenGL o algunas del mismo corte, estas están bien para funciones en 2D y sin utilizar muchas florituras, pero si pasamos a 3D se hacen bastante difíciles la creación de nuestros códigos; además de ralentizar su funcionamiento. Así que utilizando Ubuntu y conociendo la existencia del programa gnuplot ( que se ejecuta por terminal) pensé si sería posible abrirlo desde un programa que estemos escribiendo en C/C++.
Como desde hace años todo lo que aprendo de C++ es por internet, libros, amigos ( autodidacta) pensé buscar en internet información sobre ello o algún código ya hecho. Resultó que había bastante información del tema, mucha de ella eran códigos escritos en C, muy largos y farragosos. La mayoría utilizaban la función popen(), la cual desconocía (( ya mencioné que soy autodidacta )) . Seguí buscando y al final encontré en un foro una cita sobre un código escrito por alguien de habla Shaekesperiana que había escrito el código en C++ utilizando clases y para Linux. El enlace en cuestión es en Foros Del Web.
Pensé que si funcionaba sería genial, ya que aparte de tener un código escrito en C++, lo podría tener en formato de clases y, no sólo eso, sino que además me permitiría escribir un archivo .h y otro .cpp para utilizarlos con la llamada include para futuros programas que realices, sin tener que reescribir cada vez todo el código. Así que a ratitos he ido modificando el código, que podéis ver en el enlace antes mentado, para que haga lo que yo quiero.
He de aclarar que el código que he hecho no está basado en librerías GTK, QT o similares. El programa cuando lo ejecuto se ejecuta, valga la redundancia, en una terminal. Aunque para mi parecer ésta es la forma más cómoda y eficaz de aprender C/C++, los GUIS siempre me resultan pesados y enrevesados.
Bueno sin más escribo aquí el código en cuestión, el código se compone de tres ficheros, el primero le he llamado gnuplot.h y contiene la declaración de la clase GNUplot, sus funciones y variables miembro:
#ifndef GNUPLOT_H_
#define GNUPLOT_H_
#include <iostream>
using namespace std;
class GNUplot
{
public:
GNUplot() throw(string);
~GNUplot();
void operator ()(const string& command);
protected:
FILE *gnuplotpipe;
};
#endif /*GNUPLOT_H_*/
Después tengo el fichero gnuplot.cpp que consta del código que tienen cada una de las funciones miembro de la clase GNUplot y que se han declarado anteriormente en gnuplot.h
#include <iostream>
#include <string>
#include "gnuplot.h"
using namespace std;
GNUplot::GNUplot() throw(string)
{
gnuplotpipe=popen("gnuplot -persist","w");
if (!gnuplotpipe) {
throw("¡ No se encontro GNUPLOT!");
}
}
GNUplot::~GNUplot()
{
fprintf(gnuplotpipe,"exit\n");
pclose(gnuplotpipe);
}
void GNUplot::operator() (const string& command)
{
fprintf(gnuplotpipe,"%s\n",command.c_str());
fflush(gnuplotpipe);
// fflush es necesario para poder dibujar
}
Quiero hacer hincapié en algo muy importante en este fichero, y es que en estos ficheros en los que el código lo único que hace es especificar las instrucciones de nuestra clase (antes declarada con un .h) nunca declaréis la función main(), y mucho menos si lo queréis utilizar en otros futuros programas. Para eso ya tenéis la oportunidad de crearos otro fichero .cpp que contenga la declaración de main(), como es el caso del fichero que he llamado dibujar.cpp y que de código es:
#include <iostream>
#include <string>
#include "gnuplot.h"
using namespace std;
int main(int argc, char** argv)
{
GNUplot plotter;
string comando;
cout<<"Introduce la orden gnuplot a ejecutar:"<<endl;
getline(cin,comando);
plotter(comando);
return 0;
}
Bueno como veis en dibujar.cpp declaramos un include hacia la librería gnuplot.h que hemos creado por nuestra cuenta. Además éste es el cuerpo de nuestro fichero principal de nuestro programa, en el cual ya declaramos la función principal main() y lo mque queremos que se realice en nuestro programa. En este programa lo que se hará es que por terminal introduciremos una orden o conjunto de órdenes de gnuplot y el programa al llegar a la instrucción plotter(comando) nos abrirá gnuplot, realizará lo que le hemos mandado y si lo que le hemos mandado posee algún error de sintaxis el programa nos informará de ello.
Con éste simple código y un poco más allá podríamos crear nuestro gnuplotgtk.
Bueno para que vaya el programa deberéis tener instalado gnuplot en vuestro S.O., los de Ubuntu y derivados lo encontraréis en Synaptic.
Para compilar el programa y ejecutarlo lo podéis hacer por terminal escribiendo:
g++ gnuplot.cpp dibujar.cpp -o dibujar
./dibujar
También lo podéis escribir, compilar y ejecutar fácilmente con EasyEclipse para C/C++ Por ejemplo si al ejecutarlo escribimos el siguiente conjunto de órdenes:
set xrange [-2:2]; set yrange [-2:2]; set pm3d; splot exp(-x*x)*exp(-y*y); set term postscript eps enhanced color; set output ‘/home/crislosi/color.eps’; replot
Obtendremos la siguiente gráfica, además nos guardará la gráfica en formato Postscript (.eps) en /home/crislosi con nombre color.eps, así la podremos añadir fácilmente con Lyx a nuestros documentos escritos con Latex.
Para escribir un conjunto de órdenes basta escribirlas en una misma línea separadas por punto y coma y un espacio.
A ver si saco tiempo y hago un gnuplotgtk
Saludos
Enlace-> Tutorial de Gnuplot
Comentarios