这几天一直很忙,申请创新项目,撰写数学建模报告,上亚历山大的各种课。。。。
但程序一直在写,但是成果不大,而且有几个技术难关还没有攻破,但那些都不是事,
今天早上有点时间去图书馆,去了好好的再写了一下双向链表,及双向链表的优化,
还有好好地改进了科赫曲线和雪花的实现,拒绝自己以前的暴力实现,
成功的使用了递归,而且加入了组件来调整颜色和线条的粗细。。。具体代码解释如下:
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.border.SoftBevelBorder;
/**
* 绘制科赫曲线以及科赫雪花
* @author LONG 2013-03-24
*
*/
public class Snow extends JFrame {
private static final long serialVersionUID = 1L;
private static final double PI = Math.PI;//定义全局变量PI
private Dimension di = null; //定义全局变量
private Graphics2D gr = null; //定义为这样便于后面更改线条粗细
private JPanel jp_draw = null; //定义绘画的面板
private double angle = 0.0; //记录传入直线的角度
private int count = 0; //创建计数器变量,用来记录鼠标点击的次数,即递归次数
private JSlider js_red = null; //定义用来改变颜色和粗细的拉杆
private JSlider js_blue = null;
private JSlider js_green = null;
private double apha = PI/3;
private JRadioButton jr_kehe = null;
private JRadioButton jr_snow = null;
private ButtonGroup bg = null; //定义按钮组
private JSlider js_stroke = null;
/**
* 程序入口
* @param args
*/
public static void main(String[] args){
Snow sh = new Snow();
sh.showFrame();
}
public void showFrame(){
this.setTitle("科赫曲线");
Toolkit tl = Toolkit.getDefaultToolkit(); //得到系统工具
di = tl.getScreenSize(); //得到屏幕尺寸
this.setSize(di.width,di.height);
this.setDefaultCloseOperation(3);
jp_draw = new JPanel();
jp_draw.setPreferredSize(new Dimension(di.width*3/4,di.height));//设置画布的大小
this.add(jp_draw,BorderLayout.WEST); //设置画布位置
this.setResizable(false);
jp_draw.setBackground(Color.WHITE);
JLabel jl_red = new JLabel("红色"); //如下三个是用于调整参数的
js_red = new JSlider();
JLabel jl_blue = new JLabel("蓝色");
js_blue = new JSlider();
JLabel jl_green = new JLabel("绿色");
js_green = new JSlider();
JLabel jl_stroke = new JLabel("粗细");
js_stroke = new JSlider();
js_stroke.setValue(2); //将初始粗细设为2
js_stroke.setMaximum(12);
js_red.setMaximum(255); //设置三个拉杆的最大值
js_blue.setMaximum(255);
js_green.setMaximum(255);
JButton jb_ok = new JButton("开始");//定义按钮用来改变递归的深度和初始化递归的深度
JButton jb_reset = new JButton("重置");
jb_ok.setPreferredSize(new Dimension(180,40));
jb_reset.setPreferredSize(new Dimension(180,40));
JPanel jp_b = new JPanel(); //定义存放组件的面板
this.add(jp_b,BorderLayout.CENTER);
jp_b.setBorder(new SoftBevelBorder(0));
jp_b.add(js_red);
jp_b.add(jl_red);
jp_b.add(js_blue);
jp_b.add(jl_blue);
jp_b.add(js_green);
jp_b.add(jl_green);
jp_b.add(js_stroke);
jp_b.add(jl_stroke);
jr_kehe = new JRadioButton("科赫曲线",true);
jr_kehe.setActionCommand("kehe");
jr_snow = new JRadioButton("科赫雪花",false);
jr_snow.setActionCommand("snow");
bg = new ButtonGroup();
bg.add(jr_kehe);
bg.add(jr_snow);
JPanel jp = new JPanel(); //定义存放按钮及选项按钮
jp.setPreferredSize(new Dimension(200,250));
jp_b.add(jp);
FlowLayout fl = new FlowLayout();
jp.setLayout(fl);
fl.setVgap(40);
jp.add(jr_kehe);
jp.add(jr_snow);
jp.add(jb_ok);
JPanel jp_reset = new JPanel();
jp_b.add(jp_reset);
jp_reset.add(jb_reset);
this.setVisible(true);
gr = (Graphics2D) jp_draw.getGraphics();
jb_ok.addMouseListener(new MouseAdapter(){ //给增加递归深度的按钮添加监听器
public void mousePressed(MouseEvent e){
repaint();
count++;
}
public void mouseReleased(MouseEvent e){
init();
}
});
jb_reset.addMouseListener(new MouseAdapter(){ //给重置按钮添加监听器
public void mousePressed(MouseEvent e){
repaint();
count = 0; //将递归深度设为0
}
public void mouseReleased(MouseEvent e){
init(); //执行初始化,并画图
}
});
js_red.addMouseMotionListener(new MouseAdapter(){
//如下三个均是给拉杆添加监听器,使得颜色随着拉杆改变
public void mouseDragged(MouseEvent e){
init();
}
});
js_blue.addMouseMotionListener(new MouseAdapter(){
public void mouseDragged(MouseEvent e){
init();
}
});
js_green.addMouseMotionListener(new MouseAdapter(){
public void mouseDragged(MouseEvent e){
init();
}
});
js_stroke.addMouseMotionListener(new MouseAdapter(){//给粗细添加监听器
public void mouseDragged(MouseEvent e){
init();
}
});
}
/**
* 执行初始化的函数,得到拉杆上的值来设置参数大小
*/
public void init(){
int red = js_red.getValue();
int blue = js_blue.getValue();
int green = js_green.getValue();
int stroke = js_stroke.getValue();
gr.setStroke(new BasicStroke((float)stroke));
gr.setColor(new Color(red,green,blue));
draw(); //调用画的函数
}
public void draw(){
double x1 = jp_draw.getWidth()/4;
double y1 = jp_draw.getHeight()/4;
double x2 = jp_draw.getWidth()*3/4;
double y2 = jp_draw.getHeight()/4;
double x3 = (x1 + x2)/2; //用于计算科赫雪花中会用到的第三个点的x坐标
double y3 = y1 + (x2 - x1)*Math.sqrt(3)/2;//用于计算科赫雪花会用到的第三个点的y坐标
String command = bg.getSelection().getActionCommand();
if(command.equals("kehe")){ //如果选择科赫曲线则执行,否则执行画出科赫雪花的过程
drawKehe(x1,y1,x2,y2,count);
}else{
drawKehe(x1,y1,x2,y2,count);
drawKehe(x2,y2,x3,y3,count);
drawKehe(x3,y3,x1,y1,count);
}
}
/**
* 测试只做一次递归
* @param x1 传入的起始点
* @param y1
* @param x2 传入的终点
* @param y2
* @param deepth 用做递归的深度
*/
public void drawKehe(double x1,double y1,double x2,double y2,int deepth){
if(deepth > 0){
//得到三分点的坐标
double length = Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2));
double sx_1 = x1 + (x2 - x1)/3; //第一个三分点的x坐标
double sy_1 = y1 + (y2 - y1)/3; //第一个三分点的y坐标
double sx_2 = x2 - (x2 - x1)/3; //第二个三分点的x坐标
double sy_2 = y2 - (y2 - y1)/3; //第二个三分点的y坐标
if(sx_2 - sx_1 == 0 ){
angle = PI/2;
}else{
angle = Math.atan((sy_2 - sy_1)/(sx_2 - sx_1)); //得到此时准备画的边的角度
}
if(angle >= 0 && (sx_2 - sx_1) < 0 || angle <= 0 && (sx_2 - sx_1) < 0){
//因为反正切的值范围在-PI/2到PI/2之间,所以根据位置旋转
angle += PI;
}
double sx_3 = sx_1 + Math.cos(angle - apha) * length/3; //算出第三个点的坐标
double sy_3 = sy_1 + Math.sin(angle - apha) * length/3;
drawKehe(x1,y1,sx_1,sy_1,deepth - 1); //以下四个用于递归
drawKehe(sx_1,sy_1,sx_3,sy_3,deepth - 1);
drawKehe(sx_3,sy_3,sx_2,sy_2,deepth - 1);
drawKehe(sx_2,sy_2,x2,y2,deepth - 1);
}else{
gr.drawLine((int)x1, (int)y1, (int)x2, (int)y2); //执行划线功能
}
}
}
代码就是上面那么多,但是呢,就是我也感觉太长了,
我看起来烦,但是如果对于诸君有用呢,那是我最大的欢乐了。。。嘻嘻
啥话不说,上几张图瞧瞧结果哈!
如上所示是各种图片。预览有点问题,大家可以在附件看一下。。。。嘻嘻