三阶贝塞尔曲线选点_三次贝塞尔曲线绘制算法(优化过)

package

{

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.Shape;

import flash.display.Sprite;

import flash.events.Event;

import flash.events.MouseEvent;

import flash.geom.Point;

import flash.geom.Rectangle;

/**

*贝塞尔曲线绘制算法

* @author boycy815*/

public class Main extends Sprite

{

/*C30到C33的值总共才4个直接枚举*/

private const C30:int = 1;

private const C31:int = 3;

private const C32:int = 3;

private const C33:int = 1;

/*定义曲线上点的个数(包括两端)*/

private const LENGTH:int = 10000;

/*btC30到btC33分别是R0 R1 R2 R3四个点当t取前三个值时的权重值*/

private var btC30:Vector. = new Vector.(3);

private var btC31:Vector. = new Vector.(3);

private var btC32:Vector. = new Vector.(3);

private var btC33:Vector. = new Vector.(3);

/*画点的位图*/

private var data:BitmapData;

private var map:Bitmap;

/*用于连接四个点的四条直线*/

private var lin:Shape;

/*分别是四个点的显示对象*/

private var ct0:Sprite;

private var ct1:Sprite;

private var ct2:Sprite;

private var ct3:Sprite;

public function Main():void

{

if (stage) init();

else addEventListener(Event.ADDED_TO_STAGE, init);

}

private function init(e:Event = null):void

{

removeEventListener(Event.ADDED_TO_STAGE, init);

/*初始化位图和一些显示对象*/

data = new BitmapData(800, 600,false);

map = new Bitmap(data);

this.addChild(map);

lin = new Shape();

this.addChild(lin);

ct0 = new Sprite();

ct0.buttonMode = true;

ct0.graphics.lineStyle(0, 0x00000);

ct0.graphics.beginFill(0xffffff);

ct0.graphics.drawCircle(0, 0, 5);

ct0.graphics.endFill();

ct0.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);

ct0.addEventListener(MouseEvent.MOUSE_UP, mouseUp);

this.addChild(ct0);

ct1 = new Sprite();

ct1.buttonMode = true;

ct1.graphics.lineStyle(0, 0x00000);

ct1.graphics.beginFill(0xffffff);

ct1.graphics.drawCircle(0, 0, 5);

ct1.graphics.endFill();

ct1.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);

ct1.addEventListener(MouseEvent.MOUSE_UP, mouseUp);

this.addChild(ct1);

ct2 = new Sprite();

ct2.buttonMode = true;

ct2.graphics.lineStyle(0, 0x00000);

ct2.graphics.beginFill(0xffffff);

ct2.graphics.drawCircle(0, 0, 5);

ct2.graphics.endFill();

ct2.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);

ct2.addEventListener(MouseEvent.MOUSE_UP, mouseUp);

this.addChild(ct2);

ct3 = new Sprite();

ct3.buttonMode = true;

ct3.graphics.lineStyle(0, 0x00000);

ct3.graphics.beginFill(0xffffff);

ct3.graphics.drawCircle(0, 0, 5);

ct3.graphics.endFill();

ct3.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);

ct3.addEventListener(MouseEvent.MOUSE_UP, mouseUp);

this.addChild(ct3);

/*初始化计算的一些准备数据*/

btInit();

/*默认进行第一次定位和绘制*/

ct0.x = 100;

ct0.y = 100;

ct1.x = 700;

ct1.y = 100;

ct2.x = 700;

ct2.y = 500;

ct3.x = 100;

ct3.y = 500;

lin.graphics.lineStyle(0, 0x000000);

lin.graphics.moveTo(ct0.x, ct0.y);

lin.graphics.lineTo(ct1.x, ct1.y);

lin.graphics.lineTo(ct2.x, ct2.y);

lin.graphics.lineTo(ct3.x, ct3.y);

drawBezier3(new Point(ct0.x, ct0.y), new Point(ct1.x, ct1.y), new Point(ct2.x, ct2.y), new Point(ct3.x, ct3.y));

}

/*按钮按下便开始可以拖动点*/

private function mouseDown(e:MouseEvent):void

{

e.target.startDrag();

stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);

}

/*鼠标移动便不断绘制曲线*/

private function mouseMove(e:MouseEvent):void

{

/*绘制连接四个点的直线*/

lin.graphics.clear();

lin.graphics.lineStyle(0, 0x000000);

lin.graphics.moveTo(ct0.x, ct0.y);

lin.graphics.lineTo(ct1.x, ct1.y);

lin.graphics.lineTo(ct2.x, ct2.y);

lin.graphics.lineTo(ct3.x, ct3.y);

/*绘制曲线*/

data.fillRect(new Rectangle(0, 0, 800, 600), 0xffffffff);

drawBezier3(new Point(ct0.x, ct0.y), new Point(ct1.x, ct1.y), new Point(ct2.x, ct2.y), new Point(ct3.x, ct3.y));

}

