//======================================================
// Numerical Analysis package in java
// Polynomial Least Square Curve Fitting
// University of Nebraska - Lincoln
// N106 WSEC phone : 402-472 3973
// Dr. Turhan Coban
// =====================================================
/*
 * Java 2 Swing version.
 */

import java.lang.Integer;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import javax.swing.*;
import javax.swing.border.*;
import Numeric;
import Text;
import java.util.*;
import java.io.*;
import Plot2D;
import PlotShapesSW;
import java.security.*;

public class leastE extends JFrame implements ItemListener,ActionListener
{

    boolean inAnApplet = true;
    final static String girdi        = "DATA input page";
    final static String leastcikti   = "least square output page";
    final static String KONTROLPanel = "PLOT  control page";
    final static String PLOTPanel = "Plot page";
    Plot2D jta;
    StringTokenizer t;
//  least variable set seti ********
    double             ee[];
    double             xi[];
    double             yi[];
    BufferedReader     fin;
    File girdiDosyasi;
    File ciktiDosyasi;
    File plotDosyasi;
    int nGirdi;
    int nCikti;
    double minX,maxX;
    int PolinomDerecesi;

//  ****** input page *******
    JLabel     promptGirdi;
    JTextField  inputGirdi;
    JLabel     promptPD;
    JTextField  inputPD;
    JTextArea  outputGirdi;

//  ****** output page *******
    JLabel     promptCikti;
    JTextField  inputCikti;
    JTextArea  outputCikti;
    JTextArea outputFormul;
    JLabel promptP1_1,promptP1_2,promptP1_3,promptP1_4;
    JTextField inputP1_1,inputP1_2,inputP1_3,inputP1_4;

//  ****** plot control page ****
    JLabel      promptXmin;      // Label prompt in Xmin field
    JLabel      promptXmax;      // Label prompt in Xmax field
    JLabel      promptYmin;      // Label prompt in Ymin field
    JLabel      promptYmax;      // Label prompt in Ymax field
    JLabel     promptLabel;      // Label prompt Plot Label;
    JLabel    promptXLabel;      // Label prompt Plot XLabel;
    JLabel    promptYLabel;      // Label prompt Plot YLabel;
    JLabel     promptXntic;      // Label prompt in Xmin field
    JLabel     promptYntic;      // Label prompt in Xmax field
    JLabel   promptXgridon;      // Label prompt in Ymin field
    JLabel   promptYgridon;      // Label prompt in Ymax field
    JTextField   inputXmin;      // input field Xmin
    JTextField   inputXmax;      // input field Xmax
    JTextField   inputYmin;      // input field Ymin
    JTextField   inputYmax;      // input field Ymax
    JTextField  inputLabel;      // input field Label
    JTextField inputXLabel;      // input field XLabel
    JTextField inputYLabel;      // input field YLabel
    JTextField  inputXntic;      // input field xntic
    JTextField  inputYntic;      // input field yntic
    JCheckBox inputXgridon;      // input field xgridon
    JCheckBox inputYgridon;      // input field ygridon
    JButton    printButton;

    //===========================================================

