Java - 绘制正弦波

时间:2014-08-29 02:08:39

标签: java waveform sine

我使用以下代码生成正弦波: SineWave
这个动画的速度慢 - 快 - 慢。 代码:

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"));
}

现在我想将正弦动画更改为快速 - 慢速 - 它在峰值处慢,所以我尝试了以下结果并得到了这个:
SineWave2我会期望它只是动画速度不同。代码:

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"));
}

任何人都知道我做错了什么,因为我希望结果与第一个不同的动画速度相同?

1 个答案:

答案 0 :(得分:3)

如果你想要一个平滑的动画,我会分开数据和动画;

首先创建你的数据 - 它是一个(数学)函数[意思是f(x) - &gt; y],所以你可以简单地使用一个数组来获取数据

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
    }
}

所以 - 现在您可以轻松使用此数据来提供流畅的动画

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!
    }
}

所以 - 这将是您申请的开始,现在该怎么办?首先创建一个合适的绘图面板:

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;
}

最重要的是 - 你必须开始动画:

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();
}

所以剩下要做什么了?我们必须计算睡眠时间:如果两点之间的距离是“大”的话。我们睡得更久,如果距离很短,我们睡得更少......

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;
}

我已经编写了所有代码,我没有任何IDE来检查它是否包含任何拼写错误或编译错误,请为自己做,以及我没有启动BufferedImage img ang Graphics gr。但显而易见,你已经可以做到了!