svg:生成'大纲路径'

时间:2012-11-16 12:35:26

标签: vector svg coordinates shapes

我有一组坐标,我将其转换为svg路径(使用立方贝塞尔曲线使其平滑)。当我应用一定的笔画宽度时,我得到以下结果(蓝点是我的坐标)cubic svg path with stroke width

我感兴趣的是获得一条围绕灰色形状的路径(例如:选择灰色/白色边框上的任意点,然后绕着形状转动,直到你回到原点起点)。

我将如何计算这样的路径?

供参考,这是我的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>

3 个答案:

答案 0 :(得分: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曲线。

答案 1 :(得分:1)

我创建了svgContour函数,该函数被认为是与此类似的场景,
生成的轮廓偏移量与stroke-width值无关,必须设置为函数的参数。

目前它会一次找到一个偏移方,但每侧运行一次就可以解决这个问题。

<强> TLDR
实际上通过svgContour你可以找到任何svg形状的轮廓,目前它不支持填充模式,但下一个目标之一是实现它。 它依赖于getPathData()来获取任何SVGGeometryElement的pathData, 那么这些数据分为三个阶段:

  • <强> redrawSteepCurve
    前提:绘制一条平行于另一个的beizer曲线,只是偏移曲线的点/控制点,除非曲线足够平坦(在这种情况下,视觉渲染会很好) );这个方法接受一个SVGPathData,如果它找到一条陡峭的曲线,它会将它分开,直到它足够平坦(返回一个视觉上等效的SVGPathData)。

  • <强> contourPathData
    在这个阶段,pathData被分解为点,点以段连接,每个段被偏移,然后为每个连续的段找到一个交叉点(我们得到的是一个偏移点列表)。

  • <强>的drawLine
    此阶段将步骤2中的点放在来自步骤1的pathData中,最后绘制轮廓。

一个例子:

&#13;
&#13;
const path = document.querySelector('path')

svgContour(path, 5)
&#13;
svg {
  width: 100vw;
  height: 100vh
}
&#13;
<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>
&#13;
&#13;
&#13;

跟踪轮廓!

答案 2 :(得分:-1)

这非常苛刻。老实说,我怀疑你是否能够编写一个可以做到这一点的代码,而不会有一个可以为你做的lib。

此技术有时称为“缓冲区”。就像在对象周围创建缓冲区一样。

如果您可以使用Programming lang C,那么您应该查看LEDA库。 在java中我什么都不知道,也许是GeoTools lib。