How do I detect overlapping SVG paths with python?

Viewed 125

The output of a CAD program I need to work with generates almost duplicate shapes. These shapes are close enough that a boolean operation (in Inkscape) results in nothing, but their path definition (the 'd' attribute) are different nonetheless.

An example file is this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   version="1.1"
   id="svg870"
   width="448.3017"
   height="1506.1682"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">
  <defs
     id="defs874" />
  <sodipodi:namedview
     id="namedview872"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageshadow="2"
     inkscape:pageopacity="0.0"
     inkscape:pagecheckerboard="0" />
  <inkscape:clipboard
     style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.99999874;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
     min="195.47421,-74.148449"
     max="643.77589,1432.0197"
     geom-min="196.03279,-73.64411"
     geom-max="643.27559,1431.3741" />
  <g
     id="g876"
     transform="matrix(3.7795276,0,0,3.7795276,-195.47421,74.148449)">
    <path
       d="m 168.24002,-17.616914 -18.24834,0.0922 -15.13588,0.48842 -20.75215,1.19729 -14.415133,1.15168 -14.450721,1.44134 -14.111416,1.68593 -13.79342,2.11608 11.30861,89.579874 11.214389,69.99748 10.470806,51.38623 0.0079,0.0379 5.258011,23.24563 4.054317,15.27122 0.005,0.0193 2.120057,8.55438 2.37826,16.61018 v 0.0193 l -2.4878,33.47204 -1.31276,17.82027 9.91756,2.14731 6.83633,4.81412 0.11621,0.1384 3.14973,6.21102 1.16623,9.2075 -0.003,0.20031 -1.6524,11.68519 -3.28401,12.81052 29.52192,11.7743 1.21877,-9.08706 4.85934,-11.10218 3.82709,-4.73665 2.52299,-11.68805 5.38247,-20.14799 4.4164,-10.72791 -0.003,-5.29166 -0.081,-160.36346 z"
       fill="#cccccc"
       stroke="#000000"
       id="path20"
       style="fill:none;stroke-width:0.264583" />
    <path
       d="m 168.24002,-17.616914 -18.24834,0.0922 -15.13588,0.48842 -20.75215,1.19729 -14.415133,1.15168 -14.450721,1.44134 -14.111416,1.68593 -13.79342,2.11608 11.30861,89.579874 11.214389,69.99748 10.47885,51.42412 5.258011,23.24563 4.059449,15.29046 2.120051,8.55437 2.37929,16.62963 -2.48779,33.47204 -1.31276,17.82027 9.91756,2.1473 6.95254,4.95252 3.14973,6.21102 1.16287,9.40781 -1.6524,11.6852 -3.28401,12.81051 29.52192,11.7743 1.21877,-9.08706 4.85934,-11.10218 3.82709,-4.73665 2.52299,-11.68805 5.38247,-20.14799 4.4164,-10.7279 -0.003,-5.29167 -0.081,-160.36346 z"
       fill="#cccccc"
       stroke="#000000"
       id="path36"
       style="fill:none;stroke-width:0.264583" />
    <path
       d="m 170.09184,-19.485004 -20.56889,0.17778 -15.53867,0.5475 -21.28273,1.27846 -14.792144,1.20923 -14.826721,1.49992 -14.492335,1.74562 -16.72334,2.56833 6.0289,46.54781 6.22999,44.739079 v 5.2e-5 l 5.48867,35.078223 6.307564,34.95159 10.907898,51.42428 2.7e-5,1.1e-4 5.464836,23.29045 4.191,15.29641 2.6e-5,5e-5 2.167388,8.44743 1.577551,8.07522 0.86913,8.09599 v 2e-5 l 0.0241,8.10363 -0.62722,8.18039 -2.127701,16.64885 -2.251472,20.3998 7.298053,1.05884 4.32081,1.22113 3.15581,1.71551 2.56218,2.39389 v 3e-5 l 1.47936,2.39313 1.03333,2.77709 0.77864,4.19627 0.10057,4.30773 v 0 l -0.62592,5.52627 -1.18928,5.5463 -4.18391,14.94666 36.12563,13.81366 0.94498,-2.47132 1.23294,-9.35913 1.79361,-5.45743 2.79363,-5.02062 3.26498,-4.04083 0.24328,-1.13546 2.5917,-11.99877 2.3554,-10.12261 2.98114,-9.87177 3.17328,-7.88053 H 170.2 l -0.002,-3.35664 -0.003,-5.22552 -0.081,-160.36309 z"
       fill="#cccccc"
       stroke="#000000"
       id="path30"
       style="fill:none;stroke-width:0.264583" />
    <path
       d="m 170.09184,-19.485004 -20.56889,0.17778 -15.53867,0.5475 -21.28273,1.27846 -14.792144,1.20923 -14.826721,1.49992 -14.492335,1.74562 -16.72334,2.56833 6.0289,46.54781 6.22999,44.739131 5.48867,35.078223 6.307564,34.95159 10.907925,51.42439 5.464836,23.29045 4.191026,15.29646 2.167388,8.44743 1.577551,8.07522 0.86913,8.09601 0.0241,8.10363 -0.62722,8.18039 -2.127701,16.64885 -2.251472,20.3998 7.298053,1.05884 4.32081,1.22113 3.15581,1.71551 2.56218,2.39392 1.47936,2.39313 1.03333,2.77709 0.77864,4.19627 0.10057,4.30773 -0.62592,5.52627 -1.18928,5.5463 -4.18391,14.94666 36.12563,13.81366 0.94498,-2.47132 1.23294,-9.35913 1.79361,-5.45743 2.79363,-5.02062 3.26498,-4.04083 0.24328,-1.13546 2.5917,-11.99877 2.3554,-10.12261 2.98114,-9.87177 3.17328,-7.88053 H 170.2 l -0.002,-3.35664 -0.003,-5.22552 -0.081,-160.36309 z"
       fill="#cccccc"
       stroke="#000000"
       id="path38"
       style="fill:none;stroke-width:0.264583" />
  </g>
</svg>

I'd like to eliminate the duplicate shapes - which I was trying to do by calculating intersections with svgpathtools like this:

from svgpathtools import svg2paths, parse_path
import sys

svg_file = sys.argv[1]

paths, attributes = svg2paths(svg_file)

for p in paths:
    print(str(p))

print(str(paths[0]) == str(paths[1])) # prints False

print(paths[1].intersect(paths[0]))   # throws error

which however throws an error - I suppose because the first segments are the same, and that would return an infinite number of intersection points:

Traceback (most recent call last):
  File "intersect.py", line 14, in <module>
    print(paths[1].intersect(paths[0]))
  File "/home/simone/.local/lib/python3.8/site-packages/svgpathtools/path.py", line 2760, in intersect
    for t1, t2 in seg1.intersect(seg2, tol=tol):
  File "/home/simone/.local/lib/python3.8/site-packages/svgpathtools/path.py", line 666, in intersect
    assert self != other_seg
AssertionError

What's the right way to do that?

0 Answers
Related