迭代分形是一种数学上的概念,是指通过一种简单的规则,不断重复运算,最终得到复杂的图形。我们通过画板来实现图像的生成,迭代图像即通过一定的坐标推算公式,从初始坐标点不断获取新的坐标值并打点,修改点迹颜色以形成一个有深浅变化的图像。用代码实现自然界的美,生成一系列二维,三维的图像,它们不是杂乱无章的,而是具有一定规则的富有美感的图像。
首先创建一个窗体类,这样可以在窗体类中重写容器的paint方法。添加和创建一些基本组件:画板标题、画板大小、关闭方式等。
public class DrawPad extends JFrame{
public DrawPad(){
setTitle ("迭代分形");
setSize (800,800);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setVisible (true);
setLocationRelativeTo (null);
}
要想在窗体中呈现一些图案还需要添加一些数据,利用数学函数的方式,利用循环不断的更新点的坐标,使成千上万的点组成我们需要创建的图案。
public void paint(Graphics g){
super.paint (g);
drawIFS_01 (g);
public void drawIFS_01(Graphics g){
double a = -1.8, b = -2.0, c = -0.5, d = -0.9;
double xn = 0, yn = 0;
for(int i = 0; i < 100000; i++){
double tempx = Math.sin (a * yn) + c * Math.cos (a * xn);
double tempy = Math.sin (b * xn) + d * Math.cos (b * yn);
// 迭代给下一次 xn yn
xn = tempx;
yn = tempy;
int px = (int) (tempx * 100) + 400;
int py= (int) (tempy * 100) + 400;
g.setColor (Color.blue);
g.drawLine (px, py, px, py);
}
}
public static void main(String[] args){
new DrawPad ();
}
以上是迭代图像的实现方法,在写这段代码的过程中我们要注意几个要点。首先,坐标通过公式计算后数值很小,需要放大并移到屏幕中央,打点后再进行迭代,再打点,直到循环结束,其中每一次迭代都使颜色加深。此处a,b,c,d的值是我们自己定义的。颜色可以根据自己的喜好更改即可。修改这里的函数和参数图形会相应地发生改变。如下图是这段代码运行后画出的图案。
g.setColor (Color.blue); //修改颜色的迭代函数
以上程序画出来的是一个2D的平面图形。下面利用内存缓冲,记录每次绘制的点,每个值都是一张图片,随着点连续不断的增加,就实现了动画的效果。
窗体类:
package DrawDongHua;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
//用一个内存队列,来保存要画的对象
//一个线程,来画
public class Game extends JFrame {
//队列对象
private ArrayList<Shape> al=new ArrayList();
public void initUI(){
this.setSize(600,800);
this.setDefaultCloseOperation(3);
FlowLayout fl=new FlowLayout();
this.setLayout(fl);
this.setVisible(true);
JButton buSend=new JButton("绘制");
this.add(buSend);
Graphics g=this.getGraphics();
BuAction ba=new BuAction(g);
buSend.addActionListener(ba);
}
public static void main(String args[]) {
Game wu=new Game();
wu.initUI();
}
}
监听器类:
package DrawDongHua;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
public class BuAction implements ActionListener {
private Graphics g=null;
public BuAction(Graphics g){
this.g=g;
}
public void actionPerformed(ActionEvent e) {
double x = 0f;
double y = 0f;
double a=-1.8;
// double b = -2.0;
double c = -0.5, d = -0.9;
for (double b = -2; b < 2; b += 0.001) { //b的值每次增加0.001
// a=b;
try {
Thread.sleep(10);
}catch (Exception ef){}
//内存缓冲
BufferedImage bi=new BufferedImage(800,800,BufferedImage.TYPE_INT_RGB);
Graphics g2=bi.getGraphics();
g2.setColor(Color.GREEN);
for (int i = 0; i < 20000; i++) {
//计算下一次的x,y
double temx = Math.sin(a * y) + c * Math.cos(a * x);
double temy = Math.sin(b * x) + d * Math.cos(b * y);
//对x1,y1转型,放大,移动到屏幕坐标系:
int x1 = (int) (temx * 130 + 300);
int y1 = (int) (temy * 130 + 400);
g2.fillOval(x1, y1, 2, 2);
//
x = temx;
y = temy;
}
//生成一张图片之后,则画到界面上:
g.drawImage(bi,0,100,null);
}
}
}
如下利用迭代函数以及数学中图形的基本思想,构建图形的偏移连接,完成一个3D的立体图形。
与上述步骤一样,先创建一个窗体类,继承构建图案的paint类。
package draw;
import javax.swing.*;
import java.awt.*;
import java.util.Random;
@SuppressWarnings("serial")
public class DrawPad extends JFrame{
public DrawPad(){
setTitle ("迭代分形");
setSize (800,800);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setVisible (true);
setLocationRelativeTo (null);
}
接下来,根据数学思维,定义立方体所需的值,画出一个正方形,用 g.drawRect() 函数,填入相应值,画出其相对面,用 g.drawLine() 函数连接两个面之间八个顶点构成正方体。
int x = 100, y = 250, w = 300, h = 300, dx = w / 3, dy = h / 3;//正方形初始值
//x图形页面左边距 y页面上边距 w正方形的宽 h正方形的高 dx在x轴偏移距离 dy在y轴偏移的距离
g.drawRect (x + dx, y - dy, w, h);//构建相对面
//绘制两正方形间八个顶点的连接线
g.drawLine (x, y, x + dx, y - dy);
g.drawLine (x + w, y, x + w + dx, y - dy);
g.drawLine (x, y + h, x + dx, y + h - dy);
g.drawLine (x + w, y + h, x + w + dx, y + h - dy);
g.setColor (Color.red);//定义颜色,初始正方形为红色线
g.drawRect (x, y, w, h);
同样画出一个3D球体,先画出一个圆,利用循环和颜色的改变,使多个圆形不断叠加变成一个球体。
for(int i = 0; i < 255; i++){
g.setColor (new Color (i, i, 0));//设置颜色
g.fillOval (160 + i/4 , 200 + i/4, 255 -i, 255-i );
//(左上角x坐标,左上角y坐标,圆宽、圆高)
}
不断调整球体在坐标中的位置,使球体放在立方体的内部。运行结果后的效果图如下:
在这里我还拓展了一个函数。g.fillPolygon (); 定义一个多边形的内部,先定义一个函数值,输入相对的顶点坐标,够建一个面,可以更改面的颜色。
//选择正方形的四个点构成面
Polygon polygon = new Polygon ();
polygon.addPoint (x, y);
polygon.addPoint (x + dx, y - dy);
polygon.addPoint (x + dx, y - dy+h);
polygon.addPoint (x, y + h);
g.setColor(Color.gray);
g.fillPolygon (polygon);// fillPolygon 定义多边形内部
这样就给立方体的一个面添加了颜色,将上述代码运行一下看看效果。
这样,一个立方体内部添加一个球体的图形就完成了,只需添加一个主函数即可。