    public leastE(String s) throws IOException
    {
    super(s);
    Border b=BorderFactory.createRaisedBevelBorder();
    girdiDosyasi=new File("c://temp//in.txt");
    girdiDosyasi=new File(girdiDosyasi.getAbsolutePath());
    ciktiDosyasi=new File("c://temp//out.txt");
    ciktiDosyasi=new File(ciktiDosyasi.getAbsolutePath());
    plotDosyasi=new File("c://temp//Plot.txt");
    plotDosyasi=new File(plotDosyasi.getAbsolutePath());
    oku();
    nGirdi=xi.length;
    nCikti=nGirdi;
    minX=xi[0];
    maxX=xi[nGirdi-1];
    ee=new double[nGirdi];
    PolinomDerecesi=4;
    ee=Numeric.poly_least_square(xi,yi,PolinomDerecesi);
    Container contentPane = getContentPane();
    JTabbedPane tabbedPane = new JTabbedPane();
        JPanel pane1 = new JPanel();
        JPanel pane2 = new JPanel();
        pane2.setLayout(new BorderLayout());
        JPanel pane3=new JPanel();
        JPanel pane4=new JPanel();
        JPanel mpane=new JPanel();
        mpane.setLayout(new GridLayout(1,8));
        JPanel xpane=new JPanel();
        xpane.setLayout(new GridLayout(1,8));
        JPanel lpane=new JPanel();
        lpane.setLayout(new GridLayout(3,2));
        JPanel PanelCikti1=new JPanel();
        PanelCikti1.setLayout(new GridLayout(4,2));
        JPanel PanelCikti2=new JPanel();
        PanelCikti2.setLayout(new BorderLayout());
        //JScrollPane.VERTICAL_SCROLLBAR_ALWAYS;
        JPanel PanelGirdi1=new JPanel();
        PanelGirdi1.setLayout(new GridLayout(2,2));
        //***************
        promptGirdi=new JLabel("input file name");
        inputGirdi=new JTextField("c:\\temp\\in.txt");
        promptPD=new JLabel("degree of polynomial");
        inputPD=new JTextField(""+PolinomDerecesi);
        outputGirdi=new JTextArea(yazxiyi(),20,40);
        outputGirdi.setLineWrap(true);
        outputGirdi.setBorder(b);
        promptCikti=new JLabel("output file name");
        inputCikti=new JTextField("c:\\temp\\out.txt");
        promptP1_2=new JLabel("number of output data points");
        promptP1_3=new JLabel("output file Minimum x : ");
        promptP1_4=new JLabel("output file Maximum x : ");
        inputP1_2=new JTextField(""+nCikti);
        inputP1_3=new JTextField(""+minX);
        inputP1_4=new JTextField(""+maxX);
        outputCikti=new JTextArea(yazCikti(),20,40);
        outputCikti.setBorder(b);
        outputFormul=new JTextArea(yaze(),10,40);
        outputFormul.setLineWrap(true);
        outputFormul.setAutoscrolls(true);
        outputFormul.setBorder(b);
        PanelCikti1.add(promptCikti);
        PanelCikti1.add(inputCikti);
        PanelCikti1.add(promptP1_2);
        PanelCikti1.add(inputP1_2);
        PanelCikti1.add(promptP1_3);
        PanelCikti1.add(inputP1_3);
        PanelCikti1.add(promptP1_4);
        PanelCikti1.add(inputP1_4);
        PanelCikti2.add(PanelCikti1,BorderLayout.NORTH);
        PanelCikti2.add(new JScrollPane(outputFormul),BorderLayout.CENTER);
        PanelCikti2.add(new JScrollPane(outputCikti),BorderLayout.SOUTH);
        PanelGirdi1.add(promptGirdi);
        PanelGirdi1.add(inputGirdi);
        PanelGirdi1.add(promptPD);
        PanelGirdi1.add(inputPD);
        pane3.add(PanelGirdi1);
        pane3.add(new JScrollPane(outputGirdi));
        pane4.add(PanelCikti2);

        //***************
        promptXmin = new JLabel("Xmin ");
        inputXmin  = new JTextField(5);
        promptXmax = new JLabel("Xmax ");
        inputXmax  = new JTextField(5);
        promptYmin = new JLabel("Ymin ");
        inputYmin  = new JTextField(5);
        promptYmax = new JLabel("Ymax ");
        inputYmax  = new JTextField(5);
        //*******
        promptLabel  = new  JLabel("Plot heading   : ");
        promptXLabel = new  JLabel("x axis heading : ");
        promptYLabel = new  JLabel("y axis heading : ");
        inputLabel   = new JTextField(30);
        inputXLabel  = new JTextField(30);
        inputYLabel  = new JTextField(30);
        //*******
        promptXntic=new JLabel("X tic no");
        inputXntic=new JTextField(5);
        promptYntic=new  JLabel("Y tic no");
        inputYntic=new JTextField(5);
        promptXgridon=new JLabel("X grid");
        inputXgridon=new JCheckBox(" ");
        promptYgridon=new JLabel("Y grid");
        inputYgridon=new JCheckBox(" ");
        //*******
        mpane.add(promptXmin);
        mpane.add(inputXmin);
        mpane.add(promptXmax);
        mpane.add(inputXmax);
        mpane.add(promptYmin);
        mpane.add(inputYmin);
        mpane.add(promptYmax);
        mpane.add(inputYmax);
        pane1.add(mpane,BorderLayout.NORTH);
        xpane.add(promptXntic);
        xpane.add(inputXntic);
        xpane.add(promptYntic);
        xpane.add(inputYntic);
        xpane.add(promptXgridon);
        xpane.add(inputXgridon);
        xpane.add(promptYgridon);
        xpane.add(inputYgridon);
        pane1.add(xpane,BorderLayout.NORTH);
        //********
        lpane.add(promptLabel);
        lpane.add(inputLabel);
        lpane.add(promptXLabel);
        lpane.add(inputXLabel);
        lpane.add(promptYLabel);
        lpane.add(inputYLabel);
        pane1.add(lpane,BorderLayout.SOUTH);
        //*********
        jta=new Plot2D();
        inputXmin.setText(Double.toString(jta.p1.xmin));
        inputXmax.setText(Double.toString(jta.p1.xmax));
        inputYmin.setText(Double.toString(jta.p1.ymin));
        inputYmax.setText(Double.toString(jta.p1.ymax));
        inputXntic.setText(Integer.toString(jta.p1.xntic));
        inputYntic.setText(Integer.toString(jta.p1.yntic));
        inputLabel.setText(jta.p1.label);
        inputXLabel.setText(jta.p1.xlabel);
        inputYLabel.setText(jta.p1.ylabel);
        printButton=new JButton("print");
        pane2.add(jta);
        pane1.add(printButton,BorderLayout.SOUTH);
        tabbedPane.addTab(girdi,         pane3);
        tabbedPane.addTab(leastcikti,    pane4);
        tabbedPane.addTab(PLOTPanel,     pane2);
        tabbedPane.addTab(KONTROLPanel,  pane1);
        contentPane.add(  tabbedPane, BorderLayout.CENTER);
        printButton.addActionListener(this);
        inputXmin.addActionListener(this);
        inputXmax.addActionListener(this);
        inputYmin.addActionListener(this);
        inputYmax.addActionListener(this);
        inputLabel.addActionListener(this);
        inputXLabel.addActionListener(this);
        inputYLabel.addActionListener(this);
        inputXntic.addActionListener(this);
        inputYntic.addActionListener(this);
        inputXgridon.addItemListener(this);
        inputYgridon.addItemListener(this);
        //en küçük kareler metodu action listener bağlantısı
        inputP1_2.addActionListener(this);  // nCikti
        inputP1_3.addActionListener(this);  // minX
        inputP1_4.addActionListener(this);  // maxX
        inputGirdi.addActionListener(this); // Girdi dosyasi
        inputCikti.addActionListener(this); // Cikti dosyasi
        inputPD.addActionListener(this);    // PolinomDerecesi
        leastCiktisiniPlotGirdisiOlarakYazdir();
    }


