html5 画布贝塞尔曲线得到所有的点

0 html javascript canvas

我喜欢从贝塞尔曲线中得到一些点。我发现

在javascript中找到三次贝塞尔曲线的所有点

位置很容易。首先,计算混合函数。这些控制您的控制点在曲线上的“效果”。

B0_t = (1-t)^3

B1_t = 3 * t * (1-t)^2

B2_t = 3 * t^2 * (1-t)

B3_t = t^3
Run Code Online (Sandbox Code Playgroud)

请注意当 t 为 0 时 B0_t 是 1(并且其他所有内容都为零)。此外,当 t 为 1 时 B3_t 为 1(其他所有内容均为零)。所以曲线从 (ax, ay) 开始,到 (dx, dy) 结束。任何中间点 (px_t, py_t) 将由以下给出(将 t 从 0 变化到 1,在循环内以小增量):

px_t = (B0_t * ax) + (B1_t * bx) + (B2_t * cx) + (B3_t * dx)

py_t = (B0_t * ay) + (B1_t * by) + (B2_t * cy) + (B3_t * dy)
Run Code Online (Sandbox Code Playgroud)

我的代码

            var ax = 100, ay = 250;
            var bx = 150, by = 100;
            var cx = 350, cy = 100;
            var dx = 400, dy = 250;


            ctx.lineWidth = 1;
            ctx.strokeStyle = "#333";
            ctx.beginPath();
            ctx.moveTo(ax, ay);
            ctx.bezierCurveTo(bx, by, cx, cy, dx, dy);
            ctx.stroke();

            var t = 0 
            var B0_t = (1 - t) ^ 3
            var B1_t = 3 * t * (1 - t) ^ 2
            var B2_t = 3 * t ^ 2 * (1 - t)
            var B3_t = t ^ 3


              // override manually *Notice* above
             //This is work first and laste point in curve
            //  B0_t = 1; B1_t = 0; B2_t = 0; B3_t = 0; t = 0;
           // B0_t = 0; B1_t = 0; B2_t = 0; B3_t = 1; t = 1;  

            var px_t = (B0_t * ax) + (B1_t * bx) + (B2_t * cx) + (B3_t * dx)
            var py_t = (B0_t * ay) + (B1_t * by) + (B2_t * cy) + (B3_t * dy)


// doesnt work

var t = 0

var B0_t = (1 - t) ^ 3   //*Notice* above should be 1 
//Debug    (1 - t) ^ 3 = 2 ?? 

var B1_t = 3 * t * (1 - t) ^ 2 //*Notice* above should be 0 
//Debug    3 * t * (1 - t) ^ 2 = 2 ??

var B2_t = 3 * t ^ 2 * (1 - t)//*Notice* above should be 0 
//Debug    3 * t ^ 2 * (1 - t) =2 ??

var B3_t = t ^ 3//*Notice* above should be 0 but its 2
//Debug    t ^ 3 = 3 ??

var px_t = (B0_t * ax) + (B1_t * bx) + (B2_t * cx) + (B3_t * dx)

var py_t = (B0_t * ay) + (B1_t * by) + (B2_t * cy) + (B3_t * dy)
Run Code Online (Sandbox Code Playgroud)

感谢任何帮助谢谢

mar*_*rkE 7

如何沿贝塞尔曲线找到像素

在此处输入图片说明

这组函数将[x,y]T三次贝塞尔曲线上找到一个间隔点,其中0<=T<=1

简单来说:它沿着三次贝塞尔曲线从开始到结束绘制点。

// Given the 4 control points on a Bezier curve 
// get x,y at interval T along the curve (0<=T<=1)
// The curve starts when T==0 and ends when T==1
function getCubicBezierXYatPercent(startPt, controlPt1, controlPt2, endPt, percent) {
    var x = CubicN(percent, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
    var y = CubicN(percent, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
    return ({
        x: x,
        y: y
    });
}

// cubic helper formula
function CubicN(T, a, b, c, d) {
    var t2 = T * T;
    var t3 = t2 * T;
    return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3;
}
Run Code Online (Sandbox Code Playgroud)

您可以通过向绘图函数发送大量介于 0.00 和 1.00 之间的 T 值来获取曲线上的点。

示例代码和演示:

// Given the 4 control points on a Bezier curve 
// get x,y at interval T along the curve (0<=T<=1)
// The curve starts when T==0 and ends when T==1
function getCubicBezierXYatPercent(startPt, controlPt1, controlPt2, endPt, percent) {
    var x = CubicN(percent, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
    var y = CubicN(percent, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
    return ({
        x: x,
        y: y
    });
}

// cubic helper formula
function CubicN(T, a, b, c, d) {
    var t2 = T * T;
    var t3 = t2 * T;
    return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3;
}
Run Code Online (Sandbox Code Playgroud)
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var cBez1=[{x:250,y: 120},{x:290,y:-40},{x:300,y:200},{x:400,y:150}]

drawBez(cBez1);

var cPoints=findCBezPoints(cBez1);

drawPlots(cPoints);


function findCBezPoints(b){
  var startPt=b[0];
  var controlPt1=b[1];
  var controlPt2=b[2];
  var endPt=b[3];
  var pts=[b[0]];
  var lastPt=b[0];
  var tests=5000;
  for(var t=0;t<=tests;t++){
    // calc another point along the curve
    var pt=getCubicBezierXYatT(b[0],b[1],b[2],b[3], t/tests);
    // add the pt if it's not already in the pts[] array
    var dx=pt.x-lastPt.x;
    var dy=pt.y-lastPt.y;
    var d=Math.sqrt(dx*dx+dy*dy);
    var dInt=parseInt(d);
    if(dInt>0 || t==tests){
      lastPt=pt;
      pts.push(pt);
    }
  }
  return(pts);
}

// Given the 4 control points on a Bezier curve 
// Get x,y at interval T along the curve (0<=T<=1)
// The curve starts when T==0 and ends when T==1
function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
  var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
  var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
  return ({
    x: x,
    y: y
  });
}

// cubic helper formula
function CubicN(T, a, b, c, d) {
  var t2 = T * T;
  var t3 = t2 * T;
  return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3;
}

function drawPlots(pts){
  ctx.fillStyle='red';
  // don't draw the last dot b/ its radius will display past the curve
  for(var i=0;i<pts.length-1;i++){
    ctx.beginPath();
    ctx.arc(pts[i].x,pts[i].y,1,0,Math.PI*2);
    ctx.fill();
  }
}

function drawBez(b){
  ctx.lineWidth=7;
  ctx.beginPath();
  ctx.moveTo(b[0].x,b[0].y);
  ctx.bezierCurveTo(b[1].x,b[1].y, b[2].x,b[2].y, b[3].x,b[3].y);
  ctx.stroke();
}
Run Code Online (Sandbox Code Playgroud)
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
Run Code Online (Sandbox Code Playgroud)