如何尽可能准确地绘制蝴蝶曲线?

我想画一个蝶形线使用Java

这是上述曲线的参数方程:

http://img2.mukewang.com/61bd8a070001b6ed03330129.jpg

根据我在大学时的记忆,绘制参数方程的方法Java是下一个:


public void paintComponent(Graphics g) {

    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D)g;

    g2.translate(300,300);

    int x1,y1;

    int x0 = 0;

    int y0 = (int)(Math.E-2); //for x = 0, we get y = Math.E - 2

    int nPoints = 1000;

    g2.scale(30,-30);

    for(int i=0;i<nPoints;i++) {

        double t= 12*i*Math.PI/nPoints; //to make it between 0 and 12*PI.

        x1=(int)(Math.sin(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));

        y1 = (int)(Math.cos(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));

        g2.drawLine(x0,y0,x1,y1);

        x0=x1;

        y0=y1;

    }

}

现在,这给了我下一个结果:

http://img4.mukewang.com/61bd8a11000188b802420263.jpg

好吧,这与预期的结果相差甚远。


然后我决定尝试一下,Line2D.Double认为这会提供更准确的绘图。


public void paintComponent(Graphics g) {

    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D)g;

    g2.translate(300,300);

    double x1,y1;

    double x0 = 0;

    int nPoints = 500;

    g2.scale(30,-30);

    double y0 = Math.E-2;

    for(int i=0;i<nPoints;i++) {

        double t= 12*i*Math.PI/nPoints;

        x1=(Math.sin(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));

        y1 = (Math.cos(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));

        g2.draw(new Line2D.Double(x0,y0,x1,y1));

        x0=x1;

        y0=y1;

    }

}

这产生了下一个结果:

http://img3.mukewang.com/61bd8a210001b05e02230214.jpg

好的,这肯定看起来更好,但肯定不是预期的结果。

因此我问,有没有办法使用这个参数方程绘制最准确的曲线Java

http://img.mukewang.com/61bd8a2e0001d3a502510250.jpg

它不必像上图那样 100% 看起来,而是最接近的。


慕桂英3389331
浏览 247回答 1
1回答

鸿蒙传说

你的 scale 语句也会缩放你的线的宽度,导致你的曲线形状奇怪。有两种简单的方法可以解决这个问题:减少线的宽度,例如到 0.01f:Graphics2D g2 = (Graphics2D)g;g2.translate(300,300);double x1,y1;double x0 = 0;int nPoints = 500;// Alternative 1 ---------------------g2.scale(30,-30);g2.setStroke(new BasicStroke(0.01f ));// -----------------------------------double y0 = Math.E-2;for(int i=0;i<nPoints;i++) {&nbsp; &nbsp; double t= 12*i*Math.PI/nPoints;&nbsp; &nbsp; x1= (Math.sin(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));&nbsp; &nbsp; y1 = (Math.cos(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));&nbsp; &nbsp; g2.draw(new Line2D.Double(x0,y0,x1,y1));&nbsp; &nbsp; x0=x1;&nbsp; &nbsp; y0=y1;}&nbsp;&nbsp;这导致:删除您的比例声明并使用其幅度缩放曲线,即使用关于您的 x 和 y 值的恒定前置因子,例如 -30:Graphics2D g2 = (Graphics2D)g;g2.translate(300,300);double x1,y1;double x0 = 0;int nPoints = 500;// Alternative 2 ---------------------double amp = -30.0;// -----------------------------------double y0 = Math.E-2;for(int i=0;i<nPoints;i++) {&nbsp; &nbsp; double t= 12*i*Math.PI/nPoints;&nbsp; &nbsp; // Alternative 2 ----------------------------------------------------------------------------------&nbsp; &nbsp; x1=amp*(Math.sin(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));&nbsp; &nbsp; y1=amp*(Math.cos(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));&nbsp; &nbsp; // ------------------------------------------------------------------------------------------------&nbsp; &nbsp; g2.draw(new Line2D.Double(x0,y0,x1,y1));&nbsp; &nbsp; x0=x1;&nbsp; &nbsp; y0=y1;}&nbsp;&nbsp;这导致(或多或少相同):此外,您可以通过使用抗锯齿和增加 nPoints 来提高绘图的质量:&nbsp; &nbsp; Graphics2D g2 = (Graphics2D)g;&nbsp; &nbsp; // Optimization ------------------------------------&nbsp; &nbsp; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RenderingHints.VALUE_ANTIALIAS_ON);&nbsp; &nbsp; int nPoints = 1500;&nbsp; &nbsp; // -------------------------------------------------&nbsp; &nbsp; g2.translate(300,300);&nbsp; &nbsp; double x1,y1;&nbsp; &nbsp; double x0 = 0;&nbsp; &nbsp; // Alternative 1 ---------------------&nbsp; &nbsp; g2.scale(50,-50);&nbsp; &nbsp; g2.setStroke(new BasicStroke(0.01f ));&nbsp; &nbsp; // -----------------------------------&nbsp; &nbsp; double y0 = Math.E-2;&nbsp; &nbsp; for(int i=0;i<nPoints;i++) {&nbsp; &nbsp; &nbsp; &nbsp; double t= 12*i*Math.PI/nPoints;&nbsp; &nbsp; &nbsp; &nbsp; x1= (Math.sin(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));&nbsp; &nbsp; &nbsp; &nbsp; y1 = (Math.cos(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));&nbsp; &nbsp; &nbsp; &nbsp; g2.draw(new Line2D.Double(x0,y0,x1,y1));&nbsp; &nbsp; &nbsp; &nbsp; x0=x1;&nbsp; &nbsp; &nbsp; &nbsp; y0=y1;&nbsp; &nbsp; }&nbsp;&nbsp;这导致(看起来好多了):到目前为止,两点之间的连接是一条直线。当然,您可以使用样条曲线(贝塞尔曲线等)进行进一步优化,但这可能并非易事。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java