import java.awt.event.WindowEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JFrame; import java.awt.Graphics; import java.awt.Color; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.Font; import java.awt.Point; import java.awt.Label; import java.util.LinkedList; import java.util.StringTokenizer; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.FileInputStream; import java.io.IOException; // ====================================================================== // Objetivo: Graficar un conjunto de pares de valores x,y // Autor: J. Rafael R. Ochoa // Fecha: 2003, // Derechos: SID - FIE - UMSNH // // ----------------------------------------------------------------------------------------------------------------------- // NOTAS: // // 1.- Hay que ejecutarlo de la siguiente manera: // Prompt> java xy_plot ARCHIVO // 2.- El contenido de ARCHIVO debe ser solamente los pares x,y separados por una coma y un par bajo el otro. // 3.- Hay que calcular cuando es cero. AquI se considera que existe exActamente el valor de cero (mEtodo ObtenCero) // El primer cruce por cero, se puede obtener en el primer cambio de signo. Usando esas 2 coordenadas, se // puede usar la ecuaciOn de la intersecciOn -SE PUEDE OCUPAR- // // V E R S I O N 1 . 0 // ----------------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------- // MEJORAS: // Julio 1 del 2004. Se centra la ventana en la pantalla y se dispone de varios colores. // Julio 6 del 2004 Le quitE la rayita extra y se atiende al evento del ratOn con el click izquierdo // dando el valor de la funciOn para ese valor de X. // ----------------------------------------------------------------------------------------------------------------------- public class xy_plot extends JFrame { // DeclaraciOn de las variables que controlan al sistema //________________________________________________________ LinkedList ListaReal; // Lista de valores de los datos reales. int Vector_X_Pixel[], Vector_Y_Pixel[]; // Vector de valores interpretados como enteros. // Valores extremos convenientes para recibir los nuevos valores double VXmax = -10000, VXmin = 10000, VYmax = -10000, VYmin = 10000, CX0 = 0.0, X_CERO, Y_CERO; Graphics AG = null; // Objeto grAfico -Area para graficar- int CDM_X = 20; // Constante Del Margen -CDM- en x int CDM_Y = 40; // Constante Del Margen -CDM- en y int posX=0, posY=0; // Posiciones de los ejes. int ANCHO = 600, ALTO = 500; // Dimensiones del Area grAfica String ARCHIVO = ""; // Nombre del archivo a leer Point Pos_XY_Mouse; // PosiciOn del ratOn en la curva al dar click izquierdo public xy_plot(String ARCHIVO) throws IOException { this.ARCHIVO = ARCHIVO; getContentPane().setLayout(null); // Contenedor nulo setTitle(" { " + ARCHIVO + " } "); // TItulo de la ventana setResizable(true); // No es redimensionable Dimension DimMonitor = Toolkit.getDefaultToolkit().getScreenSize(); // Dimensiones del monitor setLocation((DimMonitor.width - ANCHO) / 2, (DimMonitor.height - ALTO) / 2); // PosiciOn centrada setSize(new Dimension(ANCHO, ALTO)); // Dimensiones addMouseListener(new EventoRaton()); // Escuchador de eventos del ratOn show(); // Mostrar la ventana } // SOlo se captura el evento de cierre de la ventana protected void processWindowEvent(WindowEvent e) { if (e.getID() == WindowEvent.WINDOW_CLOSING) System.exit(0); } public static void main(String S[]) throws IOException { if (S.length != 1) { System.out.println("Error en el nUmero de parAmetros...\n[Uso: java xy_plot Archivo_De_Datos]"); System.exit(0); } new xy_plot(S[0]); } void Inicia(String ARCHIVO) throws IOException { Lee_Datos(ARCHIVO); CalcularRelacion(); } public void paint(Graphics G) { G.setColor(Color.black); G.fillRect(0,0,this.getWidth(), this.getHeight()); // Limpiar el Area AG = G.create(); // Copia del Area grAfica try { Inicia(ARCHIVO); } catch(IOException e){} } // Obtiene los datos del archivo que entrO como argumento y los guarda en una lista ligada void Lee_Datos(String archivo) throws IOException { Object OBJETO; String Linea; ListaReal = new LinkedList(); BufferedReader ARCHIVO = new BufferedReader(new InputStreamReader(new FileInputStream(archivo))); while((Linea = ARCHIVO.readLine()) != null ) ListaReal.add(Crea_Objeto(Linea)); ARCHIVO.close(); } // Cada una de las lIneas leIdas en el mEtodo "Lee_Dato" se convierten a un elemento de la clase "NODO" // Se regresa un Objeto para poder ser aNadido a la lista ligada. Object Crea_Objeto(String Linea) { String VMAX_STR = "", VMIN_STR = ""; StringTokenizer ST = new StringTokenizer(Linea, ","); if (ST.countTokens() != 2) { System.out.println("Error en el archivo de datos..."); System.exit(0); } double X = Double.parseDouble(ST.nextToken()); double Y = Double.parseDouble(ST.nextToken()); ObtenValorMinimo(X, Y); ObtenValorMaximo(X, Y); ObtenCero(X, Y); return (Object)new NODO(X, Y); // ConversOn a Objeto } void ObtenValorMinimo(double X, double Y) { VXmin = Math.min(VXmin, X); VYmin = Math.min(VYmin, Y); } void ObtenValorMaximo(double X, double Y) { VXmax = Math.max(VXmax, X); VYmax = Math.max(VYmax, Y); } // Hay que calcular cuando es cero. AquI se considera que existe exActamente el valor de cero void ObtenCero(double X, double Y) { X_CERO = (X == 0) ? X : VXmin; Y_CERO = (Y == 0) ? Y : VYmin; } // Realiza la conversiOn de valores reales a valores de pixel // guardAndose estos en un vector de enteros //______________________________________________________________ void ConvierteListaAVectorDeEnteros(double Escala_X, double Escala_Y) { Vector_X_Pixel = new int[ListaReal.size()]; Vector_Y_Pixel = new int[ListaReal.size()]; NODO Nodo = null; double Dato = 0; // CAlculo en pixeles de X // Si es (-) = posY - LO QUE DE + CDM_X // Si es (+) = posY + LO QUE DE + CDM_X // Si es (0) = posY + CDM_X // CAlculo en pixeles de Y // Si es (-) = posX + LO QUE DE + CDM_Y // Si es (+) = posX - LO QUE DE + CDM_Y // Si es (0) = posX + CDM_Y for (int k = 0; k < ListaReal.size(); k++) { Nodo = (NODO)ListaReal.get(k); Dato = Nodo.X; // ObtenciOn del valor leIdo (valor de X) //if (Dato >= Double.POSITIVE_INFINITY) Dato = 0; Vector_X_Pixel[k] = (int)(Math.abs(Dato) * Escala_X); if (Dato < 0) Vector_X_Pixel[k] = posY - Vector_X_Pixel[k]; // Es hacia la izquierda if (Dato > 0) Vector_X_Pixel[k] = posY + Vector_X_Pixel[k]; // Es hacia la derecha if (Dato == 0) Vector_X_Pixel[k] = posY; Dato = Nodo.Y; // ObtenciOn del valor leIdo (valor de Y) //if (Dato >= Double.POSITIVE_INFINITY) Dato = 0; Vector_Y_Pixel[k] = (int)(Math.abs(Dato) * Escala_Y); if (Dato > 0) Vector_Y_Pixel[k] = posX - Vector_Y_Pixel[k]; if (Dato < 0) Vector_Y_Pixel[k] = posX + Vector_Y_Pixel[k]; if (Dato == 0) Vector_Y_Pixel[k] = posX; } AG.setColor(Color.yellow); // Color de la curva AG.drawPolyline(Vector_X_Pixel, Vector_Y_Pixel, Vector_X_Pixel.length); // SE GRAFICA LA FUNCION AG.setColor(Color.orange); // Color del borde AG.draw3DRect(CDM_X, CDM_Y, ANCHO-CDM_X*2, ALTO-CDM_Y*2, true); // Se coloca un borde } // CAlculos de la informaciOn base void CalcularRelacion() { // CALCULO DE LA RELACION REAL-PIXEL int LongXVentana = ANCHO-2*CDM_X, LongYVentana = ALTO-2*CDM_Y; // CAlculo del espacio disponible en X y en Y double LongY_Real = VYmax - VYmin; // CAlculo de la longitud real -Y- double LongX_Real = VXmax - VXmin; // CAlculo de la longitud real -X- double Escala_Y = LongYVentana / LongY_Real; // RelaciOn por pixel en Y double Escala_X = LongXVentana / LongX_Real; // RelaciOn por pixel en X // Trazado del sistema cartesiano TrazaEjes(LongX_Real, LongY_Real,LongXVentana, LongYVentana, Escala_X, Escala_Y); ConvierteListaAVectorDeEnteros(Escala_X, Escala_Y); } void TrazaEjes(double LongX_Real, double LongY_Real, int XVentana, int YVentana, double Escala_X, double Escala_Y) { // CAlculo de la posiciOn del eje X posX=0; posY=0; if (VYmax >= 0 && VYmin >= 0) posX = YVentana+CDM_Y; // ambos y's positivos if (VYmax <= 0 && VYmin <= 0) posX = CDM_Y; // ambos y's negativos if (posX == 0) posX = (int)(VYmax * Escala_Y) + CDM_Y; // CAlculo de los porcentajes en la posiciOn // CAlculo de la posiciOn del eje Y if (VXmax >= 0 && VXmin >= 0) posY = CDM_X; // ambos x's positivos if (VXmax <= 0 && VXmin <= 0) posY = XVentana+CDM_X; // ambos x's negativos if (posY == 0) posY = (int)(VXmax * Escala_X) + CDM_X; // CAlculo de los porcentajes en la posiciOn AG.setColor(Color.white); // Color de los ejes AG.drawLine(CDM_X, posX, ANCHO-CDM_X, posX); // Trazo del eje X AG.drawLine(posY, CDM_Y, posY, ALTO-CDM_Y); // Trazo del eje Y Font TipoDeLetra = new Font("Serif", Font.PLAIN, 10); // Tipo de letra AG.setFont(TipoDeLetra); // Fijar tipo de letra // Se muestran los valores extremos de los ejes con un mAximo de 5 caracteres AG.setColor(Color.yellow); AG.drawString((""+VXmin).substring(0, ((""+VXmin).length() < 5?(""+VXmin).length()-1:5)), CDM_X+5, posX); AG.drawString((""+VXmax).substring(0, ((""+VXmax).length() < 5?(""+VXmax).length()-1:5)), XVentana-CDM_X, posX); AG.drawString((""+VYmax).substring(0, ((""+VYmax).length() < 5?(""+VYmax).length()-1:5)), posY+5, CDM_Y+10); AG.drawString((""+VYmin).substring(0, ((""+VYmin).length() < 5?(""+VYmin).length()-1:5)), posY+5, YVentana+CDM_Y); } // AtenciOn al evento del ratOn class EventoRaton implements MouseListener { public void mouseEntered(MouseEvent e) {} // no me interesa public void mouseExited(MouseEvent e) {} // no me interesa public void mousePressed(MouseEvent e) {} // no me interesa public void mouseReleased(MouseEvent e) {} // no me interesa public void mouseClicked(MouseEvent e) { int Indice = -1; if (MouseEvent.BUTTON1 == e.getButton()) // click en botOn izquierdo { Pos_XY_Mouse = new Point(e.getPoint()); // Se obtiene la posiciOn del ratOn. Indice = Busca(Pos_XY_Mouse.x); // Se bUsca el Indice correspondiente a ese valor X AG.setColor(Color.black); // Color del fondo AG.fillRect(10, 465, 400, 30); // Limpiar el Area AG.setColor(Color.yellow); // Color de la fuente AG.drawString("X= " + ((NODO)ListaReal.get(Indice)).X, 100, 475); AG.drawString("Y= " + ((NODO)ListaReal.get(Indice)).Y, 100, 490); } } } // Se busca el Indice mAs sercano al valor X // ya que podrIa no existir el valor exacto de cero int Busca(int X) { int Indice = 0; // valor conveniente para obtener el mAs pequeNo int diferencia = Math.abs(X - Vector_X_Pixel[0]); // Diferencia mAs pequeNa for (int k = 0; k < Vector_X_Pixel.length; k++) { Indice = (Math.abs(Vector_X_Pixel[k] - X) < diferencia ? k:Indice); diferencia = (Math.abs(Vector_X_Pixel[k] - X) < diferencia ? Math.abs(Vector_X_Pixel[k] - X):diferencia); } return Indice; } } // Elementos class NODO { double X, Y; public NODO(double X, double Y) { this.X = X; this.Y = Y; } }