2016-08-23 108 views
4

就像圖片展示一樣,我有兩個座標,我想繪製一個長軸與這兩點匹配的橢圓。如何使用兩個座標用javascript繪製橢圓?

enter image description here

我試圖讓這兩個座標之間的中點,並借鑑這些一個座標的橢圓形底座。像這樣的代碼,下面的函數返回橢圓點的陣列,只是我想:

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

您還必須定義短軸,以繪製[橢圓](https://en.wikipedia.org/wiki/Ellipse)。 – Teemu

+0

@Teemu,我可以爲短軸做一個具體的數值,沒關係。 –

回答

3

提示

如果在JavaScript沒有旋轉的橢圓特徵,一種解決方法是使用一個貝塞爾立方近似值來代替。請參閱How to create circle with Bézier curves?文章,瞭解如何用四個貝塞爾曲線近似一個圓。然後一個橢圓只是一個拉伸的圓,並且以相同的方式拉伸控制點就足夠了。

從單位圓開始,通過軸長度縮放控制點,應用所需的旋轉並將其轉換爲所需的中心。縮放和旋轉參數可以從給定的主軸(加上鏡的長度)繪製。

另一種方法是使用橢圓的參數方程並將其繪製爲多段線。

1

我會用這個基礎向量。

  1. 橢圓定義

    ellipse

    因此,我們知道A,B 2D點。您還需要定義標量次要半軸大小|b|以定義您的橢圓。這樣的已知,有:

    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 
    

    之間選擇,你像米礦石(哪個並不重要)。這一點C將作爲基礎向量的起源。

  3. 基礎矢量a,b

    主要半軸是容易,因爲它是由CBCA(也無所謂其爲完整的橢圓)

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

    也可以使用半定義的AB

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

    mi也不半軸b更糟糕的是,我們知道這是垂直於a所以在3D廣告的重新調整開發的a叉積與向量(0,0,1)或使用的事實,如果換成(x,y)(y,-x)(-y,x)你獲得在2D 90度旋轉。和重新調整大小,從到|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. 橢圓

    現在我們終於得到了我們需要渲染的一切。我們通過橢圓角度ang=<0,2.0*M_PI>參數化的任何點M_PI=3.1415926535897932384626433832795很簡單:

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

    因此,無論添加此到您的for循環,並用點渲染你的橢圓形,你有現在。或使橢圓與線條折線...例如像這樣在VCL/GDI(對不起,我不使用JavaScript):

    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 
    } 
    

注意

  • 矢量在2D中被定義爲2座標集合(x,y)
  • 標量
  • |a|單個值(標準號)指矢量的大小a
  • 以上計算不要求|a|>|b|
  • 如果|b|是未知的可以使用的|a|縮放例如讓|b|/|a|=0.3
+0

如果我想獲得橢圓的所有座標但不「繪製」該怎麼辦。其實,畫法並不是由我控制的。我只能提供該方法的點列表。 –

+0

@JackZhang然後你忽略moveto/line並將'(x,y)'加到你的點列表中。你也需要改變'dang'步驟,以便你有足夠的分數。計算精確的相鄰像素位置對於旋轉來說確實是一個難題,因爲它會導致超驗問題...更簡單快速的方法是讓「dang」步驟更小並且有重複像素的風險。爲了更好的估計,你可以使用循環近似...所以如果'| a |> = | b |'那麼如果我沒有弄錯'dang <= 1/| a |'應該非常接近像素步長。取決於偏心...我會使用'dang = 0.75/| a |'或更小的步長 – Spektre