8

を使用して、html キャンバスに二次曲線を描画していcontext.quadraticCurveTo(controlX, controlY, endX, endY);ます。

コントロールポイントと始点と終点がありますが、これらは必ずしも水平方向に互いに水平であるとは限りません。

これらのパラメータを使用して曲線の中心点を見つけるにはどうすればよいですか?

本当はこの中心点にdivタグをつけたい。このプロセスに関係する方程式の解法はありますか?

4

3 に答える 3

22

quadraticCurveTo二次ベジエ曲線を描きます。

曲線上の任意の位置 (0 から 1) にある点の座標を計算する式は次のとおりです。

x(t) = (1-t)^2 * x1 + 2 * (1-t) * t * x2 + t^2 * x3
y(t) = (1-t)^2 * y1 + 2 * (1-t) * t * y2 + t^2 * y3

ここで、(x1, y1) は始点、(x2, y2) は制御点、(x3, y3) は終点です。

それを JavaScript に変換すると、次のようになります。

function _getQBezierValue(t, p1, p2, p3) {
    var iT = 1 - t;
    return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3;
}

function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
    return {
        x:  _getQBezierValue(position, startX, cpX, endX),
        y:  _getQBezierValue(position, startY, cpY, endY)
    };
}

getQuadraticCurvePointそこに開始点、終了点、制御点を渡すと0.5、途中の位置とともに、X 座標と Y 座標を持つオブジェクトを取得する必要があります。

function _getQBezierValue(t, p1, p2, p3) {
  var iT = 1 - t;
  return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3;
}

function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
  return {
    x: _getQBezierValue(position, startX, cpX, endX),
    y: _getQBezierValue(position, startY, cpY, endY),
  };
}

var position = 0.0;
var startPt = { x: 120, y: 10 };
var controlPt = { x: 410, y: 250 };
var endPt = { x: 10, y: 450 };
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
function drawNextPoint() {
  var pt = getQuadraticCurvePoint(
    startPt.x,
    startPt.y,
    controlPt.x,
    controlPt.y,
    endPt.x,
    endPt.y,
    position,
  );
  position = (position + 0.006) % 1.0;

  ctx.fillStyle = "rgba(255,0,0,0.5)";
  ctx.fillRect(pt.x - 2, pt.y - 2, 5, 5);
}

ctx.strokeStyle = "black";
ctx.moveTo(startPt.x, startPt.y);
ctx.quadraticCurveTo(controlPt.x, controlPt.y, endPt.x, endPt.y);
ctx.stroke();

setInterval(drawNextPoint, 40);
<canvas id="c" width="500" height="500">

于 2012-02-08T14:55:27.840 に答える
0

二次方程式とその解決策を説明するページは次のとおりです。wikiページ。そして、ここに図を備えた主題に関する良いチュートリアルがあります:チュートリアル

于 2012-02-08T13:55:00.847 に答える
0

可能な方法:

// compute coordinates of the middle point of a quadratic Bezier curve
// need two functions: quadraticBezierCurvePoint and quadraticBezierCurvesMiddle

function quadraticBezierCurvePoint(t, c) {
  // compute relative coordinates of a point on the curve using t and c
  // t is a number between 0 and 1
  // c is an array of 3 points:
  //     the initial point of the curve (always (0,0))
  //     the "handle" point of the curve
  //     the final point of the curve
  var t1, t1_2a, t1_2b, t1_2c;
  t1 = 1 - t;
  t1_2a = t1 * t1;
  t1_2b = (2 * t) * t1;
  t1_2c = t * t;
  return {
    x: (c[0].x * t1_2a) + (t1_2b * c[1].x) + (t1_2c * c[2].x),
    y: (c[0].y * t1_2a) + (t1_2b * c[1].y) + (t1_2c * c[2].y)
  };
}

function quadraticBezierCurvesMiddle(m, c) {
  var k, km = 1000,
    km2 = (km >> 1),
    len = 0,
    len2, x, y, a = new Array(km + 1);
  // compute curve lengths from start point to any point
  // store relative point coordinates and corresponding length in array a
  for (k = 0; k <= km; k++) {
    a[k] = {
      pt: quadraticBezierCurvePoint(k / km, c),
      len: 0
    };
    if (k > 0) {
      x = a[k].pt.x - a[k - 1].pt.x;
      y = a[k].pt.y - a[k - 1].pt.y;
      a[k].len = a[k - 1].len + Math.sqrt(x * x + y * y);
    }
  }
  // retrieve the point which is at a distance of half the whole curve length from start point
  // most of the time, this point is not the one at indice km2 in array a, but it is near it
  len2 = a[km].len / 2;
  if (a[km2].len > len2)
    for (k = km2; k >= 0; k--) {
      if (len2 >= a[k].len) break;
    } else
    for (k = km2; k <= km; k++) {
      if (len2 <= a[k].len) break;
    }
    // return absolute coordinates of the point
  return {
    x: Math.round((a[k].pt.x + m.x) * 100) / 100,
    y: Math.round((a[k].pt.y + m.y) * 100) / 100
  };
}

対応する jsfiddle: jsfiddle.net/pTccL/

于 2015-12-12T01:24:19.933 に答える