TameHog
TameHog

Reputation: 950

Java - plotting sine waves

I am using the following code to generate a sine wave: SineWave
The speed of this animation is slow-fast-slow. Code:

public static final double SINE_TO_180 = 114.58865012930961, TIMES = 180, SINE_OF_90 = Math.sin(Math.toRadians(90));

public static void main(String[] args) throws Exception{
    float velc = 200;
    float angle = 45;
    float resistance = 0f;
    double multiple = (velc * 2.5 / SINE_TO_180);
    int offset = 0;
    double y = 0;
    double x = 0;
    double h = 0;
    double cos = Math.cos(Math.toRadians(angle));
    double sin = Math.sin(Math.toRadians(angle));
    for(int i = offset; i < TIMES + 1 + offset; i ++){
        y += ((Math.sin(Math.toRadians(i * 2)))) * multiple * sin;
        if(y >= h)
            h = y;
        x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
//          x += multiple * cos;
//          if(i + offset < TIMES / 2){
//              x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
//          }else{
//              x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
//          }
    }
    y = Math.round(y);
    //do round x?
    x = Math.round(x);
    System.out.println("X: " + x);
    JFrame frm = new JFrame("Projectile!");
    frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    BufferedImage b = new BufferedImage((int)x + 1, (int)h + 1, BufferedImage.TYPE_INT_RGB);
    Graphics g = b.getGraphics();
    y = 0;
    x = 0;

    JLabel l = new JLabel(new ImageIcon(b));
    frm.add(l);
    frm.pack();
    frm.setVisible(true);

    for(int i = offset; i < TIMES + 1 + offset; i ++){
        y += ((Math.sin(Math.toRadians(i * 2)))) * multiple * sin;

        x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
 //         x += multiple * cos;
//          if(i + offset < TIMES / 2){
//              x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
//          }else{
//              x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
//          }
        g.setColor(Color.red);
        g.drawLine((int)x, (int)(h - y), (int)x, (int)(h - y));
        l.setIcon(new ImageIcon(b));
        frm.repaint();
        Thread.sleep((int)(1000.0 / 24.0));
    }
    ImageIO.write(b, "png", new File("C:\\proj.png"));
}

Now I would like to change the sine animation to fast-slow-fast where it is slow at its peak so I tried the following result and got this:
SineWave2
I would expect it to be the same just the animation speed different. Code:

public static void main(String[] args) throws Exception{
    float velc = 200;
    float angle = 45;
    float resistance = 0f;
    double multiple = (velc * 2.5 / SINE_TO_180);
    int offset = 0;
    double y = 0;
    double x = 0;
    double h = 0;
    double cos = Math.cos(Math.toRadians(angle));
    double sin = Math.sin(Math.toRadians(angle));
    for(int i = offset; i < TIMES + 1 + offset; i ++){
        y += (1 - Math.sin(Math.toRadians(i * 2))) * multiple * sin;
        if(y >= h)
            h = y;
//          x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
        x += 2;
        //          x += multiple * cos;
//          if(i + offset < TIMES / 2){
//              x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
//          }else{
//              x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
//          }
    }
    y = Math.round(y);
    //do round x?
    x = Math.round(x);
    System.out.println("X: " + x);
    JFrame frm = new JFrame("Projectile!");
    frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    BufferedImage b = new BufferedImage((int)x + 1, (int)h + 1, BufferedImage.TYPE_INT_RGB);
    Graphics g = b.getGraphics();
    y = 0;
    x = 0;

    JLabel l = new JLabel(new ImageIcon(b));
    frm.add(l);
    frm.pack();
    frm.setVisible(true);

    for(int i = offset; i < TIMES + 1 + offset; i ++){
        y += (1 - Math.sin(Math.toRadians(i * 2))) * multiple * sin;
        x += 2;
//          x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
//          x += multiple * cos;
//          if(i + offset < TIMES / 2){
//              x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
//          }else{
//              x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
//          }
        g.setColor(Color.red);
        g.drawLine((int)x, (int)(h - y), (int)x, (int)(h - y));
        l.setIcon(new ImageIcon(b));
        frm.repaint();
        Thread.sleep((int)(1000.0 / 24.0));
    }
    ImageIO.write(b, "png", new File("C:\\proj2.png"));
}

Anyone know what I am doing wrong because I expect the result to be the same as the first just different animation speeds?

Upvotes: 2

Views: 4030

Answers (1)

Martin Frank
Martin Frank

Reputation: 3454

if you want to have a smooth animation i would seperate the data and the animation;

first create your data - it is a (mathematical) function [meaning f(x)->y], so you can simply use an array for data

private int endOfX = 100; //adjust as you wish
private int[] data;
public void calculateData(){
    data = new int[amendOfX ountPixels];
    for(int x = 0; x < endOfX ; x++){
        y = x*x; //this is an example, use your mathematical function here
    }
}

so - now you can easily use this data to provide a smooth animation

public class AnimationOfFunction(){
    public static void main(String[] args){
        new AnimationOfFunktion().createAndShowGui(); //as from java tutorials
    }

    private BufferedImage img;
    private Graphics gr;
    private void createAndShowGui(){
        calculateData(); first of all we create the data!
        JFrame frame = new JFrame();//then create your frame here
        JPanel panel = createContent(); //create your drawing panel here
        frame.add(panel);//adding drawing panel
        frame.pack(); //setting the proper size of frame
        frame.setVisible(true); //show frame          
        startAnimation(panel); //this is important - after showing the frame you start your animation here!
    }
}

so - this would be the start of you application, what to do now? first create a proper drawing panel:

private JPanel createContent(){
    //create a anonym class
    @surpress serial
    JPanel panel = new JPanel(){

        @override
        public void paintComponent(Graphics gr){
            super.paintComponent(gr);
            gr.drawImage(img, 0,0, null);
        }

    } 
    panel.setPreferredSize(new Dimension(img.getWidth(), img.getHeight() ));
    return panel;
}

and most important - you have to start the animation:

private void startAnimation(final JPanel panel){
    //create a anonym class
    Runnable r = new Runnable(){
        private int py = 0; //previous values
        private int py = 0; //previous values
        @overrdie
        public void run(){
            for(int x = 0; x < endOfX ; x++){
                int y = data[x];
                //now we have x and y, so you can plot your function;
                gr.drawLine(px, py, x,y); //you can scale here
                int sleeptime = calculateSleepTime(px,py, x,y);
                Thread.sleep(sleeptime);

                //set the previouse values;
                px = x;
                py = y;

                //important - repaint your panel to create an 'animation'
                panel.repaint();

            }
        }
    }

    //having that runnable we must start that runnable within an thread
    Thread thread = new Thread(r);
    thread.setDaemon(true);
    thread.start();
}

so whats left to do? we must calculate the sleep time: if the distance between two points is 'big' we sleep longer, if the distance is short, we sleep less...

public int calculateSleeptime(int px, int py, int x, int y){
    int distance = (y-py)*(y-py)+(x-px)*(x-px);
    distance = (int)(Math.sqrt(distance);
    int sleepTime = distance*100; //play with this value!
    return sleeptime;
}

I have written that code all out of my head, i didn't have any IDE to check if it contains any spelling errors or compiling errors, please do that for yourself, as well as i didn't initiate the BufferedImage img ang Graphics gr. but obvious you can do that already!

Upvotes: 3

Related Questions