2011-09-08 14 views
8

私のアプリケーションでは、Html5キャンバスのベジェ曲線上に破線のカーブを描く必要があります...ダッシュの長さと間隔は可変でなければなりません。 JavaFx、see this link ...私はHtml5キャンバスを使用して同じ効果を達成したいと思います。私は点線で描画する方法を知っていますが、ベジェに沿った曲線ではありません。Html5キャンバスベジェの破線カー

私は専門家ではありませんが、私はbezier drawing algorithmを知っています。このアルゴリズムでは問題があります。 0〜1の範囲の時間パラメータを使用するベジェを使用します。

破線のベジェを描くためには、これは十分ではありません。指定された長さのパラメータと所定のギャップ距離で多くの小さなベジェを描く必要がありますメインベジェパス。 JavaFxで使用されるアルゴリズムが必要です。誰かが私を助けることができるなら、それは素晴らしいだろう。

+0

あなたがここに点線の曲線に適応することができるかもしれという似たようなのスマートな実装があります:http://stackoverflow.com/questions/を4576724/dotted-stroke-in-canvasここでのライブ例:http://phrogz.net/tmp/canvas_dashed_line.html – unmounted

+0

私が言ったように、私は破線をプロットする方法を知っていますが、問題は点線の曲線をベジェパス... –

+0

私はbez描画アルゴでmod op(%)を使うことができると思います。偶数位置の場合はアルファをゼロに設定し、長さを基準にしてカーブの奇数位置の場合はアルファを通常に設定します。あなたが私にベジエ・アルゴを与えることができれば、私はこの数学を差し込んでも構いません。:) –

答えて

4

私は、JavaFXが破線の曲線を描画するための一般的なテクニックを使用していて、その例ではベジェで使用していると思います。

ハード部分は、各ダッシュを開始および停止する場所を把握しています。そこには、さまざまな点でベジェ曲線のarc lengthを知る必要があります。

は、分析的なアプローチがありますが、私は次のことをお勧めします。このアプローチの

var bezier = function(controlPoints, t) { 
    /* your code here, I'll presume it returns a 2-element array of x and y. */ 
}; 

//just figure out the coordinates of all the points in each dash, don't draw. 
//returns an array of arrays, each sub-array will have an even number of nu- 
//merical elements, to wit, x and y pairs. 

//Argument dashPattern should be an array of alternating dash and space 
//lengths, e.g., [10, 10] would be dots, [30, 10] would be dashes, 
//[30, 10, 10, 10] would be 30-length dash, 10-length spaces, 10-length dash 
// and 10-length space. 
var calculateDashedBezier = function(controlPoints, dashPattern) { 
    var step = 0.001; //this really should be set by an intelligent method, 
        //rather than using a constant, but it serves as an 
        //example. 

    //possibly gratuitous helper functions 
    var delta = function(p0, p1) { 
    return [p1[0] - p0[0], p1[1] - p0[1]]; 
    }; 
    var arcLength = function(p0, p1) { 
    var d = delta(p0, p1); 
    return Math.sqrt(d[0]*d[0] + d[1] * d[1]); 
    }; 

    var subPaths = []; 
    var loc = bezier(controlPoints, 0); 
    var lastLoc = loc; 

    var dashIndex = 0; 
    var length = 0; 
    var thisPath = []; 
    for(var t = step; t <= 1; t += step) { 
    loc = bezier(controlPoints, t); 
    length += arcLength(lastLoc, loc); 
    lastLoc = loc; 

    //detect when we come to the end of a dash or space 
    if(length >= dashPattern[dashIndex]) { 

     //if we are on a dash, we need to record the path. 
     if(dashIndex % 2 == 0) 
     subPaths.push(thisPath); 

     //go to the next dash or space in the pattern 
     dashIndex = (dashIndex + 1) % dashPattern.length; 

     //clear the arclength and path. 
     thisPath = []; 
     length = 0; 
    } 

    //if we are on a dash and not a space, add a point to the path. 
    if(dashIndex % 2 == 0) { 
     thisPath.push(loc[0], loc[1]); 
    } 
    } 
    if(thisPath.length > 0) 
    subPaths.push(thisPath); 
    return subPaths; 
}; 

//take output of the previous function and build an appropriate path 
var pathParts = function(ctx, pathParts) { 
    for(var i = 0; i < pathParts.length; i++) { 
    var part = pathParts[i]; 
    if(part.length > 0) 
     ctx.moveTo(part[0], part[1]); 
    for(var j = 1; j < part.length/2; j++) { 
     ctx.lineTo(part[2*j], part[2*j+1]); 
    } 
    } 
}; 

//combine the above two functions to actually draw a dashed curve. 
var drawDashedBezier = function(ctx, controlPoints, dashPattern) { 
    var dashes = calculateDashedBezier(controlPoints, dashPattern); 
    ctx.beginPath(); 
    ctx.strokeStyle = /* ... */ 
    ctx.lineWidth = /* ... */ 
    pathParts(ctx, dashes); 
    ctx.stroke(); 
}; 

主な問題は、その非インテリジェントな粒度です。ステップがあなたの(小さい)ダッシュや(大きな)カーブには大きすぎると、ステップサイズがうまく機能せず、ダッシュ境界があなたが望む場所に正確には収まらなくなります。ステップが小さすぎると、サブピクセルの距離が離れている点でlineTo()秒を過ぎることがあり、時にはAAアーティファクトが発生します。サブピクセルの距離座標をフィルタリングすることは困難ではありませんが、実際に必要とするより多くの「頂点」を生成することは非効率的です。より良いステップサイズが登場するのは、実際には私はより分析的に攻撃すると考えています。

bezier(controlPoints, t)をカーブに評価するものに置き換えた場合、前の段落にリストされている同様の潜在的な問題があります。しかし粒状性の問題に対する本当に良い解決策は、すべての「よく振舞われた」曲線でうまくいく可能性があります。将来的には

+1

あなたは進歩したベジエのサイズを知ることができないので、ステップ= 0.001への推定ステップは大きなリスクです。 2つの点の距離が0になるか、または曲線が直線になるまで、中間点を見つけることによってステップが再帰的に計算されると良いでしょう。 –

+0

もう一つの簡単な方法は、 'step'を円弧長の近似値ベジェ曲線の最小ダッシュ長さで割ったものです。それでも、 '1/step'が円弧の長さを最小のダッシュの長さで割った値よりもはるかに大きくなるようなカーブの場合、固定された' step'はうまく動作します。 – ellisbben

+0

助けていただきありがとうございます... –