关于简单分形图形的绘制
之前,我们在蓝杰学习了分形图形的画法,分形不跟其他的程序一样,基础的学习之后,我们发现,分形就是通过简单的循环递归,或者根据某种规律实现一步步的画图,画出一些根据某种特殊关系形成的图形。
拿最基础的我们画过了谢尔宾斯基三角形,和一些简单的通过函数画成的图形来说:
谢尔宾斯基三角形
画谢尔宾斯基三角形的重点是,掌握好每次的递归规律:
首先它的递归规律是,先画出一个大三角形A,然后再取出它的各个边中点连接,之后再把每个边上的三角形当成一个大三角形A,重复上面的步骤。
下面是代码:
/**
* 1.画谢尔宾斯基三角形
* @param count 循环的次数
*/
public void drawSJX(double x1,double y1,double x2,double y2,double x3,double y3,int count){
//第一次循环时画出最大的三角A
if(count==10){
g.drawLine((int)x1, (int)y1,(int) x2,(int) y2);
g.drawLine((int)x1, (int)y1, (int)x3, (int)y3)
g.drawLine((int)x2, (int)y2, (int)x3, (int)y3);
}
//开始递归
if(count>0){
//画大三角A的中位线
g.drawLine((int)(x1+x3)/2, (int)(y1+y3)/2,(int)(x2+x3)/2,(int) (y2+y3)/2);
g.drawLine((int)(x1+x3)/2, (int)(y1+y3)/2,(int)(x2+x1)/2, (int)(y2+y1)/2);
g.drawLine((int)(x2+x3)/2,(int) (y2+y3)/2,(int) (x2+x1)/2, (int)(y2+y1)/2);
//分别把角上三个小三角当作大三角A重复画中位线的步骤
drawSJX(x1,y1,(x2+x1)/2,(y2+y1)/2,(x1+x3)/2,(y1+y3)/2,count-1);
drawSJX((x2+x1)/2,(y2+y1)/2,x2,y2,(x2+x3)/2,(y2+y3)/2,count-1);
drawSJX((x1+x3)/2,(y1+y3)/2,(x2+x3)/2,(y2+y3)/2,x3,y3,count-1);
}
}
之后再在按钮实现类里编写相关画图的方式:
//实现接口中的方法
public void actionPerformed(ActionEvent e) {
String str=e.getActionCommand();
System.out.println("str="+str);
//开始绘制图形
if(str.equals("谢尔宾斯基三角形")){
double x1=100,y1=600;
double x2=600,y2=600;
double x3=(x2+x1)/2,y3=y1-Math.sqrt(3.00d)*(x3-x1);
int count=10;
drawSJX( x1, y1, x2, y2, x3, y3,count);
}else if(str.equals("清空")){
g.clearRect(100, 130, 980, 628);
}
}
简单函数画图
除了通过递归,我们也画过通过一些函数关系式而得到的图像,画这些图形的关键是,掌握好每次画点的变化。
函数图形理论上没有通过递归要画的图像抽象,不需要自己去发现它变化的规律,不用自己定义变化的规则,因为已经知道了确切的关系式,我们需要做的就是通过画一个个点的累积,最后形成一个图形,但是画函数图形的核心也在这里,虽然已经知道给定的变化关系式,但是要画出图形使其可视化,函数点的变化范围必须要在电脑范围内,所以在画点上就要做相应的处理,通过各种扩大缩小点的坐标变换,使其能够展现在电脑屏幕上。
首先是几个比较简单的函数做成的图形,同一个函数使用不同的参数,也可以展现出不同的函数图形:
<!--EndFragment-->
下面是代码:
if(str.equals("函数图形一")){
//float a = 1.5f, b = -1.8f, c = 1.6f, d = 0.9f ;
float a = -1.4f, b = 1.6f, c = 1.0f, d = 0.7f ;
//float a = 1.1f, b = -1.0f, c = 1.0f, d = 1.5f;
//float a = 1.6f, b = -0.6f, c = -1.2f, d = 1.6f;
//float a = 1.3f, b = 1.7f, c = 0.5f, d = 1.4f;
//float a = 1.7f, b = 1.7f, c = 0.06f, d = 1.2f ;
double x1=300;
double y1=300;
int x3,y3;
for(i=0;i<100000;i++){
double x2=Math.sin(a*y1)+c*Math.cos(a*x1);
double y2=Math.sin(b*x1)+d*Math.cos(b*y1);
x3=(int)(x2*100+500);
y3=(int)(y2*100+500);
g.setColor(color);
g.drawLine(x3, y3, x3,y3);
x1=x2;
y1=y2;
}
}else if(str.equals("函数图形二")){
//float a = 1.4f, b = -2.3f, c = 2.4f, d = -2.1f;
//float a = 2.01f, b = -2.53f, c = 1.61f, d = -0.33f;
//float a = -2.7f, b = -0.09f, c = -0.86f, d = -2.2f;
//float a = -2.24f, b = 0.43f, c = -0.65f, d = -2.43f;
float a = -2, b = -2, c = -1.2f, d = 2 ;
double x1=300;
double y1=300;
int x3,y3;
for(i=0;i<100000;i++){
double x2=Math.sin(a*y1)-Math.cos(b*x1);
double y2=Math.sin(c*x1)-Math.cos(d*y1);
x3=(int)(x2*100+500);
y3=(int)(y2*100+500);
g.drawLine(x3, y3, x3,y3);
x1=x2;
y1=y2;
}
}else if(str.equals("ring")){
float a = 1.40f, b = 1.56f, c = 1.40f, d = -6.56f ;
double x1=300;
double y1=300;
int x3,y3;
for(i=0;i<80000;i++){
double x2=d*Math.sin(a*x1)-Math.sin(b*y1);
double y2=c*Math.cos(a*x1)+Math.cos(b*y1);
x3=(int)(x2*40+500);
y3=(int)(y2*40+500);
g.drawLine(x3, y3, x3,y3);
x1=x2;
y1=y2;
}
}
<!--EndFragment-->
其中有好多有趣的图像,像海豚、笑脸之类的,之后可以作为团队分形项目的部分图形。
但是之前考虑过要给图形加上渐变色,使图像更加漂亮,但是渐变色的代码还没有完全搞懂,正在考虑中。
还有一些通过其他函数的迭代,包含概率的一些分形图形的画法,还没有搞懂所以图形还画出……不过之前想通过Java画出著名的笛卡尔心形曲线(感觉比较有趣。。),
但是多次尝试未果……上网查资料时找到了有人画出来的据说3D心形线贴出来看看……(虽然觉得吧不怎么像……
)
<!--EndFragment--><!--EndFragment--><!--EndFragment-->
由于是网上拷的代码,因为源代码不是Java编译而是C++编译的,自己做的只是改了一下使它能在java平台上运行,具体的画法还是没怎么看懂,只是好看就粘来玩玩………………-_- !……………………
<!--EndFragment-->
else if(str.equals("心形曲线")){
double x, y, r;
for (int i1 = 0; i1 < 90; i1++) {
for (int j = 0; j < 90; j++) {
r = Math.PI / 45 * i1 * (1 - Math.sin(Math.PI / 45 * j)) * 18;
x = r * Math.cos(Math.PI / 45 * j) * Math.sin(Math.PI / 45 * i1)
+ 1000/ 2;
y = -r * Math.sin(Math.PI / 45 * j) + 700/ 4;
// 绘制椭圆
g.fillOval((int) x, (int) y, 2, 2);
}
}
}
else if(str.equals("心形曲线2")){
double x, y, r;
for (int i1 = 0; i1 < 90; i1++) {
for (int j = 0; j < 90; j++) {
r = Math.PI / 30 * i1 * (1 - Math.sin(Math.PI / 30 * j)) * 18;
x = r * Math.cos(Math.PI / 30 * j) * Math.sin(Math.PI / 30 * i1)
+ 1000/ 2;
y = -r * Math.sin(Math.PI / 30 * j) + 700/ 4;
// 绘制椭圆
g.fillOval((int) x, (int) y, 2, 2);
}
}
}else if(str.equals("调色")){
//调色板
color = JColorChooser.showDialog(null, "颜色选择",
Color.BLACK);
System.out.println("Color = "+color);
System.out.println("哈哈哈");
}else if(str.equals("清空")){
g.clearRect(100, 130, 980, 628);
}
<!--EndFragment-->
<!--EndFragment-->