Android 使用贝塞尔曲线将多点连成一条平滑的曲线

来源:互联网 发布:数据预处理方法和步骤 编辑:程序博客网 时间:2024/04/29 11:45

本文主要讲解怎么用贝塞尔曲线将多点连成一条平滑的曲线,若不了解贝塞尔曲线的同学可以查看这里

先看效果

不带辅助线
带辅助线

确定控制点

使用贝塞尔曲线,我们就要先找出它的控制点,笔者Google后发现了此篇文章,文章中列出了找出控制点的公式

找出控制点

注意:
1.公式中的当前点是线段的起点,文中的当前点指的是线段的终点
2.公式中的a,b代表曲线的弯曲指数,越大代表曲线越弯,一般设置0.16

从公式中可以发现,确定当前点的控制点,需要用到当前点的前两个点和下一个点四个点,那么当当前点是第一个点,第二个点和最后一个点时,我们就无法获取到全部点,那篇文章中又指出

找出控制点

第二种方法过于复杂,文中使用的是第一中方法,即用当前点的值表示无法获取到的点的值,
下面列出代码:

    private void measurePath() {        //保存曲线路径        mPath = new Path();        //保存辅助线路径        mAssistPath = new Path();        float prePreviousPointX = Float.NaN;        float prePreviousPointY = Float.NaN;        float previousPointX = Float.NaN;        float previousPointY = Float.NaN;        float currentPointX = Float.NaN;        float currentPointY = Float.NaN;        float nextPointX;        float nextPointY;        final int lineSize = mPointList.size();        for (int valueIndex = 0; valueIndex < lineSize; ++valueIndex) {            if (Float.isNaN(currentPointX)) {                Point point = mPointList.get(valueIndex);                currentPointX = point.x;                currentPointY = point.y;            }            if (Float.isNaN(previousPointX)) {                //是否是第一个点                if (valueIndex > 0) {                    Point point = mPointList.get(valueIndex - 1);                    previousPointX = point.x;                    previousPointY = point.y;                } else {                    //是的话就用当前点表示上一个点                    previousPointX = currentPointX;                    previousPointY = currentPointY;                }            }            if (Float.isNaN(prePreviousPointX)) {                //是否是前两个点                if (valueIndex > 1) {                    Point point = mPointList.get(valueIndex - 2);                    prePreviousPointX = point.x;                    prePreviousPointY = point.y;                } else {                    //是的话就用当前点表示上上个点                    prePreviousPointX = previousPointX;                    prePreviousPointY = previousPointY;                }            }            // 判断是不是最后一个点了            if (valueIndex < lineSize - 1) {                Point point = mPointList.get(valueIndex + 1);                nextPointX = point.x;                nextPointY = point.y;            } else {                //是的话就用当前点表示下一个点                nextPointX = currentPointX;                nextPointY = currentPointY;            }            if (valueIndex == 0) {                // 将Path移动到开始点                mPath.moveTo(currentPointX, currentPointY);                mAssistPath.moveTo(currentPointX, currentPointY);            } else {                // 求出控制点坐标                final float firstDiffX = (currentPointX - prePreviousPointX);                final float firstDiffY = (currentPointY - prePreviousPointY);                final float secondDiffX = (nextPointX - previousPointX);                final float secondDiffY = (nextPointY - previousPointY);                final float firstControlPointX = previousPointX + (lineSmoothness * firstDiffX);                final float firstControlPointY = previousPointY + (lineSmoothness * firstDiffY);                final float secondControlPointX = currentPointX - (lineSmoothness * secondDiffX);                final float secondControlPointY = currentPointY - (lineSmoothness * secondDiffY);                //画出曲线                mPath.cubicTo(firstControlPointX, firstControlPointY, secondControlPointX, secondControlPointY,                        currentPointX, currentPointY);                //将控制点保存到辅助路径上                mAssistPath.lineTo(firstControlPointX, firstControlPointY);                mAssistPath.lineTo(secondControlPointX, secondControlPointY);                mAssistPath.lineTo(currentPointX, currentPointY);            }            // 更新值,            prePreviousPointX = previousPointX;            prePreviousPointY = previousPointY;            previousPointX = currentPointX;            previousPointY = currentPointY;            currentPointX = nextPointX;            currentPointY = nextPointY;        }        mPathMeasure = new PathMeasure(mPath, false);    }

参考博客 http://blog.csdn.net/u011102153/article/details/52039794 部分源码拷贝了该项目的源码
完整代码 https://github.com/zFxiang/BezierDemo
笔者还属于学习阶段,若文中有错误,还请赐教

0 0
原创粉丝点击