任意调节的贝塞尔曲线

         最近电脑老是出问题,保存在电脑中的东西一直积压的也够多了,怕的是电脑那天坏了,还真不知道自己以前写过的东西,所以决定还是发上博客好点,以后也有点回念。

          看了看写过的东西,贝塞尔曲线,这个挺好玩的,所以。。。。

记得做贝塞尔曲线时,自己看过许多资料,但是看的东西,一旦在电脑中编写起来,种种困难就来了。说绘制一条直线挺容易,直接g.drawLine(),就来了。但是绘制曲线怎么做?



 上面是我绘制的曲线,黄色的点,点击FF按钮就可以调节,得到自己想要的曲线。拖动鼠标,曲线相应的产生不同的幅度。实现过程如下:

贝塞尔曲线是由一个二项式来,构建二项式

B(t) = \sum_{i=0}^n {n \choose i} Pi_{}(1-t)^{n-i} t^i={n \choose 0} P0_{}(1-t)^n t^0+{n \choose 1} P1_{}(1-t)^{n-1} t^1+...+{n \choose n-1} Pn-1_{}(1-t)^1 t^{n-1}+{n \choose n} Pn_{}(1-t)^0 t^n,t\in[0,1]
首先构建n的阶乘:
/**
* 建一个 n 阶乘的函数
* @param fenzi
* @return
*/
public int cn(int fenzi) {

if (fenzi == 1 || fenzi == 0)
return 1;
else if (fenzi < 0) {
System.out.println("N_1输入错误");
return 1;
} else
return fenzi * cn(fenzi - 1);
}
 接着构建一个n*..(n-m+1)的函数:
public int cmn(int n, int m) {

if (n < m && pan == 0 || n < 0 || m < 0) {
System.out.println("N_m输入错误");
return 1;
} else {
pan = 1;
}
if (m == 0 || n == 1 || n == 0) {
return 1;
} else {
m--;
return n * cmn(n - 1, m);
}
}
 这样我们就能得到我们想要的 项,再次构造(1-t)*t 的n-m次方与m次方项
实现如下:
public double Cy(double t, int count, int cou) {
if (cou == 0)
return cmn(count, cou) / cn(cou) * Math.pow(t, count - cou)
* Math.pow(1 - t, cou) * xy[0][1];
else {
s = (cmn(count, cou) / cn(cou) * Math.pow(t, count - cou)
* Math.pow(1 - t, cou) * xy[cou][1])
+ Cy(t, count, cou - 1);
return s;
}
}
 当构造完成后就开始怎么绘制贝塞尔曲线
1.对于图上的黄点,我是用数组(注意开始第一点与第二点即最后一点)保存的,让后绘制成方形。
2.曲线是由点构成,将点保存到队列中
3.根据3个点(数组中)+t值得变化可以产生一条曲线
4.鼠标移动,画布不断绘制,数组中的一个值不断变化,产生不同的弧度
数组的保存:
private static int n = -1, pan = 0;
    private double t = 0, s = 0;
    private int[][] xy = new int[100][2];// 差值点的保存
    private int[][] xy0 = new int[1][2];// 最后一个点的保存
    private boolean reless = false, atom = false;// 差值点的移动和原点的移动
    private Point p, p1;
x2 = e.getX();//获取鼠标中的释放点
y2 = e.getY();

// 保存初值点
if (atom) {
bs.x = x2;
bs.y = y2;
atom = false;
return;
} else if (bs.count == 1 && !bs.change && !atom) {
bs.savelist.clear();
bs.rectlist.clear();
xy[0][0] = x1;
xy[0][1] = y1;
xy0[0][0] = x2;
xy0[0][1] = y2;

p = new Point(xy[0][0], xy[0][1]);
bs.savelist.add(p);// 保存第一点
bs.rectlist.add(p);

p1 = new Point(xy0[0][0], xy0[0][1]);// 保存第二点
bs.savelist.add(p1);
bs.rectlist.add(p1);
} else if (bs.count > 1 && !atom) {
bs.savelist.clear();
// 画差值点位置
if (!bs.change) {
xy[bs.count - 1][0] = x2;
xy[bs.count - 1][1] = y2;
}
bs.rectlist.clear();
for (int i = 0; i < bs.count; i++) {
p = new Point(xy[i][0], xy[i][1]);
bs.rectlist.add(p);
}
p = new Point(xy0[0][0], xy0[0][1]);// 加上最后的点
bs.rectlist.add(p);
}
 将产生的点保存到数组中
// 清空队列
bs.savelist.clear();
xo = -1;
yo = -1;
while (t < 1) {

xc1 = (int) (Cx(t, bs.count, bs.count - 2)
+ cmn(bs.count, bs.count - 1) / cn(bs.count - 1)
* Math.pow(t, 1) * Math.pow(1 - t, bs.count - 1) * x2 + Math
.pow(1 - t, bs.count)
* xy0[0][0]);
yc1 = (int) (Cy(1-t, bs.count, bs.count - 2)
+ cmn(bs.count, bs.count - 1) / cn(bs.count - 1)
* Math.pow(1-t, 1) * Math.pow(t, bs.count - 1) * y2 + Math
.pow(t, bs.count)
* xy0[0][1]);
// 去除重合的点
if (xo == -1 && yo == -1) {
xo = xc1;
yo = yc1;
p = new Point(xc1, yc1);
bs.savelist.add(p);
} else if (xo != xc1 || yo != yc1) {
p = new Point(xc1, yc1);
bs.savelist.add(p);
}
xo = xc1;
yo = yc1;
t += 0.0001;
}
t = 0;
 在这里当t 的变化很小时如t +=0.0001,每次t的变化只有万分之一,因此,对加入队列中的重复点我们要进行选择的加入队列中,减少不必要的空间,绘制速度加快。每次绘制是都要清空原队列bs.savelist.clear();
t=0的初始化。
 

 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值