Svg: создать 'контурный путь'

У меня есть набор координат, которые я превращаю в путь 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>

Ответ 1

Я создал функцию svgContour, которая считается для сценариев, подобных этому,
результирующее смещение контура не связано с значением stroke-width и должно быть установлено как параметр для функции.

В настоящий момент он найдет одну сторону смещения за раз, но запустив ее один раз на каждой стороне, вы можете решить эту проблему.

TL;DR
Фактически через svgContour вы можете найти контур любых svg-фигур, в настоящее время он не поддерживает режимы заполнения, но одна из следующих целей - реализовать это. он полагается на getPathData(), чтобы получить pathData любого SVGGeometryElement, то эти данные проходят через три этапа:

  • redrawSteepCurve
    Помещение: рисование кривой бисера параллельно другому не получается просто компенсировать точки/контрольные точки кривой , если кривая достаточно плоская (в этом случае визуальная рендеринг будет прекрасной); этот метод принимает SVGPathData, и в случае, если он находит крутую кривую, он разбивает его до тех пор, пока он не станет достаточно плоским (верните визуально эквивалентные SVGPathData).

  • contourPathData​​STRONG >
    На этом этапе pathData размывается в точках, точки связаны в сегментах, каждый сегмент смещен, точка пересечения затем определяется для каждого смежного сегмента (мы возвращаем список смещенных точек).

  • 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>

Ответ 2

Я не уверен, решит ли это вашу проблему. Это зависит от того, что вы хотите сделать с контуром контура.

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

Попробуйте, но я не уверен, будете ли вы удовлетворены. Сложность вывода может дать нам подсказку о реальной сложности проблемы. Особенно самопересекающиеся пути являются проблемой.

Изменить (говоря о проблемах): Я считаю, что в общем случае математически невозможно создать кривую Безье, которая идеально "параллельна" данной кривой Безье.

Ответ 3

Это очень требовательный. Честно говоря, я сомневаюсь, что вы сможете написать код sorce, который сделает это, без lib, который сделает это за вас.

Эта техника иногда называется "буфером". Как создать буфер вокруг объекта.

Если вы можете использовать Программирование lang C, вам следует посмотреть библиотеку LEDA. В java я ничего не знаю, возможно, GeoTools lib.