I need to intersect 2 SVG paths and get path with thier intersection.
It should work in browser or in Node.js (any of them, not both).
I need intersection, usage of clip-path
isn't ok.
If by some reason intersection will use transform
it's ok (I'll remove it myself).
I think there is a library for that, but I found only
- svg-intersections - returns array of points, but I need
path
- path-intersection - can't make it working - by some reason it always returns an empty array
- snap.svg - seems to provide something usefull, but I don't understand how to use that
like in Difference and Intersection of paths in SVG using Snap.path.intersection
For example intersecting following paths:
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
I want to get something like:
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
Here is interactive snippet with path
s from the example (ignore colors - they are for clarity) - need to get Intersection from #path1
and #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>Input</label>
<label for=out>Intersection</label>
<label for=cp>Clip</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>
Example with 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>
We can do it with PaperJS boolean operations, which can operate with SVG paths.
PaperJS has 5 different boolean operations:
exclude
,subtract
,unite
,intersect
,divide
and we will use one from them with the nameintersect
. This operations are also functions with the same name and they returnitem
object, which has the functionexportSVG()
. It returns trueSVG Path element
, which has a new shape of both paths intersection.Example of correct solution
Useful links:
Snap.svg seems to have the basic functions needed to do this. Some of them are be a bit akward, but this might be the direction to go. Please take this as pseudocode and not as working as-is: