2011-01-15 15 views
0

与えられた円のすべての点座標を次々に持つ必要があるので、ある点から次の点へとホッピングすることでオブジェクトを円にすることができます。私は中点サークルアルゴリズムを試しましたが、私が見つけたバージョンは描くことを意図しており、座標は連続していません。それらは同時に8つの四分円とその上に反対方向に生産されます。少なくとも彼らが同じ方向にあったなら、私はすべての象限ごとに別々の配列を作って、最後にそれらを互いに追加することができました。これは、私が今持っているJavaScript適応コードです:円の座標を連続的に計算する

function calcCircle(centerCoordinates, radius) { 
    var coordinatesArray = new Array(); 
    // Translate coordinates 
    var x0 = centerCoordinates.left; 
    var y0 = centerCoordinates.top; 
    // Define variables 
    var f = 1 - radius; 
    var ddFx = 1; 
    var ddFy = -radius << 1; 
    var x = 0; 
    var y = radius; 
    coordinatesArray.push(new Coordinates(x0, y0 + radius)); 
    coordinatesArray.push(new Coordinates(x0, y0 - radius)); 
    coordinatesArray.push(new Coordinates(x0 + radius, y0)); 
    coordinatesArray.push(new Coordinates(x0 - radius, y0)); 
    // Main loop 
    while (x < y) { 
     if (f >= 0) { 
     y--; 
     ddFy += 2; 
     f += ddFy; 
     } 
     x++; 
     ddFx += 2; 
     f += ddFx; 
     coordinatesArray.push(new Coordinates(x0 + x, y0 + y)); 
     coordinatesArray.push(new Coordinates(x0 - x, y0 + y)); 
     coordinatesArray.push(new Coordinates(x0 + x, y0 - y)); 
     coordinatesArray.push(new Coordinates(x0 - x, y0 - y)); 
     coordinatesArray.push(new Coordinates(x0 + y, y0 + x)); 
     coordinatesArray.push(new Coordinates(x0 - y, y0 + x)); 
     coordinatesArray.push(new Coordinates(x0 + y, y0 - x)); 
     coordinatesArray.push(new Coordinates(x0 - y, y0 - x)); 
    } 
    // Return the result 
    return coordinatesArray; 
    } 

私は三角法を使わないでいくつかの高速アルゴリズムを好むが、どんな助けもありがとう!

EDIT

これは、最終的な解決策です。みんなありがとう!

function calcCircle(centerCoordinates, radius) { 
    var coordinatesArray = new Array(); 
    var octantArrays = 
     {oct1: new Array(), oct2: new Array(), oct3: new Array(), oct4: new Array(), 
     oct5: new Array(), oct6: new Array(), oct7: new Array(), oct8: new Array()}; 
    // Translate coordinates 
    var xp = centerCoordinates.left; 
    var yp = centerCoordinates.top; 
    // Define add coordinates to array 
    var setCrd = 
     function (targetArray, xC, yC) { 
     targetArray.push(new Coordinates(yC, xC)); 
     }; 
    // Define variables 
    var xoff = 0; 
    var yoff = radius; 
    var balance = -radius; 
    // Main loop 
    while (xoff <= yoff) { 
     // Quadrant 7 - Reverse 
     setCrd(octantArrays.oct7, xp + xoff, yp + yoff); 
     // Quadrant 6 - Straight 
     setCrd(octantArrays.oct6, xp - xoff, yp + yoff); 
     // Quadrant 3 - Reverse 
     setCrd(octantArrays.oct3, xp - xoff, yp - yoff); 
     // Quadrant 2 - Straight 
     setCrd(octantArrays.oct2, xp + xoff, yp - yoff); 
     // Avoid duplicates 
     if (xoff != yoff) { 
     // Quadrant 8 - Straight 
     setCrd(octantArrays.oct8, xp + yoff, yp + xoff); 
     // Quadrant 5 - Reverse 
     setCrd(octantArrays.oct5, xp - yoff, yp + xoff); 
     // Quadrant 4 - Straight 
     setCrd(octantArrays.oct4, xp - yoff, yp - xoff); 
     // Quadrant 1 - Reverse 
     setCrd(octantArrays.oct1, xp + yoff, yp - xoff); 
     } 
     // Some weird stuff 
     balance += xoff++ + xoff; 
     if (balance >= 0) { 
     balance -= --yoff + yoff; 
     } 
    } 
    // Reverse counter clockwise octant arrays 
    octantArrays.oct7.reverse(); 
    octantArrays.oct3.reverse(); 
    octantArrays.oct5.reverse(); 
    octantArrays.oct1.reverse(); 
    // Remove counter clockwise octant arrays last element (avoid duplicates) 
    octantArrays.oct7.pop(); 
    octantArrays.oct3.pop(); 
    octantArrays.oct5.pop(); 
    octantArrays.oct1.pop(); 
    // Append all arrays together 
    coordinatesArray = 
     octantArrays.oct4.concat(octantArrays.oct3).concat(octantArrays.oct2).concat(octantArrays.oct1). 
     concat(octantArrays.oct8).concat(octantArrays.oct7).concat(octantArrays.oct6).concat(octantArrays.oct5); 
    // Return the result 
    return coordinatesArray; 
    } 
