贝塞尔曲线N阶实现-德卡斯特里奥算法(De Casteljau’s Algorithm)

贝塞尔曲线很多客户端已经自行集成,安卓ios或是web,今天基于算法动手实现一次,今天只放源码,暂时不做说明了(还要加班,--~),源码在下面,直接看也能看懂

德卡斯特里奥算法的基础就是在向量AB上选择一个点C,使得C分向量ABu:1-u(也就是∣AC:AB= u)。给定点AB的坐标以及uu[0,1])的值,点C的坐标便为:C = A + (B - A) * u = (1 - u) * A + B * u

 

我本来是做安卓的,不过安卓调试太慢了,我就用html实现了下 复制代码直接到txt改后缀html就可以看到效果了,其他语言和逻辑可以通用

<!DOCTYPE HTML>
<html>
<body>

<canvas id="BddCanvas" width="1000" height="500" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
贝塞尔曲线N阶算法演示
<script type="text/javascript">


<!-- 拿到画布 -->
var c=document.getElementById("BddCanvas")
<!-- 拿到绘制环境 -->
var canvasRC2D=c.getContext("2d")

<!-- 测试4个控制点 -->
var points_control=new Array(
{x:10,y:10},
{x:150,y:400},
{x:300,y:40},
{x:800,y:300})


<!-- 先展示折线效果 -->
canvasRC2D.moveTo(points_control[0].x,points_control[0].y)
canvasRC2D.lineTo(points_control[1].x,points_control[1].y)
canvasRC2D.lineTo(points_control[2].x,points_control[2].y)
canvasRC2D.lineTo(points_control[3].x,points_control[3].y)


<!-- 系统自带实现三阶贝塞尔的效果 --> 
canvasRC2D.moveTo(points_control[0].x,points_control[0].y)
canvasRC2D.bezierCurveTo(
points_control[1].x,points_control[1].y,
points_control[2].x,points_control[2].y,
points_control[3].x,points_control[3].y
)
canvasRC2D.stroke() 


//自己按原理算法实现
<!-- //AB两点间符合要求的c 取向量 算法基础∣AC∣:∣AB∣= u (u∈[0,1]) C = A + (B - A) * u = (1 - u) * A + B * u -->
//重新开始一条路径 采用红色和往下一点的起点+40作为区分
canvasRC2D.beginPath()
canvasRC2D.strokeStyle="red"
canvasRC2D.lineWidth=3


points_control=new Array(
{x:10,y:10+40},
{x:150,y:400+40},
{x:300,y:40+40},
{x:800,y:300+40})

var x_start = points_control[0].x
var y_start = points_control[0].y

canvasRC2D.moveTo(x_start,y_start)

 //动态比例 越小曲线越细腻u = 0.01

var time = 0
for (var u=0;u<=1;u+=0.01){
	for (var i=1;i<points_control.length;++i){

		for (var j=0;j<points_control.length-i;j++){
			console.log("time:"+time++);
			if(i == 1){
			
				<!-- //根据上面公式 -->
				points_control[j].x = parseInt((1 - u) * points_control[j].x + points_control[j + 1].x * u)
 				points_control[j].y = parseInt((1 - u) * points_control[j].y + points_control[j + 1].y * u)
		
			    continue
				
			}
			<!-- //i != 1时,通过上一次迭代的结果计算 -->
			points_control[j].x = points_control[j].x * (1 - u) + points_control[j + 1].x * u
			points_control[j].y = points_control[j].y * (1 - u) + points_control[j + 1].y * u
				
		
}
	console.log("计算结果:x"+x_start);
	//绘制线条
	//canvasRC2D.moveTo(x_start,y_start)
	canvasRC2D.lineTo(points_control[0].x,points_control[0].y)
	//生成一个新点
	x_start = points_control[0].x
 
	y_start = points_control[0].y
	
	canvasRC2D.stroke()
	
}
}

<!-- //用延时展现绘制过程和外层循坏 多阶展现-->
points_control=new Array(
{x:10,y:10+80},
{x:150,y:400+80},
{x:300,y:40+80},
{x:800,y:300+80},	
{x:20,y:331},	
{x:80,y:80},	
{x:500,y:150},	
{x:31,y:66},	
{x:400,y:1},	
{x:31,y:30},	
{x:800,y:2},	
{x:400,y:500},	
{x:1000,y:1})

x_start = points_control[0].x
y_start = points_control[0].y

canvasRC2D.beginPath()
canvasRC2D.strokeStyle="green"
canvasRC2D.lineWidth=3




canvasRC2D.moveTo(x_start,y_start)

	<!-- for (var i=0;i<points_control.length;i++){ -->
		<!-- canvasRC2D.lineTo(points_control[i].x,points_control[i].y) -->
	<!-- } -->
	<!-- canvasRC2D.moveTo(x_start,y_start) -->

u=0

var interval=self.setInterval("clock()",30)
function clock() { 

	for (var i=1;i<points_control.length;++i){

		for (var j=0;j<points_control.length-i;j++){
		
			if(i == 1){
			
				<!-- //根据上面公式 -->
				points_control[j].x = parseInt((1 - u) * points_control[j].x + points_control[j + 1].x * u)
 				points_control[j].y = parseInt((1 - u) * points_control[j].y + points_control[j + 1].y * u)
		
			    continue
				
			}
			<!-- //i != 1时,通过上一次迭代的结果计算 -->
			points_control[j].x = points_control[j].x * (1 - u) + points_control[j + 1].x * u
			points_control[j].y = points_control[j].y * (1 - u) + points_control[j + 1].y * u

	}

	//绘制线条
	//canvasRC2D.moveTo(x_start,y_start)
	canvasRC2D.lineTo(points_control[0].x,points_control[0].y)
	//生成一个新点
	x_start = points_control[0].x
 
	y_start = points_control[0].y
	
	canvasRC2D.stroke()
	
	u+=0.001
	
	
	if(u>=1){
	clearInterval(interval)
}
}
}


</script>
</body>
</html>

//核心部分讲解

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值