1. 贝塞尔曲线在数学上的理解
3 点确定一断曲线,对于二阶贝塞尔曲线
在t 时间内,
从p0 到 q
从q 到 p1 上的点的连线,对应的切线,就是
贝塞尔曲线的轨迹
效果图:
上面是我对贝塞尔曲线立即在数学中,可能理解是错误的,Android开发中不用去管什么公式, 用api就行了
2. Adroid贝塞尔曲线绘制
2.1. 二阶绘制
2.2. 三阶绘制
xml布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.denganzhi.cusomerwidget.canvas.PathActivity">
<com.denganzhi.cusomerwidget.canvas.PathView
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.denganzhi.cusomerwidget.canvas.PathView>
</LinearLayout>
Java代码实现:
public class PathView extends View {
public PathView(Context context) {
super(context);
}
Paint paint=null;
public PathView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
paint=new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(5);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 6. 贝塞尔曲线api
Path path6=new Path();
path6.moveTo(100,400);
// 二阶贝塞尔曲线1
path6.quadTo(250,200,400,400);
// 二阶贝塞尔曲线2, 起点是上一个曲线的结束点
path6.quadTo(500,500,600,400);
// 三阶贝塞尔曲线,4个点
Path path7=new Path();
path7.moveTo(100,400);
path7.cubicTo(200,100,300,250,400,300);
canvas.drawPath(path6,paint);
canvas.drawPath(path7,paint);
}
}
3. PathMeasure 计算轨迹路径长度:
3.1. getLength计算轨迹长度
// PathMeasure 测量工具类
// 600 实际长度 path
PathMeasure pathMeasure1=new PathMeasure(path8,false);
// 800 绘制图形 闭合以后的长度
// PathMeasure pathMeasure2=new PathMeasure(path8,true);
// Log.e("denganzhi","length1:"+pathMeasure1.getLength());
float length1= pathMeasure1.getLength();
// path 可以绘制多条路径,
boolean nextCouner= pathMeasure1.nextContour(); //获取下一个路径,可能没有
// 获取第二条路径长度
float length2= pathMeasure1.getLength();
Log.e("denganzhi","第一个条路径长度:"+length1+ "nextCounter "+ nextCouner+ "第二条路径长度:"+length2);
// 第一个条路径长度:600.0nextCounter true第二条路径长度:160.0
paint.setColor(Color.BLACK);
canvas.drawPath(path8,paint);
输出 : E/denganzhi: 第一个条路径长度:600.0nextCounter true第二条路径长度:160.0
3.2. getSegment截取轨迹,存入新path中
// PathMeasure 用于测量path路径长度
canvas.translate(100,100);
Path path8=new Path();
// 默认其实点是0,0
path8.lineTo(0,200);
path8.lineTo(200,200);
path8.lineTo(200,0);
RectF rect8=new RectF(10,10,50,50);
// 600 实际长度 path
PathMeasure pathMeasure1=new PathMeasure(path8,false);
// 800 绘制图形 闭合以后的长度
float length1= pathMeasure1.getLength();
paint.setColor(Color.BLACK);
canvas.drawPath(path8,paint);
// 路径截取
Path dst= new Path();
paint.setColor(Color.RED);
// dst 的起始点 dst.moveTo(x,x); 是否为上一个节点结束点,是否保存连续性
pathMeasure1.getSegment(0,400,dst,false);
canvas.drawPath(dst,paint);
红色部分为截取部分重新绘制
3.3. getPosTan 获取某一段长度终点的坐标,以及切线(?)
// PathMeasure 用于测量path路径长度
canvas.translate(100,100);
Path path8=new Path();
// 默认其实点是0,0
path8.lineTo(0,200);
path8.lineTo(200,200);
path8.lineTo(200,0);
RectF rect8=new RectF(10,10,50,50);
path8.addRect(rect8, Path.Direction.CCW);
paint.setColor(Color.BLACK);
canvas.drawPath(path8,paint);
float[] pos=new float[2];
float[] tan= new float[2]; // tan=y/x
pathMeasure9.getPosTan(pathMeasure9.getLength()/4,pos,tan);
// postionx: 3.051759E-5 positiony: 50.0 tanx:-1.0 tany: 6.473757E-7
Log.e("denganzhi","postionx: "+pos[0]+" positiony: "+ pos[1] +" tanx:" +tan[0] + " tany: " + tan[1]);
canvas.drawPath(path9,paint);
输出: E/denganzhi: postionx: 3.051759E-5 positiony: 50.0 tanx:-1.0 tany: 6.473757E-7
综合代码 :PathView
package com.denganzhi.cusomerwidget.canvas;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.RegionIterator;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by Administrator on 2020/3/15.
*/
public class PathView extends View {
public PathView(Context context) {
super(context);
}
Paint paint=null;
public PathView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
paint=new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(5);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 6. 贝塞尔曲线api
Path path6=new Path();
path6.moveTo(100,400);
// 二阶贝塞尔曲线1
path6.quadTo(250,200,400,400);
// 二阶贝塞尔曲线2, 起点是上一个曲线的结束点
path6.quadTo(500,500,600,400);
// 三阶贝塞尔曲线,4个点
Path path7=new Path();
path7.moveTo(100,400);
path7.cubicTo(200,100,300,250,400,300);
// canvas.drawPath(path6,paint);
// canvas.drawPath(path7,paint);
// PathMeasure 用于测量path路径长度
canvas.translate(100,100);
Path path8=new Path();
// 默认其实点是0,0
path8.lineTo(0,200);
path8.lineTo(200,200);
path8.lineTo(200,0);
RectF rect8=new RectF(10,10,50,50);
path8.addRect(rect8, Path.Direction.CCW);
// PathMeasure 测量工具类
// 600 实际长度 path
PathMeasure pathMeasure1=new PathMeasure(path8,false);
// 800 绘制图形 闭合以后的长度
// PathMeasure pathMeasure2=new PathMeasure(path8,true);
// Log.e("denganzhi","length1:"+pathMeasure1.getLength());
float length1= pathMeasure1.getLength();
// path 可以绘制多条路径,
// boolean nextCouner= pathMeasure1.nextContour(); //获取下一个路径,可能没有
// 获取第二条路径长度
// float length2= pathMeasure1.getLength();
// Log.e("denganzhi","第一个条路径长度:"+length1+ "nextCounter "+ nextCouner+ "第二条路径长度:"+length2);
// 第一个条路径长度:600.0nextCounter true第二条路径长度:160.0
paint.setColor(Color.BLACK);
canvas.drawPath(path8,paint);
// 路径截取
Path dst= new Path();
paint.setColor(Color.RED);
// dst 的起始点 dst.moveTo(x,x); 是否为上一个节点结束点,是否保存连续性
pathMeasure1.getSegment(0,400,dst,false);
// canvas.drawPath(dst,paint);
// 获取某一段长度的坐标,切线
Path path9=new Path();
path9.addCircle(0,0,50,Path.Direction.CW);
PathMeasure pathMeasure9=new PathMeasure(path9,false);
float[] pos=new float[2];
float[] tan= new float[2]; // tan=y/x
pathMeasure9.getPosTan(pathMeasure9.getLength()/4,pos,tan);
// postionx: 3.051759E-5 positiony: 50.0 tanx:-1.0 tany: 6.473757E-7
Log.e("denganzhi","postionx: "+pos[0]+" positiony: "+ pos[1] +" tanx:" +tan[0] + " tany: " + tan[1]);
canvas.drawPath(path9,paint);
}
}