`
wojiaolongyinong
  • 浏览: 73078 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

科赫再来。。闲言碎语

    博客分类:
  • Java
 
阅读更多

   这几天一直很忙,申请创新项目,撰写数学建模报告,上亚历山大的各种课。。。。

但程序一直在写,但是成果不大,而且有几个技术难关还没有攻破,但那些都不是事,

今天早上有点时间去图书馆,去了好好的再写了一下双向链表,及双向链表的优化,

还有好好地改进了科赫曲线和雪花的实现,拒绝自己以前的暴力实现,

成功的使用了递归,而且加入了组件来调整颜色和线条的粗细。。。具体代码解释如下:

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);	//执行划线功能
		}	
	}
}

 代码就是上面那么多,但是呢,就是我也感觉太长了,

我看起来烦,但是如果对于诸君有用呢,那是我最大的欢乐了。。。嘻嘻

啥话不说,上几张图瞧瞧结果哈!



 

 

 

 

 

 

如上所示是各种图片。预览有点问题,大家可以在附件看一下。。。。嘻嘻

 

  • 大小: 35.4 KB
  • 大小: 36 KB
  • 大小: 37.8 KB
  • 大小: 34.9 KB
  • 大小: 28 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics