/*
 * NewJApplet.java
 *
 * Created on 13. April 2008, 11:25
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import java.text.*;
import java.awt.Graphics2D;
import java.awt.geom.*;

/**
 *
 * @author  poj
 */
public class NewJApplet extends javax.swing.JApplet {

    int nmax = 50;
    double deltat = 1.0 / nmax;
    double[] y, fcy, fsy;   // function values and Fourier coefficients
    double cs, ss; // cosine-sum and sine-sum
    int i, j, k, l;
    double xi, s1, s2, s3, s4;
    double[][] data1, data2, data3;
    
    int selector=0;
    int scale=10;

    /** Initializes the applet NewJApplet */
    public void init() {
        try {
            java.awt.EventQueue.invokeAndWait(new Runnable() {

                public void run() {
                    initComponents();
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        y = new double[nmax];
        fcy = new double[nmax];
        fsy = new double[nmax];
        data1 = new double[nmax][3];
        data2 = new double[nmax * 10][3];
        data3 = new double[nmax * 10][3];

        jSlider1.setValue(scale);
        do_the_calculation();
    }

    /** This method is called from within the init() method to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new myPanel1();
        jPanel2 = new myPanel2();
        jPanel3 = new myPanel3();
        jPanel4 = new myPanel4();
        jComboBox1 = new javax.swing.JComboBox();
        jCheckBox1 = new javax.swing.JCheckBox();
        jSlider1 = new javax.swing.JSlider();
        jLabel1 = new javax.swing.JLabel();

        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 318, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 231, Short.MAX_VALUE)
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 318, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 231, Short.MAX_VALUE)
        );

        jPanel3.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 318, Short.MAX_VALUE)
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 231, Short.MAX_VALUE)
        );

        jPanel4.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 318, Short.MAX_VALUE)
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 231, Short.MAX_VALUE)
        );

        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "sym rectangle", "asym rectangle", "triangle", "sine", "delta", "linear" }));
        jComboBox1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBox1ActionPerformed(evt);
            }
        });

        jCheckBox1.setText("balance");
        jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckBox1ActionPerformed(evt);
            }
        });

        jSlider1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jSlider1MouseDragged(evt);
            }
        });

        jLabel1.setText("scale");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addGap(22, 22, 22)
                                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(layout.createSequentialGroup()
                                .addContainerGap()
                                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addGap(29, 29, 29)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(35, 35, 35)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jCheckBox1)
                                    .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(69, 69, 69)
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(13, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(33, 33, 33)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(55, 55, 55)
                        .addComponent(jCheckBox1))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(33, 33, 33)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addGap(15, 15, 15)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1)
                    .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(234, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox1ActionPerformed
      selector=jComboBox1.getSelectedIndex(); 
      do_the_calculation();// TODO add your handling code here:
    }//GEN-LAST:event_jComboBox1ActionPerformed

    private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed
     do_the_calculation();   // TODO add your handling code here:
    }//GEN-LAST:event_jCheckBox1ActionPerformed

    private void jSlider1MouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider1MouseDragged
      scale=jSlider1.getValue();
      jPanel2.repaint();// TODO add your handling code here:
    }//GEN-LAST:event_jSlider1MouseDragged

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JCheckBox jCheckBox1;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JSlider jSlider1;
    // End of variables declaration//GEN-END:variables
    void trigi(double[] y, double xi) {



        // this is the straight forward method
        // we need it for the trigonometric interpolation



        int i;
        double ca, sa;
        cs = 0.0;
        ss = 0.0;

        for (i = 0; i < nmax / 2; i++) {
            ca = Math.cos((double) (i * xi));
            cs += y[i] * ca;
        }

        for (i = 1; i < nmax / 2; i++) {
            sa = Math.sin((double) (i * xi));
            ss += y[i] * sa;
        }


        // higher frequencies are folded
        // into the first "Brillouin Zone"

        for (i = nmax / 2; i < nmax; i++) {
            ca = Math.cos((double) ((i - nmax) * xi));
            cs += y[i] * ca;
        }

        for (i = nmax / 2; i < nmax; i++) {
            sa = Math.sin((double) ((i - nmax) * xi));
            ss += y[i] * sa;
        }




    }

    void goertzel(double[] y, double xi) {
        double[] u;
        u = new double[nmax + 2];  // working array
        int i;

        double c, cc;

        u[nmax] = 0.0;
        u[nmax + 1] = 0.0;
        c = Math.cos(xi);
        cc = c * 2.0;
        for (i = nmax - 1; i >= 1; i--) {
            u[i] = y[i] + cc * u[i + 1] - u[i + 2];
        }
        cs = y[0] + u[1] * c - u[2];
        ss = u[1] * Math.sin(xi);
    }

// cs = sum (y(n) * cos(n*xi))
// ss = sum (y(n) * sin(n*xi))
    void set_input() {
       double sum;
        
        if(selector==0)
        {
        for (i = 0; i < nmax; i++) {
            y[i] = 0.0;
        }
        for (i = nmax / 2; i < nmax; i++) {
            y[i] = 1.0;
        }
        }
        
         if(selector==1)
        {
        for (i = 0; i < nmax; i++) {
            y[i] = 0.0;
        }
        for (i = nmax-10; i < nmax; i++) {
            y[i] = 1.0;
        }
        }
        
         if(selector==2)
        {
        for (i = 0; i < nmax/2; i++) {
            y[i] = i*2.0/nmax;
        }
        for (i = nmax/2; i < nmax; i++) {
            y[i] = 2.0-i*2.0/nmax;
        }
        }
         if(selector==3)
        {
        for (i = 0; i < nmax; i++) {
            y[i] = 0.7*Math.sin(2*i*Math.PI/nmax);
        }
        
        }
         if(selector==4)
        {
        for (i = 0; i < nmax; i++) {
            y[i] = 0;
        }
        y[nmax/2]=1;
        
        }
         if(selector==5)
        {
        for (i = 0; i < nmax; i++) {
            y[i] = i/(double)nmax;
        }}
        if (jCheckBox1.isSelected())
        {
        sum=0.0;
        for(i=0;i<nmax;i++)sum=sum+y[i];
        
        for (i=0;i<nmax;i++)y[i]=y[i]-sum/nmax;
    }
    }

    void transform() {
        for (i = 0; i < nmax; i++) {
            xi = 2 * Math.PI * i / nmax;
            goertzel(y, xi);

            fcy[i] = cs;
            fsy[i] = ss;
        }

    }

    void back() {

        // fcy - i*fsy is the fourier component of the
        // real function y
        //
        // the inverse transformation gives 
        // sum( (fcy-i*fsy)*(cos n*xi + i*sin n*xi))/N
        // = sum((fcy*cos + fsy*sin)  + i*(fcy*sin - fsy*cos))/N
        // 
        // hence the following two Goertzel transformations calculate
        // s1 = sum(fcy*cos)/N
        // s2 = sum(fcy*sin)/N
        // s3 = sum(fsy*cos)/N
        // s4 = sum(fsy*sin)/N
        //
        // the back transformation gives
        // (s1+s4)  + i*(s2-s3)
        //
        // where of course the imaginary part should be zero




        for (i = 0; i < nmax; i++) {
            xi = 2 * Math.PI * i / nmax;
            goertzel(fcy, xi);
            s1 = cs / nmax;
            s2 = ss / nmax;
            goertzel(fsy, xi);
            s3 = cs / nmax;
            s4 = ss / nmax;
            data1[i][0] = xi;
            data1[i][1] = s1 + s4;
            data1[i][2] = s2 - s3;

        }


    }

    void interpolate() {

        // now we use the fourier sum to interpolate
        // the function


        for (i = 0; i < nmax * 10; i++) {
            xi = 2 * Math.PI * i / (nmax * 10);
            goertzel(fcy, xi);
            s1 = cs / nmax;
            s2 = ss / nmax;
            goertzel(fsy, xi);
            s3 = cs / nmax;
            s4 = ss / nmax;
            data2[i][0] = xi;
            data2[i][1] = s1 + s4;
            data2[i][2] = s2 - s3;

        }



    }

    void interpolate_better() {


        // finally we restrict the frequencies to 
        // the first Brillouin-zone to improve the
        // trigonometric interpolation



        for (i = 0; i < nmax * 10; i++) {
            xi = 2 * Math.PI * i / (nmax * 10);

            trigi(fcy, xi);
            s1 = cs / nmax;
            s2 = ss / nmax;
            trigi(fsy, xi);

            s3 = cs / nmax;
            s4 = ss / nmax;
            data3[i][0] = xi;
            data3[i][1] = s1 + s4;
            data3[i][2] = s2 - s3;

        }








    }

    void do_the_calculation() {



        set_input();
        jPanel1.repaint();
        transform();
        jPanel2.repaint();
        back();
        interpolate();
        jPanel3.repaint();
        interpolate_better();
        jPanel4.repaint();

    }

    public class myPanel1 extends javax.swing.JPanel {

        public void paintComponent(Graphics g1) {


            super.paintComponent(g1);
            g1.setColor(Color.black);
            g1.drawLine(0, 150, 300, 150);
            g1.drawString("Input f(t)", 20, 20);
            g1.setColor(Color.red);
            for (i = 0; i < nmax; i++) {
                g1.fillOval(i * 6 - 2, 148 - (int) (y[i] * 100), 4, 4);
            }

        }
    }

    public class myPanel2 extends javax.swing.JPanel {

        public void paintComponent(Graphics g2) {


            super.paintComponent(g2);
            g2.setColor(Color.black);
            g2.drawLine(0, 150, 300, 150);
            g2.drawString("Fourier coefficients F[f] (omega)", 20, 20);
            g2.setColor(Color.red);
            for (i = 0; i < nmax; i++) {
                g2.drawLine(i*6+6,150,i*6+6,148 - (int) (fcy[i] * scale));
                g2.fillOval(i * 6 + 2, 148 - (int) (fcy[i] * scale), 8, 8);
            }
            g2.setColor(Color.blue);
            for (i = 0; i < nmax; i++) {
                g2.drawLine(i*6+6,150,i*6+6,148 - (int) (fsy[i] * scale));
                g2.fillOval(i * 6 + 2, 148 - (int) (fsy[i] * scale), 8, 8);
            }
        }
    }

    public class myPanel3 extends javax.swing.JPanel {

        public void paintComponent(Graphics g3) {


            super.paintComponent(g3);
            g3.setColor(Color.black);
            g3.drawLine(0, 150, 300, 150);
            g3.drawString("trigonometric interpolation", 20, 20);
            g3.setColor(Color.red);
            for (i = 0; i < 10 * nmax - 1; i++) {
                g3.drawLine((int) (i * 0.6), 150 - (int) (data2[i][1] * 100),
                        (int) (i * 0.6 + 0.6), 150 - (int) (data2[i + 1][1] * 100));
            }
            g3.setColor(Color.blue);
            for (i = 0; i < 10 * nmax - 1; i++) {
                g3.drawLine((int) (i * 0.6), 150 - (int) (data2[i][2] * 100),
                        (int) (i * 0.6 + 0.6), 150 - (int) (data2[i + 1][2] * 100));
            }
            
            
            g3.setColor(Color.red);
            for (i = 0; i < nmax; i++) {
                g3.fillOval(i * 6 - 2, 148 - (int) (data1[i][1] * 100), 4, 4);
            }
            g3.setColor(Color.blue);
            for (i = 0; i < nmax; i++) {
                g3.fillOval(i * 6 - 2, 148 - (int) (data1[i][2] * 100), 4, 4);
            }


        }
    }

    public class myPanel4 extends javax.swing.JPanel {

        public void paintComponent(Graphics g4) {


            super.paintComponent(g4);
            g4.setColor(Color.black);
            g4.drawLine(0, 150, 300, 150);
            g4.drawString("reduction to first Brillouin zone", 20, 20);
            g4.setColor(Color.red);
            for (i = 0; i < 10 * nmax - 1; i++) {
                g4.drawLine((int) (i * 0.6), 150 - (int) (data3[i][1] * 100),
                        (int) (i * 0.6 + 0.6), 150 - (int) (data3[i + 1][1] * 100));
            }
             g4.setColor(Color.blue);
            for (i = 0; i < 10 * nmax - 1; i++) {
                g4.drawLine((int) (i * 0.6), 150 - (int) (data3[i][2] * 100),
                        (int) (i * 0.6 + 0.6), 150 - (int) (data3[i + 1][2] * 100));
            }
            g4.setColor(Color.red);
            for (i = 0; i < nmax; i++) {
                g4.fillOval(i * 6 - 2, 148 - (int) (data1[i][1] * 100), 4, 4);
            }
            g4.setColor(Color.blue);
            for (i = 0; i < nmax; i++) {
                g4.fillOval(i * 6 - 2, 148 - (int) (data1[i][2] * 100), 4, 4);
            }


        }
    }
}
