贝塞尔曲线、Path、PathMeasure理解在Android中

Elana ·
更新时间:2024-11-13
· 593 次阅读

 1. 贝塞尔曲线在数学上的理解
   3 点确定一断曲线,对于二阶贝塞尔曲线
   在t 时间内,
   从p0 到  q
   从q  到 p1 上的点的连线,对应的切线,就是
   贝塞尔曲线的轨迹
   效果图:

上面是我对贝塞尔曲线立即在数学中,可能理解是错误的,Android开发中不用去管什么公式, 用api就行了

 2. Adroid贝塞尔曲线绘制
2.1. 二阶绘制
2.2. 三阶绘制

xml布局:

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); } }
作者:小置同学



path 贝塞尔 贝塞尔曲线 Android

需要 登录 后方可回复, 如果你还没有账号请 注册新账号