2012-11-16 236 views
14

我有一套座標,我把它變成一個SVG路徑(使用立方貝塞爾,使其平滑)。當我申請一個特定筆畫的寬度,我得到以下結果(藍點是我的座標)cubic svg path with stroke widthsvg:生成'大綱路徑'

我所感興趣的是讓周圍的灰色形狀運行的一條路徑(如:隨便選點在灰色/白色邊框上,並繞着形狀旋轉,直到你回到起點爲止)。

我將如何去計算這樣的路徑?

以供參考,這是我的SVG信息:

<g> 
    <title>number 3</title> 
    <path d="m238,50c5.67569,-1.01351 11.8327,-3.8229 20.92029,-2.14724c8.68106,0.69732 14.21173,4.90255 18.07971,7.14724c6.23697,3.61945 13.47556,9.5931 15,18c1.07056,5.90372 1.17343,10.97649 -4,16c-6.76816,6.57204 -19.45392,9.57738 -25.69687,10.59046c-3.94836,0.64074 4.73492,3.29883 10.69687,5.40954c8.05417,2.85142 15,8 21,14c6,6 5.26578,10.94739 5.26578,17.03015c-2.4541,7.30975 -4.23343,11.08675 -11.26578,12.96985c-3.98279,1.0665 -11.92578,3.49756 -17,4c-8.95618,0.88684 -15.80411,2.97838 -26,0l-9.19197,-3.44464" id="svg_1" opacity="0.5" stroke-width="10" stroke-linejoin="round" stroke="#000000" fill="none"/> 
</g> 
+0

這是一個艱難的。你需要以編程的方式來做,還是你可以使用Illustrator或Inkscape? – Duopixel

+0

我需要以編程方式進行此操作,但是如果您可以告訴如何在程序中執行操作,那也是有用的......謝謝! – Hoff

+1

在Illustrator中,選擇路徑和菜單對象>展開外觀。我對這背後的數學只有一個模糊的概念,但這不是一個簡單的任務。 – Duopixel

回答

1

我創建svgContour功能,被認爲對於類似於此場景中,
所得輪廓偏移不相關的stroke-width值且必須設置爲參數的函數。

目前它會一次發現一個偏移端,但是每個端都運行一次就可以解決這個問題。

TLDR
實際上是通過svgContour你可以找到任何SVG圖形的輪廓,目前它不支持填充模式,但下一個目標之一是實現。 它依賴於getPathData()來獲得任何SVGGeometryElement的pathData, 然後這個數據經過三個階段:

  • redrawSteepCurve前提
    :不能獲得繪製平行於另一個beizer曲線只是抵消曲線的點/控制點,除非曲線足夠平坦(在這種情況下,視覺渲染將會很好)。這個方法需要一個SVGPathData,並且如果它發現了一個陡峭的曲線,它將它分開,直到它足夠平坦(返回一個視覺上等效的SVGPathData)。

  • contourPathData
    在這個階段,pathData在點dissambled,點連接在區段,每個區段被抵消,交點然後找到每個連續段(我們回到什麼是列表抵消點)。

  • 的drawLine
    這一階段從步驟2中的pathData從步驟1來放置點,最後得出的輪廓。

一個例子:

const path = document.querySelector('path') 
 

 
svgContour(path, 5)
svg { 
 
    width: 100vw; 
 
    height: 100vh 
 
}
<script src="https://cdn.rawgit.com/fracalo/svg-contour/master/dist/svg-contour.js"></script> 
 

 
<svg viewBox='300 0 100 200'> 
 
    <g> 
 
    <title>number 3</title> 
 
    <path d="m238,50c5.67569,-1.01351 11.8327,-3.8229 20.92029,-2.14724c8.68106,0.69732 14.21173,4.90255 18.07971,7.14724c6.23697,3.61945 13.47556,9.5931 15,18c1.07056,5.90372 1.17343,10.97649 -4,16c-6.76816,6.57204 -19.45392,9.57738 -25.69687,10.59046c-3.94836,0.64074 4.73492,3.29883 10.69687,5.40954c8.05417,2.85142 15,8 21,14c6,6 5.26578,10.94739 5.26578,17.03015c-2.4541,7.30975 -4.23343,11.08675 -11.26578,12.96985c-3.98279,1.0665 -11.92578,3.49756 -17,4c-8.95618,0.88684 -15.80411,2.97838 -26,0l-9.19197,-3.44464" 
 
    id="svg_1" opacity="0.5" stroke-width="10" stroke-linejoin="round" stroke="#000000" fill="none" /> 
 
    </g> 
 
