贝塞尔曲线简介

来源:互联网 发布:单片机控制电机电路图 编辑:程序博客网 时间:2024/06/07 04:03

参考:

Android-贝塞尔曲线
贝塞尔曲线扫盲

动态绘制贝塞尔曲线的在线演示

一阶贝塞尔曲线(线段):

包含两个点:起点、终点,
其实就是lineTo的效果。

二阶贝塞尔曲线(抛物线):

包含三个点:起点A、一个控制点B、终点C

长度关系为:

AD / DB = BE / EC = DF / FE

二阶曲线对应的方法是quadTo

Path mPath = new Path();mPath.moveTo(x0,y0);//起点(x0,y0)mPath.quadTo(x1,y1,x2,y2);//控制点B坐标(x1,y1),决定了弧度方向与大小,//终点C坐标(x2,y2)canvas.drawPath(mPath, mPaint); 

示例:

public class MyView extends View {    private float mSupX;    private float mSupY;    public MyView(Context context) {        super(context);    }    public MyView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onDraw(Canvas canvas) {        Paint paint = new Paint();        paint.setStyle(Paint.Style.STROKE);        paint.setStrokeWidth(10);        Path path = new Path();        path.moveTo(200, 200);//起点        path.quadTo(mSupX, mSupY, 800, 1300);//控制点,终点        canvas.drawPath(path, paint);//画出贝塞尔曲线        paint.setColor(Color.parseColor("#ff0000"));        paint.setStrokeWidth(20);        canvas.drawPoint(mSupX, mSupY, paint);//画出控制点    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_MOVE:                mSupX = event.getX();                mSupY = event.getY();                invalidate();        }        return true;    }}

效果图:

这里写图片描述

参考:Android自定义view进阶– 神奇的贝塞尔曲线

三阶贝塞尔曲线:

包含四个点:起点A、2个控制点BC、终点D

长度关系为:

AE:AB = BF:BC = CG:CD = EH:EF = FI:FG = HJ:HI

三阶曲线对应的方法是cubicTo

path.cubicTo(0, 150, 300, 450, 0, 600);      //(0, 150):控制点B,//(300, 450):控制点C,//(0, 600):终点D

三阶曲线计算过程与二阶类似,具体可以见下图动态效果:

示例:

public class MyView extends View {    private Point controlPointOne = new Point(200, 200);    private Point controlPointTwo = new Point(500, 200);    private boolean isControlPointTwo;    private Paint paintBezier;    private Paint paintLine;    public MyView(Context context) {        this(context, null);    }    public MyView(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        paintBezier = new Paint();        paintBezier.setStyle(Paint.Style.STROKE);        paintBezier.setColor(Color.BLACK);        paintBezier.setStrokeWidth(10);        paintLine = new Paint();        paintLine.setStyle(Paint.Style.STROKE);        paintLine.setColor(Color.RED);        paintLine.setStrokeWidth(3);    }    @Override    protected void onDraw(Canvas canvas) {        Path path = new Path();//注意path不可在构造方法中new        path.moveTo(100, 500);        if (isControlPointTwo) {            paintBezier.setColor(Color.RED);        } else {            paintBezier.setColor(Color.BLUE);        }        path.cubicTo(controlPointOne.x, controlPointOne.y, controlPointTwo.x, controlPointTwo.y, 900, 500);        //绘制路径        canvas.drawPath(path, paintBezier);        //绘制辅助点        paintBezier.setColor(Color.RED);        canvas.drawPoint(controlPointOne.x, controlPointOne.y, paintBezier);        paintBezier.setColor(Color.BLUE);        canvas.drawPoint(controlPointTwo.x, controlPointTwo.y, paintBezier);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_MOVE:                if (isControlPointTwo) {                    controlPointOne.x = (int) event.getX();                    controlPointOne.y = (int) event.getY();                } else {                    controlPointTwo.x = (int) event.getX();                    controlPointTwo.y = (int) event.getY();                }                invalidate();                break;        }        return true;    }    public boolean isControlPointTwo() {        return isControlPointTwo;    }    public void setControlPointTwo(boolean controlPointTwo) {        isControlPointTwo = controlPointTwo;    }}

布局:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <Button        android:id="@+id/btn"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="切换控制点" />    <com.android.imooc.MyView        android:id="@+id/my_view"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1" /></LinearLayout>

MyActivity

public class MyActivity extends FragmentActivity {    private Button btn;    private MyView myView;    private boolean isControlPointTwo = false;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.test3);        btn = ((Button) this.findViewById(R.id.btn));        myView = ((MyView) this.findViewById(R.id.my_view));        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (isControlPointTwo) {                    myView.setControlPointTwo(false);                } else {                    myView.setControlPointTwo(true);                }                isControlPointTwo = !isControlPointTwo;            }        });    }}

效果图:

这里写图片描述

参考:Android – 贝塞尔曲线公式的推导和简单使用

原创粉丝点击