home

shop

quotes

optical illusions

tutor

about

links

links

     
MathImage    shop_logo

    


/*
SineWave.java
Any portion of this code may be used without permission from BrainyPage.
www.BrainyPage.com | Created by Raul Aguilar | Last Modified 200205032153

Enjoy!
*/

import java.awt.*;
import javax.swing.*;

import java.awt.event.*;
import java.awt.geom.*;
import java.math.*;

import java.applet.*;
import com.borland.jbcl.layout.*;

import java.util.*;


public class SineWave extends JApplet{

  private aJFrame f;
  public static final int WIDTH = 518;
  public static final int HEIGHT = 400;

  public void init() {
    // Set the arguments.
    String[] args = { "2.0" };
    f = new aJFrame(args, getContentPane());
  }

  public void paint(Graphics g) {
    super.paint(g);
    f.redraw();
  }

  public static void main(String[] args) {
    aJFrame frame = new aJFrame(args);
    frame.setTitle("SineWave");
    frame.setSize(WIDTH,HEIGHT);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.show();
  }
}

class aJFrame extends JFrame {

  public aJFrame(String[] args) {
    buildPanels(args, getContentPane());
  }

  public aJFrame(String[] args, Container cp) {
    buildPanels(args, cp);
  }

  public void buildPanels(String[] args, Container cp) {

    panelSimulate = new Simulate(args);
    Control panelControl = new Control(args, panelSimulate);

    JPanel p = new JPanel();
    p.setLayout(new XYLayout());
    p.add(panelSimulate, new XYConstraints(5, 5, 498, 335));
    p.add(panelControl, new XYConstraints(5, 345, 380, 90));
    cp.add(p,BorderLayout.CENTER);
  }

  public void redraw() {
    panelSimulate.repaint();
  }

  Simulate panelSimulate;
}

class Simulate extends JPanel {

  private double a;
  private String[] args;

  int w;
  int h;
  double w2;
  double h2;
  double cx;
  double cy;
  double positiveUnitsX;
  double positiveUnitsY;
  double degreeToRadian;
  double transMathToDeviceX;
  double transMathToDeviceY;

  public Simulate(String[] args) {
    setParameters(args);

    //Initialize drawing colors
    setBackground(Color.white);
    setForeground(Color.black);
  }

  public void setParameters(String controlValues) {
    StringTokenizer st = new StringTokenizer(controlValues);
    ArrayList al = new ArrayList();
    while (st.hasMoreTokens()) {
      al.add((String) st.nextToken());
    }
    String[] s = (String[]) al.toArray(new String[0]);
    setParameters(s);
  }

  public void setParameters(String[] args) {
    a = Double.parseDouble(args[0]);

    System.out.println("parameter values:");
    System.out.println();
    System.out.println("a = " + a);
  }

  public void fixDimensions() {

    // Find the width and height of the JPanel.
    Dimension d = getSize();
    w = d.width;
    h = d.height;

    // Calculate the half height.
    w2 = w / 2.0;
    h2 = h / 2.0;

    // Set the graph center at center of graph.
    cx = w / 2.0;
    cy = h / 2.0;

    // Set size of positive x-axis.
    positiveUnitsX = 4;

    // Find size of positive y-axis.
    positiveUnitsY = positiveUnitsX * h2 / w2;

    // Use to convert degree to radian.
    degreeToRadian = Math.PI /180.0;

    // In this code version,
    // transMathToDeviceX is same value as transMathToDeviceY.
    transMathToDeviceX = w2 / positiveUnitsX;
    transMathToDeviceY = h2 / positiveUnitsY;
  }

  public void paint(Graphics g) {

    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;

    fixDimensions();
    drawGrid(g2);

    // Set the pen width.
    int penWidth = 2;
    g2.setStroke(new BasicStroke(penWidth));

    double separator = 0.9;
    double sa = separator * a;
    drawCircle(g2, -a, 0, sa);
    double waveLength = 2 * (1.0 - (1.0 - separator) / 2.0) * a;
    drawSineWave(g2, sa, waveLength);
    drawCircleToWave(g2, 30, -a, 0, sa, waveLength);
    drawCircleToWave(g2, 60, -a, 0, sa, waveLength);
    drawCircleToWave(g2, 135, -a, 0, sa, waveLength);
    drawCircleToWave(g2, 315, -a, 0, sa, waveLength);
  }