    //===========================================================


    public void itemStateChanged(ItemEvent e)
    {
    inputXmin.setText(Double.toString(jta.p1.xmin));
    inputXmax.setText(Double.toString(jta.p1.xmax));
    inputYmin.setText(Double.toString(jta.p1.ymin));
    inputYmax.setText(Double.toString(jta.p1.ymax));
    inputXntic.setText(Integer.toString(jta.p1.xntic));
    inputYntic.setText(Integer.toString(jta.p1.yntic));
    Object source=e.getItemSelectable();
    if(source==inputXgridon)
    {
     if (e.getStateChange() == ItemEvent.DESELECTED)
     {
     jta.p1.xgridon=0;
     }
     else
     {
      jta.p1.xgridon=1;
     }
    }
    else if(source==inputYgridon)
    {
     if (e.getStateChange() == ItemEvent.DESELECTED)
     {
     jta.p1.ygridon=0;
     }
     else
     {
      jta.p1.ygridon=1;
     }
    }
    inputLabel.setText(jta.p1.label);
    inputXLabel.setText(jta.p1.xlabel);
    inputYLabel.setText(jta.p1.ylabel);
    jta.yenidenciz();
    }

    //===========================================================

    public void leastCiktisiniPlotGirdisiOlarakYazdir()
    {
      try
      {
      BufferedWriter fplot=new BufferedWriter(new FileWriter(plotDosyasi));
      fplot.write(inputLabel.getText()+" \n");
      fplot.write(inputXLabel.getText()+" \n");
      fplot.write(inputYLabel.getText()+" \n");
      fplot.write("2 \n");
      fplot.write(inputGirdi.getText()+" 20 0 0 0  \n");
      fplot.write(inputCikti.getText()+" 3  0 0 255 ");
      fplot.close();
      }
      catch(IOException e1)
      {
       System.err.println("input - output error :  c:\temp\\Plot.txt");
      }
      catch(AccessControlException ace)
      {
       System.err.println("write least output as plot input error  : "+ plotDosyasi);
      }
    }

    public void sayfalariyenile()
    {
      girdiDosyasi=new File(inputGirdi.getText());
      Integer d1=new Integer(inputPD.getText());
      PolinomDerecesi=d1.intValue();
      ciktiDosyasi=new File(inputCikti.getText());
      Integer d2=new Integer(inputP1_2.getText());
      nCikti=d2.intValue();
      Double d3=new Double(inputP1_3.getText());
      minX=d3.doubleValue();
      Double d4=new Double(inputP1_4.getText());
      maxX=d4.doubleValue();
      try{
      oku();
         }
      catch(IOException e1)
      {
       System.err.println("least input file error : "+ girdiDosyasi);
      }
      catch(AccessControlException ace)
      {
       System.err.println("least input file access control error: "+ girdiDosyasi);
      }

      ee=new double[PolinomDerecesi+1];
      ee=Numeric.poly_least_square(xi,yi,PolinomDerecesi);
      outputGirdi.setText(yazxiyi());
      outputCikti.setText(yazCikti());
      outputFormul.setText(yaze());
      jta.yenidanPlotDatasiOku();
      leastCiktisiniPlotGirdisiOlarakYazdir();
    }

