0

私はあなたが描くことができるこのキャンバスを持っていますが、ある時点で全体に物理ライブラリを使用する予定なので、描画をもう少し詳細にしたいと思います. 一定の間隔でマウスの位置を読み取り、新しいマウスの位置に直線を引くだけの線に沿って何かを考えていました。setInterval と setTimeout を使用してこれを試してみましたが、私が見たいものに近いことは決してありません。どうすればこれを行うことができるか、誰か提案がありますか?

ありがとうございました!

4

1 に答える 1

1

これは Douglas-Peucker パス単純化の JavaScript 実装です。

http://mourner.github.io/simplify-js/

(下記の simple.js の完全なコードを参照してください。)

ポイントを減らすために、線の代わりに曲線を使用することも検討してください (パス スムージング)。

パスの平滑化は、よく考慮されるタスクです。

Douglas Alan Schepers (w3c から):

http://schepers.cc/getting-to-the-point

Spiro ライブラリ (Inkscape などで使用):

http://www.levien.com/spiro/

Ken Fyrstenberg Nilsen (SO での頻繁な寄稿者):

http://www.codeproject.com/Tips/562175/Draw-Smooth-Lines-on-HTML5-Canvas

Paper.js には、パスを滑らかにし、単純化するためのメソッドがあります。

http://paperjs.org/tutorials/paths/smoothing-simplifying-flattening/

Simplify.js のコード ( http://mourner.github.io/simplify-js/の BSD ライセンス):

(function (global, undefined) {
  // to suit your point format, run search/replace for '.x' and '.y';
  // to switch to 3D, uncomment the lines in the next 2 functions
  // (configurability would draw significant performance overhead)

  function getSquareDistance(p1, p2) { // square distance between 2 points

    var dx = p1.x - p2.x,
  //        dz = p1.z - p2.z,
        dy = p1.y - p2.y;


    return dx * dx +
  //           dz * dz +
           dy * dy;
  }


  function getSquareSegmentDistance(p, p1, p2) { // square distance from a point to a segment

    var x = p1.x,
        y = p1.y,
  //        z = p1.z,


        dx = p2.x - x,
        dy = p2.y - y,
  //        dz = p2.z - z,


        t;


    if (dx !== 0 || dy !== 0) {

      t = ((p.x - x) * dx +
  //             (p.z - z) * dz +
           (p.y - y) * dy) /
              (dx * dx +
  //                 dz * dz +
               dy * dy);

      if (t > 1) {
        x = p2.x;
        y = p2.y;
  //            z = p2.z;

      } else if (t > 0) {
        x += dx * t;
        y += dy * t;
  //            z += dz * t;
      }
    }

    dx = p.x - x;
    dy = p.y - y;
  //    dz = p.z - z;

    return dx * dx +
  //           dz * dz +
           dy * dy;
  }

  // the rest of the code doesn't care for the point format

  // basic distance-based simplification

  function simplifyRadialDistance(points, sqTolerance) {

    var i,
        len = points.length,
        point,
        prevPoint = points[0],
        newPoints = [prevPoint];

    for (i = 1; i < len; i++) {
      point = points[i];

      if (getSquareDistance(point, prevPoint) > sqTolerance) {
        newPoints.push(point);
        prevPoint = point;
      }
    }

    if (prevPoint !== point) {
      newPoints.push(point);
    }

    return newPoints;
  }

  // simplification using optimized Douglas-Peucker algorithm with recursion elimination

  function simplifyDouglasPeucker(points, sqTolerance) {

    var len = points.length,

        MarkerArray = (typeof Uint8Array !== undefined + '')
                    ? Uint8Array
                    : Array,

        markers = new MarkerArray(len),

        first = 0,
        last  = len - 1,

        i,
        maxSqDist,
        sqDist,
        index,

        firstStack = [],
        lastStack  = [],

        newPoints  = [];

    markers[first] = markers[last] = 1;

    while (last) {

      maxSqDist = 0;

      for (i = first + 1; i < last; i++) {
        sqDist = getSquareSegmentDistance(points[i], points[first], points[last]);

        if (sqDist > maxSqDist) {
          index = i;
          maxSqDist = sqDist;
        }
      }

      if (maxSqDist > sqTolerance) {
        markers[index] = 1;

        firstStack.push(first);
        lastStack.push(index);

        firstStack.push(index);
        lastStack.push(last);
      }

      first = firstStack.pop();
      last = lastStack.pop();
    }

    for (i = 0; i < len; i++) {
      if (markers[i]) {
        newPoints.push(points[i]);
      }
    }

    return newPoints;
  }

  // both algorithms combined for awesome performance

  function simplify(points, tolerance, highestQuality) {

    var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;

    points = highestQuality ? points : simplifyRadialDistance(points, sqTolerance);
    points = simplifyDouglasPeucker(points, sqTolerance);

    return points;
  };

  // export either as a Node.js module, AMD module or a global browser variable

  if (typeof exports === 'object') {
    module.exports = simplify;

  } else if (typeof define === 'function' && define.amd) {
    define(function () {
      return simplify;
    });

  } else {
    global.simplify = simplify;
  }

}(this));
于 2013-08-24T15:53:34.363 に答える