科赫曲线,我想讲当时我写的两个方法,当时也想了好久,其实究其原因还是自己的畏难情绪和缺乏耐心。
科赫曲线就是通过递归来出其曲线,关键是找到规律。
第一个方法,我只想给出源代码,因为这是我糊里糊涂写出来的,我也不知道从何说起。
/**
* 科赫曲线
* @author 剑晨
*
*/
public class DrawKoch extends JFrame{
double angle=Math.PI/3;//角度60
Graphics g;//画布
public static void main(String args []){//程序入口
DrawKoch dk= new DrawKoch();
dk.init();
}
public void init(){
setSize(800,800);
setDefaultCloseOperation(3);
setVisible(true);
}
public void paint(Graphics g){
super.paint(g);
draw(100,400,700,400,4,g,Math.PI/3);
}
/**
* 画曲线方法
* @param x1 y1 x2 y2坐标
* @param deepth 递归深度
* @param g 画布
* @param angle 角度
*/
public void draw(int x1,int y1,int x2,int y2,int deepth,Graphics g,double angle){
if(deepth<=0){//递归深度为0时画线
g.drawLine( x1,y1,x2,y2);
}
else{
//第1个三分点的坐标
int x3=x1+(x2-x1)/3;
int y3=y1+(y2-y1)/3;
//第2个三分点的坐标
int x4=x1+2*(x2-x1)/3;
int y4=y1+2*(y2-y1)/3;
//通过线长和角度计算两个三分点中间点的坐标
int l=(int) Math.sqrt((x4-x3)*(x4-x3)+(y4-y3)*(y4-y3));
int x5=(int) (x3+l*Math.cos(angle));
int y5=(int) (y3- l*Math.sin(angle));
//递归
draw(x1,y1,x3,y3,deepth-1, g,angle);
draw(x3,y3,x5,y5,deepth-1,g,angle+Math.PI/3);
draw(x5,y5,x4,y4,deepth-1, g,angle-Math.PI/3);
draw(x4,y4,x2,y2,deepth-1, g,angle);
}
}
}
效果图如下:
[img]http://dl2.iteye.com/upload/attachment/0086/1353/71ab09e1-6cbc-39dd-a96a-33a0ae25ec65.png[/img]
第二个方法,这是我讲一下我写的过程的方法。同样是递归,中间点的计算也是通过线长和角度计算。不过我事先并没有考虑别的,只是按照找到的规律递归,如下代码那样,并没考虑这样是否有角度的错误,只是先画出来再说,然后再不断改正。
/**
* 画科赫的方法
* @param x1 y1 x2 y2 坐标
* @param deepth 递归深度
*/
public void draw(double x1,double y1,double x2,double y2,int deepth){
if(deepth<=1){//深度为1,画线
g.drawLine((int)x1,(int)y1,(int)x2,(int)y2);
}else{
//第一个三分点
double x3=x1+(x2-x1)/3;
double y3=y1+(y2-y1)/3;
//第二个三分点
double x4=x1+2*(x2-x1)/3;
double y4=y1+2*(y2-y1)/3;
//顶点
double l=Math.sqrt((x4-x3)*(x4-x3)+(y4-y3)*(y4-y3));
double angle=Math.atan((y4-y3)/(x4-x3));
double x5=x3+Math.cos(angle-Math.PI/3)*l;
double y5=y3+Math.sin(angle-Math.PI/3)*l;
//递归
draw(x1,y1,x3,y3,deepth-1);
draw(x3,y3,x5,y5,deepth-1);
draw(x5,y5,x4,y4,deepth-1);
draw(x4,y4,x2,y2,deepth-1);
}
}
果然,成功永远不可能那么简单。他出现了错误,如下图。
[img]http://dl2.iteye.com/upload/attachment/0086/1358/12522c09-6c05-3120-8795-ffb71ebe0a17.png[/img]
然后我就通过改变递归深度来观察出现错误点的规律,然后发现了规律,就加了一段代码。只是一句,却改变了结果。
/**
* 画科赫的方法
* @param x1 y1 x2 y2 坐标
* @param deepth 递归深度
*/
public void draw(double x1,double y1,double x2,double y2,int deepth){
if(deepth<=1){//深度为1,画线
g.drawLine((int)x1,(int)y1,(int)x2,(int)y2);
}else{
//第一个三分点
double x3=x1+(x2-x1)/3;
double y3=y1+(y2-y1)/3;
//第二个三分点
double x4=x1+2*(x2-x1)/3;
double y4=y1+2*(y2-y1)/3;
//顶点
double l=Math.sqrt((x4-x3)*(x4-x3)+(y4-y3)*(y4-y3));
double angle=Math.atan((y4-y3)/(x4-x3));
//特别点的处理(新加的一句代码!!!!!!!!!!!!!!!!!!!!)
if(x4<x3&&y4<=y3||x4<x3&&y4>=y3){
angle=angle+Math.PI;
}
double x5=x3+Math.cos(angle-Math.PI/3)*l;
double y5=y3+Math.sin(angle-Math.PI/3)*l;
//递归
draw(x1,y1,x3,y3,deepth-1);
draw(x3,y3,x5,y5,deepth-1);
draw(x5,y5,x4,y4,deepth-1);
draw(x4,y4,x2,y2,deepth-1);
}
}
效果图如下。
[img]http://dl2.iteye.com/upload/attachment/0086/1362/ceaf88cd-3e71-31d9-8abd-a0c25be0653f.png[/img]