2012-10-16 68 views
4

我想從Postscript/SVG路徑重建原始圖形基元。因此,一個原始的圓被渲染(在SVG標記)爲:從貝塞爾曲線重構圓

<path stroke-width="0.5" d="M159.679 141.309 
     C159.679 141.793 159.286 142.186 158.801 142.186 
     C158.318 142.186 157.925 141.793 157.925 141.309 
     C157.925 140.825 158.318 140.432 158.801 140.432 
     C159.286 140.432 159.679 140.825 159.679 141.309" /> 

這是使用4條貝濟耶曲線來創建circle.In其他地方圓弧通過連接貝塞爾曲線近似的近似。

我的問題是,是否有一個算法,我可以用它來識別這個結構,並重建「最佳」的圈子。我不介意小小的錯誤 - 最差的時候他們會成爲第二順位。

更新:請注意,我不知道這是一個圓或弧 - 它可能是任何東西。曲線上可能有2,3,4甚至更多點。所以,我真的想排序的函數:

error = getCircleFromPath(path) 

其中error會給這是否可能是一個圓的早期跡象。

[我同意,如果我知道這是一個圓圈這是一個簡單的問題。]

UPDATE:@george大大有助於回答我的問題的一些辦法,但我不認爲這是故事的全部。

翻譯的起源和規範化我似乎有曲線上的以下四點以後:

point [0, 1] with control point at [+-d,1] // horizontal tangent 
point [1, 0] with control point at [1,+-d] // vertical tangent 
point [0, -1] with control point at [+-d,-1] // horizontal tangent 
point [-1, 0] with control point at [-1,+-d] // vertical tangent 

這保證了各點的切線是「平行」在該點的路徑方向。它也保證了對稱性(4倍軸與反射,但它不保證一個圓圈,例如一個大值d將給出一個圓角框和一個小值圓形鑽石。 。約爲0.57,這可能是1 /開方或者它可能是else.It是這種關係我要求

@george給出了圓弧的中點爲(3);

{p1,(p1 + 3 (p2 + p3) + p4)/8,p4} 

所以在我的例子中(對於1,0到0,1)這將是: [[1,0]+3[1,d]+3[d,1]+[0,1]]/8

[0.5+3d/8, 3d/8+0.5] 

和如果d = 0.57,這給出了0.71,所以也許d是

(sqrt(0.5)-0.5)*8./3. 

這適用於正方形金剛石,但對於圓弧的公式必須是更一般的和I」如果有人有,請感激。例如,我不熟悉貝塞爾數學,所以@喬治的公式是新的我

enter code here 

回答

5

沒有拼盡全力幫助您計算..這可能有所幫助:

貝塞爾總是有4個控制點。 您的曲線是4個貝齊爾連接點1-4,4-7,7-10和10-13控制點 爲每個部分。點1,4,7和10(& 13 == 1)完全位於曲線上。要看到,如果你有一個很好的循環計算:

center = (p1+p7)/2 =( {159.679, 141.309} + {157.925, 141.309})/2 
     = {158.802, 141.309} 

驗證你使用分4 + 10相同的結果 - 沿> {158.801,141.309}

一旦你知道中心,您可以品嚐點曲線,看看你是否有一個恆定的距離。

如果你只有一個有4個點的貝塞爾弧,一個有用的公式是中點在 (p1 + 3(p2 + p3)+ p4)/ 8。因此,您可以找到經過三點的圓:

{p1,(p1 + 3 (p2 + p3) + p4)/8,p4} 

並再次採樣曲線上的其他點以確定您是否確實有近圓弧。

編輯 貝塞爾式是這樣的:

x=(1-t)^3 p1 + 3 (1-t)^2 t p2 + 3 (1-t) t^2 p3 + t^3 p4 with parameter 0 < t < 1 

所以例如在t = 1/4中,您有

x=(27 p1 + 27 p2 + 9 p3 + 1 p4)/64 

所以一旦找到中心可以很容易地檢查幾個點並計算它們的距離。

我懷疑,如果你只想檢測幾乎精確的圓弧,然後檢查兩個額外的點,以一個嚴格的寬容將做這項工作。如果你想檢測近似圓形的東西,我會計算一堆點,並使用平均誤差作爲標準。

+0

第一次計算僅顯示您有一個對稱對象 - 它可能是一個圓角框,而不是一個圓。 (+1)是有價值的 - 必要的,但仍然不夠,如果你能告訴我如何採樣除了解決問題的中點以外的點 –

+0

謝謝 - 我只看到你的更新,這是我想要的 –

1

貝塞爾曲線的端點是可能圓。如果是這樣,很容易重建原來的圈子。

另一種可能性是採取控制點的重心爲圓心,因爲控制點圍繞中心大概佈局對稱。從中心開始,您可以將半徑作爲距離中心最近的四個控制點的平均距離。

+0

但是可能不會有正好四個點,並且可能沒有完整的圓。 –

3

如果你所有的元素都是圓形的,那麼你可以通過path.getBBox()得到尺寸並從那裏生成一個圓。在這種情況下,我在考慮橢圓,但是你可以很容易地將其翻譯成實際circle元素:

var path = document.getElementById("circle_path"); 
var bbox = path.getBBox(); 

var rx = bbox.width/2; 
var ry = bbox.height/2; 
var cx = bbox.x + rx; 
var cy = bbox.y + ry; 

var ellipse = document.createElementNS(xmlns, "ellipse"); 
ellipse.setAttribute("fill", "none"); 
ellipse.setAttribute("stroke", "red"); 
ellipse.setAttribute("stroke-width", 0.1); 
ellipse.setAttribute("cx", cx); 
ellipse.setAttribute("cy", cy); 
ellipse.setAttribute("rx", rx); 
ellipse.setAttribute("ry", ry); 

svg.appendChild(ellipse); 

這裏你可以看到一個演示:

http://jsfiddle.net/nwHm6/

+0

+ 1努力創造jsfiddle。我已經更新了我的問題以清楚地說明我不知道我正在尋找一個圓圈 –

+0

但是,您只是想將圓形路徑轉換爲「circle」,或者您還想將諸如貝塞爾曲線之類的圓弧轉換爲圓弧路徑語法? – Duopixel

+0

兩者。我想知道它們是圓形和弧形。在我的應用程序中會出現很多弧線 –

0

可以將橢圓定義爲以(0,0),平移(2個參數),縮放(2個參數)和旋轉(1個參數)爲中心的單位圓。因此在每個弧上取5個點(t = 0 = 1/2),並求解這5個參數。接下來取中間四點(t =⅛⅜⅝⅞),並測試它們是否位於同一變換圓上。如果是的話,whoopee !,這是(變化的)圓的一部分。

之前和之後可能是另一個arcarcn。這些是同一個橢圓嗎?如果是的話,並且對齊的角度接觸,那麼將你對這些作品的描述聯繫在一起。