import java.awt.Color;
import java.awt.Graphics;
import javax.swing.BoundedRangeModel;

/**
 *
 * @author  zhouer
 */
public class Cycloid extends javax.swing.JApplet
{

    final int minR = 0, maxR = 100;
    final int minr = -50, maxr = 50;
    final int mind = -50, maxd = 50;
    
    final int resolution = 3000;

    int R = 30;
    int r = 10;
    int d = 10;
    
    double scale = 2;
        
    /** Initializes the applet Curve */
    // @Override
    public void init() {
        try {
            java.awt.EventQueue.invokeAndWait(new Runnable() {
                public void run() {
                    initComponents();
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    
    // @Override
    public void paint( Graphics g )
    {
		super.paint(g);
        draw();
    }
    
    public Color gradient( double g, Color start, Color end )
    {
        int r1, g1, b1;
        int r2, g2, b2;
        int mr, mg, mb;
        
        r1 = start.getRed();
        g1 = start.getGreen();
        b1 = start.getBlue();
        
        r2 = end.getRed();
        g2 = end.getGreen();
        b2 = end.getBlue();

        mr = (int) (r1 + g * (r2 - r1));
        mg = (int) (g1 + g * (g2 - g1));
        mb = (int) (b1 + g * (b2 - b1));
        
        return new Color(mr, mg, mb);
    }
    
    public int lcm( int x, int y)
    {
        x = Math.abs(x);
        y = Math.abs(y);
        return x * y / gcd(x, y);
    }
    
    public int gcd( int x, int y )
    {
        x = Math.abs(x);
        y = Math.abs(y);
        
        while( (x != 0) && (y != 0) ) {
            if( x >= y ) {
                x %= y;
            } else {
                y %= x;
            }
        }
        
        return x + y;
    }
    
    public void draw()
    {
        int i, x1, y1, x2, y2;

        double angle, t;
        double[] theta = new double[resolution];
        double[] x = new double[resolution];
        double[] y = new double[resolution];
        
        // angle = lcm( R, r ) / r * 2 * Math.PI;
        angle = R / gcd( R, r ) * 2 * Math.PI;
        
        for(i = 0; i < theta.length; i++) {
            theta[i] = angle * i / theta.length;
            t = -1 * r * theta[i] / R;
            x[i] = (R - r) * Math.cos( t ) + d * Math.cos( t + theta[i] );
            y[i] = (R - r) * Math.sin( t ) + d * Math.sin( t + theta[i] );
        }
        
        Graphics g = PlotPanel.getGraphics();
        g.clearRect( 0, 0, PlotPanel.getWidth(), PlotPanel.getHeight() );
        g.translate( PlotPanel.getWidth() / 2, PlotPanel.getHeight() / 2);
        
        for(i = 0; i < theta.length - 1; i++) {
            x1 = (int)(scale * x[i]);
            y1 = (int)(scale * y[i]);
            x2 = (int)(scale * x[i + 1]);
            y2 = (int)(scale * y[i + 1]);
            g.setColor( gradient(1. * i / theta.length, Color.ORANGE, Color.CYAN) );
            g.drawLine( x1, y1, x2, y2 );
        }

    }
    
    /** 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() {

        PlotPanel = new javax.swing.JPanel();
        ControlPanel = new javax.swing.JPanel();
        jSlider1 = new javax.swing.JSlider();
        jSlider2 = new javax.swing.JSlider();
        jSlider3 = new javax.swing.JSlider();
        jSlider4 = new javax.swing.JSlider();
        jTextField1 = new javax.swing.JTextField();
        jTextField2 = new javax.swing.JTextField();
        jTextField3 = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        RandomButton = new javax.swing.JButton();

        javax.swing.GroupLayout PlotPanelLayout = new javax.swing.GroupLayout(PlotPanel);
        PlotPanel.setLayout(PlotPanelLayout);
        PlotPanelLayout.setHorizontalGroup(
            PlotPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 483, Short.MAX_VALUE)
        );
        PlotPanelLayout.setVerticalGroup(
            PlotPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 167, Short.MAX_VALUE)
        );

        getContentPane().add(PlotPanel, java.awt.BorderLayout.CENTER);

        jSlider1.setMaximum( maxR );
        jSlider1.setMinimum( minR );
        jSlider1.setValue(R);
        jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sliderChange(evt);
            }
        });

        jSlider2.setMaximum( maxr );
        jSlider2.setMinimum( minr );
        jSlider2.setValue(r);
        jSlider2.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sliderChange(evt);
            }
        });

        jSlider3.setMaximum( maxd );
        jSlider3.setMinimum( mind );
        jSlider3.setValue(d);
        jSlider3.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sliderChange(evt);
            }
        });

        jSlider4.setValue(20);
        jSlider4.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sliderChange(evt);
            }
        });

        jTextField1.setColumns(3);
        jTextField1.setText(Integer.toString(R));

        jTextField2.setColumns(3);
        jTextField2.setText(Integer.toString(r));

        jTextField3.setColumns(3);
        jTextField3.setText(Integer.toString(d));

        jLabel1.setText("Fixed circle");

        jLabel2.setText("Moving circle");

        jLabel3.setText("Offset");

        jLabel4.setText("Scale");

        RandomButton.setText("Random");
        RandomButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                RandomButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout ControlPanelLayout = new javax.swing.GroupLayout(ControlPanel);
        ControlPanel.setLayout(ControlPanelLayout);
        ControlPanelLayout.setHorizontalGroup(
            ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(ControlPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(ControlPanelLayout.createSequentialGroup()
                        .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel1)
                            .addComponent(jLabel2)
                            .addComponent(jLabel3)
                            .addComponent(jLabel4))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jSlider4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(ControlPanelLayout.createSequentialGroup()
                                .addComponent(jSlider3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(ControlPanelLayout.createSequentialGroup()
                                .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                    .addComponent(RandomButton))
                .addContainerGap(143, Short.MAX_VALUE))
        );
        ControlPanelLayout.setVerticalGroup(
            ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(ControlPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(ControlPanelLayout.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)
                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel2)
                    .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(ControlPanelLayout.createSequentialGroup()
                        .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel3)
                            .addComponent(jSlider3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(ControlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel4)
                            .addComponent(jSlider4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(RandomButton))
                    .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(22, Short.MAX_VALUE))
        );

        getContentPane().add(ControlPanel, java.awt.BorderLayout.SOUTH);
    }// </editor-fold>//GEN-END:initComponents

    private void sliderChange(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sliderChange
        
        BoundedRangeModel m1 = jSlider1.getModel();
        BoundedRangeModel m2 = jSlider2.getModel();
        BoundedRangeModel m3 = jSlider3.getModel();
        
        BoundedRangeModel m4 = jSlider4.getModel();
        scale = m4.getValue() / 10.;
        
        R = m1.getValue();
        r = m2.getValue();
        d = m3.getValue();
        
        jTextField1.setText( Integer.toString(R) );
        jTextField2.setText( Integer.toString(r) );
        jTextField3.setText( Integer.toString(d) );
        
        draw();
}//GEN-LAST:event_sliderChange

    private void RandomButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RandomButtonActionPerformed
        BoundedRangeModel m1 = jSlider1.getModel();
        BoundedRangeModel m2 = jSlider2.getModel();
        BoundedRangeModel m3 = jSlider3.getModel();
        
        BoundedRangeModel m4 = jSlider4.getModel();
        m4.setValue( 20 );
        
        m1.setValue( (int)(minR + Math.random() * (maxR - minR)) );
        m2.setValue( (int)(minr + Math.random() * (maxr - minr)) );
        m3.setValue( (int)(mind + Math.random() * (maxd - mind)) );
}//GEN-LAST:event_RandomButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel ControlPanel;
    private javax.swing.JPanel PlotPanel;
    private javax.swing.JButton RandomButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JSlider jSlider2;
    private javax.swing.JSlider jSlider3;
    private javax.swing.JSlider jSlider4;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    // End of variables declaration//GEN-END:variables
    
}