</svg>

輪廓跟蹤!

+0

太棒了,謝謝! – Hoff

1

我不知道這是否解決您的問題。這取決於你想用大綱路徑做什麼。

PostScript具有計算描邊路徑的輪廓的功能,在填充描邊時它將產生與撫摸原始路徑相同的視覺輸出。但是,生成的路徑數據可能不如您期望的那麼優雅。

下面的PostScript程序(姑且稱之爲path2outlines.ps變成一個的PostScript路徑成「可填寫」 SVG路徑:讓

%! 
% First, we're converting to outlines. 
strokepath 

% This is just a string buffer 
/S 99 string def 

% This defines a procedure for printing coordinates to stdout 
/printCoordinates {  % coord* number command 
    print     % coord* number 
    array astore   % array 
    {      % coord 
    ()print   % coord 
    //S cvs    % string 
    print    % 
    }forall 
    (\n)print 
} bind def 

% This iterates over the path segments and prints the SVG path data. 
{2(M) printCoordinates} 
{2(L) printCoordinates} 
{6(C) printCoordinates} 
{(Z\n)print} 
pathforall 

quit 

你必須給它的數據文件像這樣(%註釋的開始)的調用這data.ps

%! 
% First, set up the graphics state parameters 
% Equivalent to stroke-width="10" 
10 setlinewidth 

% Equivalent to stroke-linejoin="round" (0 = miter, 1 = round, 2 = bevel) 
1 setlinejoin 

% Now, we're defining the path. 
% Use postfix notation, i.e. first coordinates, then command. 
% m/M = moveto 
% l = rlineto 
% L = lineto 
% c = rcurveto 
% C = curveto 

238 50 moveto 
5.67569 -1.01351 11.8327 -3.8229 20.92029 -2.14724 rcurveto 
8.68106 0.69732 14.21173 4.90255 18.07971 7.14724 rcurveto 
6.23697 3.61945 13.47556 9.5931 15 18 rcurveto 
1.07056 5.90372 1.17343 10.97649 -4 16 rcurveto 
-6.76816 6.57204 -19.45392 9.57738 -25.69687 10.59046 rcurveto 
-3.94836 0.64074 4.73492 3.29883 10.69687 5.40954 rcurveto 
8.05417 2.85142 15 8 21 14 rcurveto 
6 6 5.26578 10.94739 5.26578 17.03015 rcurveto 
-2.4541 7.30975 -4.23343 11.08675 -11.26578 12.96985 rcurveto 
-3.98279 1.0665 -11.92578 3.49756 -17 4 rcurveto 
-8.95618 0.88684 -15.80411 2.97838 -26 0 rcurveto 
-9.19197 -3.44464 rlineto 

,取決於您所使用的平臺,您可以使用Ghostscript的調用它有點類似:

gs -q data.ps path2outlines.ps > outlinePath.txt 

試一下,但我不確定你是否會滿意。輸出的複雜性可能會暗示問題的實際複雜性。特別是自相交的路徑是一個問題。

編輯(說到問題): 我相信在數學上不可能創建一條與給定Bézier曲線完全「平行」的Bézier曲線。

0

這是非常苛刻的。老實說,我懷疑你能寫出一個能夠做到這一點的sorce代碼,而沒有一個lib會爲你做。

這種技術有時被稱爲「緩衝」。就像在對象周圍創建緩衝區一樣。

如果您可以使用Programming lang C,那麼您應該查看LEDA庫。 在java中,我不知道任何東西,也許是GeoTools庫。