/*释放按钮停止拖动*/

private function mouseUp(e:MouseEvent):void

{

var n:int;

e.target.stopDrag();

stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);

}

/***********算法部分**********/

/*初始化计算所需数据,主要是btC30到btC33*/

private function btInit():void

{

var add:Number;

/*由于t的值域为[0,1],要绘制LENGTH个点,则必须计算出每次t的增量*/

add = 1.0 / (LENGTH – 1.0);

/*三次白赛尔曲线Ri的权重公式为:C3i * pow( t – 1 , 3 – i ) * pow( t , i )

*前三次t的值分别为0,add,add*2

*则代入公式就能求出R0 R1 R2 R3的前三次的权重值

**/

btC30[0] = 1;

btC30[1] = C30 * Math.pow(1 – add, 3);

btC30[2] = C30 * Math.pow(1 – add * 2, 3);

btC31[0] = 0;

btC31[1] = C31 * Math.pow(1 – add, 2) * add;

btC31[2] = C31 * Math.pow(1 – add * 2, 2) * add * 2;

btC32[0] = 0;

btC32[1] = C32 * (Math.pow(add, 2) – Math.pow(add, 3));

btC32[2] = C32 * (Math.pow(add * 2, 2) – Math.pow(add * 2, 3));

btC33[0] = 0;

btC33[1] = C33 * Math.pow(add, 3);

btC33[2] = C33 * Math.pow(add * 2, 3);

}

/*利用准备好的初始数据,通过递推方法求出四个点对应的贝塞尔曲线上每个点的坐标,并绘制

*计算中用到多项式批量计算优化策略,上一篇博文中有提及具体的方法和思想

**/

private function drawBezier3(p0:Point,p1:Point,p2:Point,p3:Point):void

{

/*qun_x和qun_x本别为x坐标和y坐标的临时数据数组*/

var qun_x:Vector. = new Vector.(3);

var qun_y:Vector. = new Vector.(3);

/*dd_x和dd_y分别为x坐标的多项式和y坐标式求导三次后得到的常数*/

var dd_x:Number;

var dd_y:Number;

var n:int;

/*计算前三次种子数据*/

dd_x = 6 * (3 * p1.x – 3 * p2.x – p0.x + p3.x) / Math.pow(LENGTH – 1.0, 3);

qun_x[0] = p0.x * btC30[0] + p1.x * btC31[0] + p2.x * btC32[0] + p3.x * btC33[0];

dd_y = 6 * (3 * p1.y – 3 * p2.y – p0.y + p3.y) / Math.pow(LENGTH – 1.0, 3);

qun_y[0] = p0.y * btC30[0] + p1.y * btC31[0] + p2.y * btC32[0] + p3.y * btC33[0];

data.setPixel(qun_x[0], qun_y[0], 0x000000);

qun_x[1] = p0.x * btC30[1] + p1.x * btC31[1] + p2.x * btC32[1] + p3.x * btC33[1];

qun_x[0] = qun_x[1] – qun_x[0];

qun_y[1] = p0.y * btC30[1] + p1.y * btC31[1] + p2.y * btC32[1] + p3.y * btC33[1];

qun_y[0] = qun_y[1] – qun_y[0];

data.setPixel(qun_x[1], qun_y[1], 0x000000);

qun_x[2] = p0.x * btC30[2] + p1.x * btC31[2] + p2.x * btC32[2] + p3.x * btC33[2];

qun_x[1] = qun_x[2] – qun_x[1];

qun_x[0] = qun_x[1] – qun_x[0];

qun_y[2] = p0.y * btC30[2] + p1.y * btC31[2] + p2.y * btC32[2] + p3.y * btC33[2];

qun_y[1] = qun_y[2] – qun_y[1];

qun_y[0] = qun_y[1] – qun_y[0];

data.setPixel(qun_x[2], qun_y[2], 0x000000);

/*进行递推计算的循环*/

for (n = 3; n < LENGTH; n++)

{

qun_x[0] += dd_x;

qun_x[1] += qun_x[0];

qun_x[2] += qun_x[1];

qun_y[0] += dd_y;

qun_y[1] += qun_y[0];

qun_y[2] += qun_y[1];

data.setPixel(qun_x[2], qun_y[2], 0x000000);

}

}

}

}

    原文作者:每天开心的进步
    原文地址: https://blog.csdn.net/weixin_35718351/article/details/114478517
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