Получить пересечение двух путей

215
26 апреля 2018, 10:09

Нужно пересечь два svg-пути и получить путь, представляющий их пересечение.
Не важно, будет это работать в браузере или в node.js.
Нужно именно пересечение, использование clip-path не подходит.
Если после пересечения вдруг понадобится transform, то не страшно (сам его уберу).

Думаю, для этого уже есть какая-нибудь библиотека, но нашёл только

  • svg-intersections - возвращает массив точек пересечения, а мне надо path
  • path-intersection - что-то у меня вообще не взлетела - всегда получается пустой массив
  • snap.svg - вроде даёт то-то полезное, но я не пойму, как это использовать

Например, при пересечении

M 24.379464,51.504463 23.434524,23.156249 38.742559,12.572916 c 0,0 29.860118,-9.0714281 17.00893,0.755953 -12.851191,9.82738 13.229166,19.465774 13.229166,19.465774 z
m 32.883928,0.28869028 c 0,0 -15.686011,1.51190452 -8.504463,7.18154712 7.181546,5.6696426 50.270836,30.0491076 26.458332,42.3333336 -23.8125,12.284226 47.058036,14.174107 47.058036,14.174107 z

должно получиться (примерно)

M 43.943359 11.123047 C 40.995759 11.900151 38.742188 12.572266 38.742188 12.572266 L 35.236328 14.996094 C 44.091432999999995 21.21816 55.052161 29.822765 57.455078 37.628906 L 66.939453 33.650391 63.632812 30.410156 C 58.77426 27.95814 52.364322 23.85552 52.214844 19.224609 L 43.943359 11.123047 z

Вот интерактивный сниппет с путями из примера (на цвета внимание не обращать - они просто для наглядности) - надо получить путь Пересечение из #path1 и #path2:

svg { width: 10em; width: 100vmin; outline: 1px dotted blue; display: none; } 
input { display: none; } 
label { width: 10em; float: left; clear: left; cursor: pointer; line-height: 2em; margin: 0 .5em .25em 0; padding: 0 .25em; border: 1px solid; } 
:checked + * + * + label { background: antiquewhite; color: blue; } 
:checked + * + * + * + * + * + svg { display: inline-block; }
<input type=radio name=svg id=in checked> 
<input type=radio name=svg id=out> 
<input type=radio name=svg id=cp> 
 
<label for=in>Данные</label> 
<label for=out>Пересечение</label> 
<label for=cp>Обрезка</label> 
 
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="22 0 76 64"> 
  <path id="path1" 
    style="fill:rgba(255,0,0,.5); stroke:red;stroke-width:0.26458332px;" 
    d="M 24.379464,51.504463 23.434524,23.156249 38.742559,12.572916 c 0,0 29.860118,-9.0714281 17.00893,0.755953 -12.851191,9.82738 13.229166,19.465774 13.229166,19.465774 z" 
  /> 
  <path id="path2" 
    style="fill:rgba(0,255,0,.5);stroke:green;stroke-width:0.26458332px;" 
    d="m 32.883928,0.28869028 c 0,0 -15.686011,1.51190452 -8.504463,7.18154712 7.181546,5.6696426 50.270836,30.0491076 26.458332,42.3333336 -23.8125,12.284226 47.058036,14.174107 47.058036,14.174107 z" 
  /> 
</svg> 
 
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="22 0 76 64"> 
  <path 
    style="fill:rgba(0,0,255,.5);stroke:blue;stroke-width:0.26458332px;" 
    d="M 43.943359 11.123047 C 40.995759 11.900151 38.742188 12.572266 38.742188 12.572266 L 35.236328 14.996094 C 44.091432999999995 21.21816 55.052161 29.822765 57.455078 37.628906 L 66.939453 33.650391 63.632812 30.410156 C 58.77426 27.95814 52.364322 23.85552 52.214844 19.224609 L 43.943359 11.123047 z" 
  /> 
</svg> 
 
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="22 0 76 64"> 
  <clipPath id="clip2"> 
    <use xlink:href="#path2" /> 
  </clipPath> 
  <use xlink:href="#path1" clip-path="url(#clip2)" /> 
</svg>

Пример со snap.svg

var p1 = "M 24.379464,51.504463 23.434524,23.156249 38.742559,12.572916 c 0,0 29.860118,-9.0714281 17.00893,0.755953 -12.851191,9.82738 13.229166,19.465774 13.229166,19.465774 z" 
var p2 = "m 32.883928,0.28869028 c 0,0 -15.686011,1.51190452 -8.504463,7.18154712 7.181546,5.6696426 50.270836,30.0491076 26.458332,42.3333336 -23.8125,12.284226 47.058036,14.174107 47.058036,14.174107 z" 
 
var intersection = Snap.path.intersection(p1, p2) 
 
console.log(intersection)
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
<script src=//cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js></script>

PS: Этот вопрос на английском.

READ ALSO
Связать значение ячеек таблицы с div Javascript

Связать значение ячеек таблицы с div Javascript

Есть таблица, имеющая 4 столбцаЕсть скрипт, меняющий высоту div в зависимости от значения в ячейках

263
Обработка массива обьектов

Обработка массива обьектов

Как можно обработать массив обьектов, чтобы суммировать все поля сost (из Detail) со статусами true при совпадении свойства country? Спасибо!

239
Простое регулярное выражение на javascript [требует правки]

Простое регулярное выражение на javascript [требует правки]

Можно, пожалуйста, пример регулярки на js, jQuery, например, для текста [A-Za-z]+На php это очень легко делать, а с js что-то не как не поймиу что куда (

165
Проблема определением наличия слова

Проблема определением наличия слова

Есть переменная val с содержимым 285 кривой или ровный %Как определить имеется ли слово в переменной val?

219