# 用三阶贝塞尔曲线拟合圆

#### 求解魔法数值

##### 证明及推算

(3/4)d = r - r·cos(θ/2) ····················· ①

d = l·sin(θ/2) ································ ②

sin2α = 2·sinα·cosα
cos2α = (cosα)^2 - (sinα)^2 = 1 - 2·(sinα)^2

#### 用贝塞尔曲线画圆关键代码

``````……
private Paint mPaint;
private Path path = new Path();
private float[] mData = new float[8];               // 顺时针记录绘制圆形的四个数据点
private float[] mCtrl = new float[16];              // 顺时针记录绘制圆形的八个控制点
private static final float C = 0.552284749831f;     // 用来计算绘制圆形贝塞尔曲线控制点的位置的常数

private void initData() {
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(8);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setTextSize(60);
// 初始化数据点
mData[0] = 0;

mData[3] = 0;

mData[4] = 0;

mData[7] = 0;

// 初始化控制点
float mDifference = mCircleRadius * C;  //圆形的控制点与数据点的差值
mCtrl[0]  = mData[0]+ mDifference;
mCtrl[1]  = mData[1];

mCtrl[2]  = mData[2];
mCtrl[3]  = mData[3]+ mDifference;

mCtrl[4]  = mData[2];
mCtrl[5]  = mData[3]- mDifference;

mCtrl[6]  = mData[4]+ mDifference;
mCtrl[7]  = mData[5];

mCtrl[8]  = mData[4]- mDifference;
mCtrl[9]  = mData[5];

mCtrl[10] = mData[6];
mCtrl[11] = mData[7]- mDifference;

mCtrl[12] = mData[6];
mCtrl[13] = mData[7]+ mDifference;

mCtrl[14] = mData[0]- mDifference;
mCtrl[15] = mData[1];
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mCenterX, mCenterY);   // 将坐标系移动到画布中央
canvas.scale(1,-1);                       // 翻转Y轴

drawAuxiliaryLine(canvas);

// 绘制贝塞尔曲线
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(6);
path.moveTo(mData[0],mData[1]);

path.cubicTo(mCtrl[0],  mCtrl[1],  mCtrl[2],  mCtrl[3],     mData[2], mData[3]);
path.cubicTo(mCtrl[4],  mCtrl[5],  mCtrl[6],  mCtrl[7],     mData[4], mData[5]);
path.cubicTo(mCtrl[8],  mCtrl[9],  mCtrl[10], mCtrl[11],    mData[6], mData[7]);
path.cubicTo(mCtrl[12], mCtrl[13], mCtrl[14], mCtrl[15],    mData[0], mData[1]);

canvas.drawPath(path, mPaint);
}

// 绘制辅助线
private void drawAuxiliaryLine(Canvas canvas) {
// 绘制数据点和控制点
mPaint.setColor(Color.GRAY);
mPaint.setStrokeWidth(10);

for (int i=0; i<8; i+=2){
canvas.drawPoint(mData[i],mData[i+1], mPaint);
}
for (int i=0; i<16; i+=2){
canvas.drawPoint(mCtrl[i], mCtrl[i+1], mPaint);
}

// 绘制辅助线
mPaint.setStrokeWidth(4);
for (int i=2, j=2; i<8; i+=2, j+=4){
canvas.drawLine(mData[i],mData[i+1],mCtrl[j],mCtrl[j+1],mPaint);
canvas.drawLine(mData[i],mData[i+1],mCtrl[j+2],mCtrl[j+3],mPaint);
}
canvas.drawLine(mData[0],mData[1],mCtrl[0],mCtrl[1],mPaint);
canvas.drawLine(mData[0],mData[1],mCtrl[14],mCtrl[15],mPaint);
}
``````

### 推荐阅读更多精彩内容

• 根据贝塞尔曲线的知识，我们知道三阶贝塞尔曲线的参数方程如下，其中A、B、C、D为四个控制点坐标，P(t)表示曲线上...
Henry_Dong阅读 2,763评论 2 4
• 谈谈贝塞尔曲线 最近在做项目的时候，需要用到一个动画，非常简单的动画，简单到就是直接对一个View做平移… 然而虽...
雨润听潮阅读 5,498评论 1 16
• APK下载地址 1.贝塞尔曲线 以下公式中：B(t)为t时间下 点的坐标；P0为起点,Pn为终点,Pi为控制点 一...
小鱼爱记录阅读 3,521评论 2 27
• 最近在做项目的时候，需要用到一个动画，非常简单的动画，简单到就是直接对一个View做平移... 然而虽然动画简单，...
IAMDAEMON阅读 3,793评论 12 69
• 本文主要内容为贝塞尔曲线原理解析并用 SurfaceView 实现其展示动画 关于SurfaceView 的使用，...
涤生_Woo阅读 12,502评论 5 92
• “今天晚上你想吃什么” “随便吧，什么都行” 在快下班的时候，妈妈打来电话让我“点菜”，每次我都很头痛，只点“随便...
树上的一条鱼阅读 522评论 0 1
• 很喜欢这样一句话：活得简单，才会活得自由；活得自由，才会获得幸福。 在当今这个处处看起来光鲜亮丽、五光十色的世界里...
zouxiaopei阅读 2,400评论 0 2
• 八点的钟声即将敲响，我却还在自己的思绪里无法自拔…… 咳咳咳，下面进入伪正题 为什么给文章取这个名字？（内❤️旁白...
倾风徐来阅读 275评论 1 3