亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

用多段三次貝塞爾曲線和距離以及曲率約束逼近數據

用多段三次貝塞爾曲線和距離以及曲率約束逼近數據

撒科打諢 2019-09-03 20:29:00
我有一些地理數據(下面的圖像顯示了河流的路徑為紅點),我想用多段三次貝塞爾曲線近似。通過對計算器等問題,在這里和這里我發現由Philip J.施耐德從“圖形寶石”的算法。我成功地實現了它并且可以報告即使有數千個點它也非??臁2恍业氖?,速度帶來了一些缺點,即裝配非常不合適。請考慮以下圖形:多段貝塞爾曲線紅點是我的原始數據,藍線是由Schneider算法創建的多段貝塞爾曲線。如您所見,算法的輸入是一個容差,至少與綠線表示的一樣高。然而,該算法創建了具有太多急轉彎的貝塞爾曲線。你也會在圖像中看到這些不必要的急轉彎。很容易想象,對于所示數據,具有較小急轉彎的貝塞爾曲線,同時仍保持最大公差條件(僅將貝塞爾曲線稍微推向品紅色箭頭的方向)。問題似乎是算法從我的原始數據中選取數據點作為各個貝塞爾曲線的終點(品紅箭頭指示一些嫌疑人)。貝塞爾曲線的端點受此限制,我正在尋找的是一種算法,它使用具有兩個約束的多段貝塞爾曲線來近似我的數據:多段貝塞爾曲線絕不能超過數據點一定距離(由Schneider算法提供)多段貝塞爾曲線絕不能產生過于尖銳的曲率。檢查此標準的一種方法是沿多段貝塞爾曲線滾動具有最小曲率半徑的圓,并檢查它是否沿其路徑接觸曲線的所有部分。雖然看起來有更好的方法涉及一階和二階導數的叉積我發現可以創造更好擬合的解決方案或者僅適用于單個貝塞爾曲線(并且省略了如何在多段貝塞爾曲線中找到每個貝塞爾曲線的良好起點和終點的問題)或者不允許最小曲率約束。我認為最小曲率約束是這里的棘手條件。這是另一個例子(這是手繪而不是100%精確):一些例子讓我們假設圖一顯示曲率約束(圓必須適合整個曲線)以及任何數據點與曲線的最大距離(恰好是綠色圓的半徑)。圖2中紅色路徑的成功近似顯示為藍色。該近似值符合曲率條件(圓可以在整個曲線內滾動并在任何地方觸摸它)以及距離條件(以綠色顯示)。圖3顯示了路徑的不同近似值。雖然它符合距離條件但很明顯圓圈不再適合曲率。圖4顯示了一條不可能用給定約束近似的路徑,因為它太尖了。該示例應該說明為了正確地近似路徑中的一些尖轉彎,算法必須選擇不屬于路徑的控制點。圖3顯示,如果選擇沿路徑的控制點,則不能再滿足曲率約束。此示例還顯示算法必須退出某些輸入,因為無法使用給定的約束來近似它。這個問題是否存在解決方案?解決方案不一定要快。如果需要一天時間來處理1000點,那就沒問題了。解決方案也不必是最佳的,因為它必須導致最小二乘擬合。最后,我將用C和Python實現它,但我也可以閱讀大多數其他語言。
查看完整描述

3 回答

?
德瑪西亞99

TA貢獻1770條經驗 獲得超3個贊

多邊形化數據


找到點的順序,這樣你就可以找到彼此最近的點,并嘗試連接“按線”。避免回到原點


計算沿路徑的推導


它是“線”的方向變化,你達到局部最小值或最大值就有你的控制點......這樣做是為了減少輸入數據(只留下控制點)。


曲線


現在使用這些點作為控制點。我強烈建議兩者的插值多項式x和y單獨的插值多項式,例如:


x=a0+a1*t+a2*t*t+a3*t*t*t

y=b0+b1*t+b2*t*t+b3*t*t*t

在哪里a0..a3計算如下:


d1=0.5*(p2.x-p0.x);

d2=0.5*(p3.x-p1.x);

a0=p1.x;

a1=d1;

a2=(3.0*(p2.x-p1.x))-(2.0*d1)-d2;

a3=d1+d2+(2.0*(-p2.x+p1.x));

b0 .. b3 以相同的方式計算,但當然使用y坐標

p0..p3 是三次插值曲線的控制點

t =<0.0,1.0>是曲線參數從。p1到p2

這確保了位置和第一次推導是連續的(c1),你也可以使用BEZIER,但它不會像這樣好。


[edit1]過于尖銳的邊緣是一個很大的問題


要解決此問題,您可以在獲取控制點之前從數據集中刪除點。我現在可以想到兩種方法:選擇對你更好的方法


從第一個推導過高的數據集中刪除點


dx/dl或者坐標dy/dl在哪里x,y,l是曲線長度(沿著它的路徑)。從曲線推導精確計算曲率半徑是棘手的


從數據集中刪除導致曲率半徑太小的點


計算相鄰線段(黑線)中點的交點。像圖像上的垂直軸(紅線)它的距離和連接點(藍線)是曲率半徑。當曲率半徑小時,你的極限移除那個點......


曲率半徑


現在,如果你真的只需要BEZIER立方體,那么你可以將我的插值立方體轉換為BEZIER立方體,如下所示:


//  ---------------------------------------------------------------------------

//  x=cx[0]+(t*cx[1])+(tt*cx[2])+(ttt*cx[3]); // cubic x=f(t), t = <0,1>

//  ---------------------------------------------------------------------------

//  cubic matrix                           bz4 = it4

//  ---------------------------------------------------------------------------

//  cx[0]=                            (    x0) =                    (    X1)

//  cx[1]=                   (3.0*x1)-(3.0*x0) =           (0.5*X2)         -(0.5*X0)

//  cx[2]=          (3.0*x2)-(6.0*x1)+(3.0*x0) = -(0.5*X3)+(2.0*X2)-(2.5*X1)+(    X0)

//  cx[3]= (    x3)-(3.0*x2)+(3.0*x1)-(    x0) =  (0.5*X3)-(1.5*X2)+(1.5*X1)-(0.5*X0)

//  ---------------------------------------------------------------------------

    const double m=1.0/6.0;

    double x0,y0,x1,y1,x2,y2,x3,y3;

    x0 = X1;           y0 = Y1;

    x1 = X1-(X0-X2)*m; y1 = Y1-(Y0-Y2)*m;

    x2 = X2+(X1-X3)*m; y2 = Y2+(Y1-Y3)*m;

    x3 = X2;           y3 = Y2;


查看完整回答
反對 回復 2019-09-03
?
largeQ

TA貢獻2039條經驗 獲得超8個贊

我不認為它回答了我的問題。為了使我的問題更清楚,我添加了另一個圖形示例。更確切地說,我不認為你的解決方案可以遵守曲率約束,因為它選擇路徑的點作為曲線的控制點。我的例子表明,對于一些非常尖的路徑,有必要選擇除輸入路徑之外的控制點。

查看完整回答
反對 回復 2019-09-03
  • 3 回答
  • 0 關注
  • 1970 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號