  private void drawGrid(Graphics2D g2) {

    // Use physical xy points.
    double px;
    double py;
    double nx;
    double ny;

    double unitsPerGridLine = .2;
    double gridLines = positiveUnitsX/unitsPerGridLine;

    for (int i=0; i < 2*gridLines ; ++i) {

      px = cx + (i * unitsPerGridLine) * transMathToDeviceX;
      py = cy - (i * unitsPerGridLine) * transMathToDeviceY;

      // Find the minus x values for grid lines
      // on the negative side of the graph.
      nx = cx - (i * unitsPerGridLine) * transMathToDeviceX;
      ny = cy + (i * unitsPerGridLine) * transMathToDeviceY;

      if (i == 0) {
        // Draw the xy axis.
        g2.setPaint(new Color(255, 0, 255));
      }
      else {
        g2.setPaint(new Color(0, 255, 255));
        g2.draw(new Line2D.Double( nx, 0, nx, h));
        g2.draw(new Line2D.Double( 0, ny, w, ny));
      }

      g2.draw(new Line2D.Double( px, 0, px, h));
      g2.draw(new Line2D.Double( 0, py, w, py));
    }

  }

  private void drawCircle(
    Graphics2D g2,
    double cx,
    double cy,
    double r) {

    // Set pen color.
    g2.setPaint(new Color(0, 255, 255));

    Ellipse2D circle =
      new Ellipse2D.Double(
        userToDeviceX(cx - r),
        userToDeviceY(cy + r),
        2 * r * transMathToDeviceX,
        2 * r * transMathToDeviceY);
    g2.draw(circle);
  }

  private void drawSineWave(Graphics2D g2, double radius, double waveLength) {

    // Set pen color.
    g2.setPaint(new Color(0, 0, 255));

    // Angular change in degree.
    double delta = 1.0;

    // Previous x and y device values.
    int dx_prev = 0;
    int dy_prev = 0;

    // Span one quadrant 0 to 90 degree.
    // Account for the square root only producing a positive radius.
    for (double degree = 0.0; degree < 360.0; degree += delta) {

      // Convert to radian.
      double radian = Math.toRadians(degree);

      // Find <x, y>
      double x = radian / (2.0 * Math.PI / waveLength);
      double y = radius * Math.sin(radian);

      int dx = userToDeviceX(x);
      int dy = userToDeviceY(y);

      if ((delta / 2.0) < degree) {
        // Render the normal distribution line.
        Point2D startP = new Point2D.Double(dx_prev, dy_prev);
        Point2D endP = new Point2D.Double(dx, dy);
        g2.draw(new Line2D.Double(startP, endP));
      }
      dx_prev = dx;
      dy_prev = dy;
    }
  }

  private void drawCircleToWave(
    Graphics2D g2,
    double angle,
    double cx,
    double cy,
    double radius,
    double waveLength) {

    // Set pen color.
    g2.setPaint(new Color(255, 0, 0));

    double radian = Math.toRadians(angle);

    double startX = cx + radius * Math.cos(radian);
    double startY = cy + radius * Math.sin(radian);
    double endX = radian / (2.0 * Math.PI / waveLength);
    double endY = radius * Math.sin(radian);
    g2.drawLine(
      userToDeviceX(startX),
      userToDeviceY(startY),
      userToDeviceX(endX),
      userToDeviceY(endY));

    // Set pen color.
    g2.setPaint(new Color(255, 255, 0));

    g2.drawLine(
      userToDeviceX(cx),
      userToDeviceY(cy),
      userToDeviceX(startX),
      userToDeviceY(startY));

    // Set pen color.
    g2.setPaint(new Color(0, 0, 0));

    // Set dot size;
    int dotSize = 3;

    Rectangle2D rect;
    rect = new Rectangle2D.Double(
      userToDeviceX(startX) - dotSize / 2,
      userToDeviceY(startY) - dotSize / 2,
      dotSize,
      dotSize);
    g2.draw(rect);
    rect = new Rectangle2D.Double(
      userToDeviceX(endX) - dotSize / 2,
      userToDeviceY(endY) - dotSize / 2,
      dotSize,
      dotSize);
    g2.draw(rect);
  }

  private int userToDeviceX(double x) {
    return (int) (cx + x * transMathToDeviceX);
  }

  private int userToDeviceY(double y) {
    return (int) (cy - y * transMathToDeviceY);
  }
}

class Control extends JPanel {

  private String[] args;
  private JTextField tf;
  private Simulate s;

  public Control(String[] args, Simulate sp) {

    this.args = args;
    this.setLayout(new XYLayout());

    s = sp;

    JButton b = new JButton("Go");
    ActionListener bl = new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        s.setParameters(tf.getText().trim());
        s.repaint();
      }
    };
    b.addActionListener(bl);
    add(b, new XYConstraints(0, 3, 50, 20));

    tf = new JTextField("2.0",5);
    add(tf, new XYConstraints(60, 3, 50, 20));
  }
}