    //===========================================================

    public void actionPerformed(ActionEvent e)
    {
    if(  e.getSource()==inputGirdi ||
         e.getSource()==inputPD    ||
         e.getSource()==inputCikti ||
         e.getSource()==inputP1_2  ||
         e.getSource()==inputP1_3  ||
         e.getSource()==inputP1_4    )
    {
         sayfalariyenile();
    }

    //grafiği yazıcıya gönderir
    //********************
    if (e.getSource()==printButton )
    {
    jta.yazdir();
    }
    //grafik min max değerlerini yeniden okur
    Double valXmin=new Double(inputXmin.getText());
    jta.p1.xmin=valXmin.doubleValue();
    Double valXmax=new Double(inputXmax.getText());
    jta.p1.xmax=valXmax.doubleValue();
    Double valYmin=new Double(inputYmin.getText());
    jta.p1.ymin=valYmin.doubleValue();
    Double valYmax=new Double(inputYmax.getText());
    //*****
    //grafik tic sayısını yeniden okur
    Integer valXntic=new Integer(inputXntic.getText());
    jta.p1.xntic=valXntic.intValue();
    Integer valYntic=new Integer(inputYntic.getText());
    jta.p1.yntic=valYntic.intValue();
    //*****
    //grafik başlıklarını yeniden okur
    jta.p1.ymax=valYmax.doubleValue();
    jta.p1.label=inputLabel.getText();
    jta.p1.xlabel=inputXLabel.getText();
    jta.p1.ylabel=inputYLabel.getText();
    //Plot'ı (grafik) yeniden çizer
    jta.yenidenciz();
    }


    public void oku() throws IOException
    {
      try{
      fin=new BufferedReader(new FileReader(girdiDosyasi));
         }
         catch(FileNotFoundException e2)
         {
          System.err.println(e2.toString());
         }

    nGirdi=0;
    Vector v1,v2;
    v1=new Vector(1);
    v2=new Vector(1);
    String X1,X2;
    boolean EOF=false;
      while(!EOF)
      {
      try{
      X1=Text.readString(fin);
      X2=Text.readString(fin);
      v1.addElement(X1);
      v2.addElement(X2);
      nGirdi++;
         }catch(EOFException e)
          {
          fin.close();
          EOF=true;
          }
      }
      xi=new double[nGirdi];
      yi=new double[nGirdi];
      Enumeration enum1=v1.elements();
      Enumeration enum2=v2.elements();
      StringBuffer b=new StringBuffer();
      //for(int i=0;i<n;i++)
      int i=0;
      while(enum1.hasMoreElements())
      {
      X1=(String)enum1.nextElement();
      Double d1=new Double(X1);
      X2=(String)enum2.nextElement();
      Double d2=new Double(X2);
      xi[i]=d1.doubleValue();
      yi[i]=d2.doubleValue();
      i++;
      }
    }

    public String yazxiyi()
    {
    String b=new String();
    for(int i=0;i<xi.length;i++)
    {
    b=b+" "+xi[i]+"\t "+yi[i]+"\n";
    }
    return b;
    }

    public String yaze()
    {
    String b="Coefficients of polynomial : ";
    b=b+"f(x) = a[0]+a[1]*x+a[2]*x^2+....a[n]*x^n \n";
    for(int i=0;i<=PolinomDerecesi;i++)
    {
    b=b+"a["+i+"] = "+ee[i]+"\n";
    }
    return b;
    }

    public String yazCikti()
    {
      String b=new String();
      try{
      ObjectOutputStream fout=new ObjectOutputStream(new FileOutputStream(ciktiDosyasi));
      double x,y;
      double nn=((maxX-minX)/(nCikti-1));
          for(int i=0;i<nCikti;i++)
          {
          x=minX+nn*i;
          y=Numeric.f_least_square(ee,x);
          b=b+" "+x+"\t "+y+"\n";
          }
          fout.writeObject(b);
          try{
          fout.close();
             }
             catch(IOException io)
             {
             System.exit(1);
             }

      }
      catch(IOException e1)
      {
       System.err.println("input output error");

      }
      catch(AccessControlException ece)
      {
        System.err.println("output file writing error"+ciktiDosyasi+ " excess kontrol");
      }
      return b;
      }

    //===========================================================

    public static void main( String argv[] ) throws IOException {
        leastE frame = new leastE( "Polynomial least square curve fitting" );
        frame.addWindowListener(new BasicWindowMonitor());
        frame.setSize( 600, 600 );
	    frame.setVisible(true);
    }
}
