2012-11-16 154 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库。