2016-08-23 10 views
4

写真のように、私は2つの座標を持っており、長軸の辺がこれらの2つの点に一致する楕円を描きたい。2つの座標を使用する方法は、JavaScriptで楕円を描画しますか?

enter image description here

私は、これら二つの座標間の中間点を取得し、これらの1座標上の楕円ベースを描画しようとしています。これらのようなコードは、関数の下に私がしたいだけである楕円点の配列を返す:

function add_oval(centre, x, y) { 
    var assemble = new Array(); 
    var angle; 
    var dot; 
    var tangent = x/y; 
    for (i = 0; i < 36; i++) { 
     angle = (2 * Math.PI/36) * i; 
     dot = [centre.lng + Math.sin(angle) * y * tangent, centre.lat + Math.cos(angle) * y]; 
     assemble.push(dot); 
    } 
    return assemble; 
} 

しかし、問題があるが、これらだけ水平楕円を描くことができ、私は角度を変更する方法がわかりません。

誰かが私の問題を解決する方法を知っていますか?

+5

[ellipse](https://en.wikipedia.org/wiki/Ellipse)を描画するには、副軸も定義する必要があります。 – Teemu

+0

@Teemu、私は副軸のための特定の値を作ることができます、それは問題ではありません。 –

答えて

3

ヒント

ジャバスクリプトには、回転楕円機能がない場合、回避策は代わりに、ベジェ立方近似を使用することです。 4つのベジエ円弧で円を近似する方法については、How to create circle with Bézier curves?の記事を参照してください。その後、楕円は伸びた円に過ぎず、コントロールポイントを同じように引き伸ばすだけで十分です。

単位円で始まり、コントロールポイントを軸の長さだけスケールし、回転を適用して目的の中心に移動します。スケーリングおよび回転パラメータは、指定された長軸(マイナー長を加えたもの)から引き出すことができます。

楕円のパラメトリック方程式を使用し、ポリラインとして描画する方法もあります。

1

私はこのために基底ベクトルを使用します。

  1. 楕円定義

    ellipse

    だから我々はA,B 2Dのポイントを知っています。楕円を定義するには、スカラー副軸のサイズ|b|も定義する必要があります。そうknownsは以下のとおりです。

    A=! 
    B=! 
    |b|=! 
    
  2. 中間点C、それはA,B

    C.x=A.x + (B.x-A.x)/2 
    C.y=A.y + (B.y-A.y)/2 
    

    またはA,B

    C.x = (A.x+B.x)/2 
    C.y = (A.y+B.y)/2 
    

    の平均選択の間の半分で簡単です

    いるあなたをmのような鉱石(それは問題ではない)。この点Cは、基底ベクトルの起源となる。

  3. 基底ベクトルa,bそれはあなたがまた半分を使用することができます

    a.x = B.x-C.x 
    a.y = B.y-C.y 
    

    CBまたはCA(また楕円のために重要ではありません)によって定義されるよう

    主要半軸が簡単です。

    a.x = (B.x-A.x)/2 
    a.y = (B.y-A.y)/2 
    

    mi半軸bは悪化していると、私たちはそのいずれかが3D広告再スケールでベクトル(0,0,1)aの外積を悪用したり、(y,-x)(x,y)を交換または(-y,x)場合は、2Dでの90度の回転を得るという事実を使用することがaに垂直である知っています。そして、サイズ|a|からそれほどサイズ|b|に再スケール:

    |a| = sqrt(a.x*a.x + a.y*a.y) 
    b.x = a.y * |b|/|a| 
    b.y =-a.x * |b|/|a| 
    
  4. 楕円

    を今、私たちは最終的に我々はレンダリングのために必要なすべてを得ました。私たちの楕円上の任意の点はM_PI=3.1415926535897932384626433832795が簡単である角度ang=<0,2.0*M_PI>によってパラメータ:

    x = C.x + a.x*cos(ang) + b.x*sin(ang) 
    y = C.y + a.y*cos(ang) + b.y*sin(ang) 
    

    だからあなたのforループにこれを追加し、あなたが今のところ持っているようにポイントを使用して楕円を描画するのどちらか。

    bool e,e0; 
    double ang,dang=2.0*M_PI/100.0; // 100 lines per 360 degree 
    for (e=true,e0=true,ang=0.0;e;ang+=dang,e0=false) 
    { 
    if (ang>=2.0*M_PI) { ang=2.0*M_PI; e=false; } // reached end? 360 degree 
    x = C.x + a.x*cos(ang) + b.x*sin(ang); 
    y = C.y + a.y*cos(ang) + b.y*sin(ang); 
    if (e0) Canvas->MoveTo(x,y); // first time is cursor moved to (x,y) 
        else Canvas->LineTo(x,y); // all the other iterations just draws a line from last cursor to (x,y) and also moves the cursor there 
    } 
    

ノート

  • :またはVCL/GDIでこのような例何か(申し訳ありませんが、私はJavaScriptを使用していない)のための...ラインとポリラインとして楕円を描画しますポイントおよび2D内のベクトルは、2座標のセットとして定義されます。(x,y)
  • スカラーは、単一の値(標準数)
  • |a|は、ベクトルの大きさが計算上a
  • |a|>|b|
  • |b|場合は、あなたは|b|/|a|=0.3
  • を聞かせてたとえば |a|のスケーリングを使用することができ不明であることを必要としないことを意味しています
+0

私は楕円のすべての座標を取得したいが、それを '描画'しない場合はどうすればいいですか? 実際には、描画方法は私のコントロールではありません。私はそのメソッドのポイントリストを提供するだけです。 –

+0

@JackZhang次にmoveto/lineを無視して、ポイントリストに '(x、y)'を追加します。また、あなたは十分なポイントを持つように 'dang'のステップを変更する必要があります。正確な隣接ピクセル位置を計算することは、超越問題につながるローテーションでは本当に難しい問題です...より簡単で速いのは、小さな「ダング」ステップと重複ピクセルのリスクを持つことです。より良い推定のために円近似を使うことができます...もし '| a |> = | b |'ならば、 'dang <= 1/| a | 'と間違っていなければピクセルステップに非常に近いはずです。偏心に依存します...私は 'dang = 0.75/| a |'またはそれより小さなステップ – Spektre

関連する問題