+1

ブラウザで円形パス上のオブジェクトを移動する場合は、問題のLASTはsin/cosのスピードでなければなりません。 – 6502

+1

私は、オブジェクトがこのような理由で正確に使用する座標を事前に計算するつもりです。オブジェクトは実際には多くのオブジェクトです。だから、sin/cosの速度が懸念されます。特にNetbookによるIEの場合。 –

+0

sin/cosのもう一つの欠点は、有限個の点を生成することです。円の半径が増加するにつれて、(周囲の間隔が増加するため)計算される点の数が同じままであれば、描画されるアイテムの見かけの速度が増加する。 – Bob

答えて

1

使用して、次のアプローチを試みることができます:あなたが与えたアルゴリズムを使用しますが、8つの異なるcoordinateArraysにあなたの座標を押してください。その後、(x0 + y、y0 + y)、(x0-y、y0 + y)、(x0 + y、y0 + x)、(x0-y、y0-x) )、その後、すべての配列を正しい順序で追加します。最初の4つの点を正しい配列に追加するように注意してください。

+0

私はそれも考えました。私はあなたにそれを打つが、私はまだあなたに信用を与える;)別の解決策は、唯一のオクタントの代わりにentiteサークルを計算することですが、私はアルゴリズムを適応させる方法を知らない。 –

1

私の知る限り、三角法なしではできませんが、かなり速く動作します。残念私は、Javaに精通していないので、私はVBでコードを書く:


Dim PointList As New List(Of PointF) 
For angle = 0 To Math.PI * 2 Step 0.01 
    'the smaller the step, the more points you get 
    PointList.Add(New PointF(Math.Cos(angle) * r + x0, Math.Sin(angle) * r + y0)) 
Next 

X0とY0は中心が円の座標で、rは半径です。

希望あなたの質問に答えました。

+1

これは、少なくとも円の半径がなくてもどうやって動くのだろうかと思います。 – Hemlock

+0

気づいてくれてありがとう、私はコードを編集しました。 – Dave

0

ここは、Daveの答えに基づくJavaScriptの実装です。あまりにも少し工夫されたので、私は罪と必要以上のものを呼ぶことを避けたかったのです。皮肉なことに、半径ずにDaveの最初の答えを生かし:)

function calculateCircle(x,y,radius) { 

    var basicPoints = getBasicCircle(); 
    var i = basicPoints.length; 
    var points = []; // don't change basicPoints: that would spoil the cache. 
    while (i--) { 
    points[i] = { 
     x: x + (radius * basicPoints[i].x), 
     y: y + (radius * basicPoints[i].y) 
    }; 
    } 
    return points; 
} 

function getBasicCircle() { 
    if (!arguments.callee.points) { 
    var points = arguments.callee.points = []; 
    var end = Math.PI * 2; 
    for (var angle=0; angle < end; angle += 0.1) { 
     points.push({x: Math.sin(angle), 
        y: Math.cos(angle) 
        }); 
    } 
    } 
    return arguments.callee.points 
} 
+0

おかげでヘムロック!あなたがしたことをもっと詳しく説明するために気をつけますか?あらかじめ計算された円のキングを使用し、次に異なる半径のために拡大しますか?ポイントが大きなサークルのために十分でない場合、これはうまくいきませんか? –

+0

ええ、それは1つの半径円をあらかじめ計算しています。より高い解像度または低い解像度の円を返すには、キャッシング機能を変更する必要があります。 – Hemlock

関連する問題