【问题标题】:Java - plotting sine wavesJava - 绘制正弦波
【发布时间】:2014-08-29 02:08:39
【问题描述】:

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

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

现在我想将正弦动画更改为快-慢-快,它在峰值时很慢,所以我尝试了以下结果并得到了这个:

我希望它是相同只是动画速度不同。代码:

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

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

【问题讨论】:

  • 您能解释一下“动画速度”是什么意思吗?是绘制的两点之间的时间吗?如果是,那我必须纠正你:画一个点的时间总是同一时间!但是两点之间的距离正在改变!如示例 2 所示,您总是向前“走”两个像素,而在示例 1 中,您向前移动不同数量的像素(开始时很少,中间更多,最后又很少)

标签: java waveform trigonometry


【解决方案1】:

如果你想要一个流畅的动画,我会把数据和动画分开;

首先创建你的数据——它是一个(数学)函数[意思是 f(x)->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 图形 gr。但显然你已经可以做到了!

【讨论】:

  • 我遵循了您的代码,但结果相同!它有一条奇怪的线,就像我的第二个例子一样。
  • 也许您可以描述一下您所期望的图表?我的代码示例可以轻松调整,以便绘制您的函数....请告诉我它应该是什么样子(也许添加图片?)
猜你喜欢
  • 2014-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多