mozman / ezdxf

Python interface to DXF
https://ezdxf.mozman.at
MIT License
937 stars 191 forks source link

Case where union operation of clipping work as difference #1094

Closed MikhailFarbshteyn closed 6 months ago

MikhailFarbshteyn commented 6 months ago

Describe the bug Have a nice day! I found a bug with using clipping. In some case when I made union operetion with 2 regions it make them difference. Could you check this case?

To Reproduce please try this code

import json
from ezdxf.math import Vec2, clipping
from SPD.helper import drawing
from pathlib import Path

with open("SPD/regions.json", "r") as file:
    data = json.load(file)

Doc = ezdxf.new()

data_vecs = [[Vec2(pt[0], pt[1]) for pt in region] for region in data]

for region in data:
    Doc.modelspace().add_lwpolyline(points=region, close=True) # show raw data

unions = clipping.greiner_hormann_union(data_vecs[0], data_vecs[1])

for region in unions:
    Doc.modelspace().add_lwpolyline(points=region, close=True, dxfattribs={"color": ezdxf.colors.YELLOW}) # show clipping result

Doc.saveas("SPD/regions_test.dxf")

print(Path("SPD/regions_test.dxf").absolute())

regions.json FILE

[
  [
    [
      -18.900001889999952,
      1450.7000002308125
    ],
    [
      -18.900001889999952,
      1470.7351470734998
    ],
    [
      1278.90012789,
      1470.7351470734998
    ],
    [
      1278.90012789,
      1450.70001562087
    ],
    [
      1503.6001841952093,
      1450.7000156208703
    ],
    [
      1503.6001841952093,
      1388.3850000081884
    ],
    [
      1503.6001841952093,
      1388.3850000081884
    ],
    [
      1647.3246376764234,
      1388.3850000081884
    ],
    [
      1647.3246376764234,
      1548.1475422037274
    ],
    [
      1831.0471719722357,
      1548.1475422037274
    ],
    [
      1831.0471719722357,
      1388.3850000081884
    ],
    [
      1831.0471719722357,
      1388.3850000081884
    ],
    [
      1980.6216566984945,
      1388.3850000081884
    ],
    [
      1980.6216566984945,
      1224.6149999918116
    ],
    [
      1831.0471719722357,
      1224.6149999918116
    ],
    [
      1831.0471719722357,
      1160.3525263520064
    ],
    [
      1647.3246376764234,
      1160.3525263520064
    ],
    [
      1647.3246376764234,
      1160.3525263520064
    ],
    [
      1647.3246376764234,
      1224.6149999918116
    ],
    [
      1647.3246376764234,
      1224.6149999918116
    ],
    [
      1503.6001841952093,
      1224.6149999918116
    ],
    [
      1503.6001841952093,
      1162.2999997691875
    ],
    [
      1278.90012789,
      1162.2999997691877
    ],
    [
      1278.90012789,
      1162.2999997691877
    ],
    [
      1278.90012789,
      286.7000156208702
    ],
    [
      1503.6001841952093,
      286.70001562087026
    ],
    [
      1503.6001841952093,
      224.3850000081885
    ],
    [
      1503.6001841952093,
      224.3850000081885
    ],
    [
      1647.3246376764234,
      224.3850000081885
    ],
    [
      1647.3246376764234,
      384.1475422037275
    ],
    [
      1831.0471719722357,
      384.1475422037275
    ],
    [
      1831.0471719722357,
      224.3850000081885
    ],
    [
      1831.0471719722357,
      224.3850000081885
    ],
    [
      1980.6216566984945,
      224.3850000081885
    ],
    [
      1980.6216566984945,
      60.61499999181149
    ],
    [
      1831.0471719722357,
      60.614999991811544
    ],
    [
      1831.0471719722357,
      -3.6474736479937064
    ],
    [
      1647.3246376764234,
      -3.6474736479937064
    ],
    [
      1647.3246376764234,
      -3.6474736479937064
    ],
    [
      1647.3246376764234,
      60.61499999181149
    ],
    [
      1647.3246376764234,
      60.61499999181149
    ],
    [
      1503.6001841952093,
      60.61499999181149
    ],
    [
      1503.6001841952093,
      -1.7000002308124635
    ],
    [
      1278.90012789,
      -1.7000002308124635
    ],
    [
      1278.90012789,
      -1.7000002308124635
    ],
    [
      1278.90012789,
      -21.735002173499993
    ],
    [
      -18.900001890000045,
      -21.735002173499993
    ],
    [
      -18.900001890000045,
      -21.735002173499993
    ],
    [
      -18.900001890000045,
      -1.7000156208705448
    ],
    [
      -243.6001841952094,
      -1.7000156208702606
    ],
    [
      -243.6001841952094,
      -1.7000156208702606
    ],
    [
      -243.6001841952094,
      60.61499999181149
    ],
    [
      -243.6001841952094,
      60.61499999181149
    ],
    [
      -237.7502641782885,
      60.61499999181149
    ],
    [
      -237.7502641782885,
      224.3850000081885
    ],
    [
      -243.6001841952094,
      224.3850000081885
    ],
    [
      -243.6001841952094,
      286.70000023081246
    ],
    [
      -18.900001890000027,
      286.7000002308125
    ],
    [
      -18.900001890000027,
      286.7000002308125
    ],
    [
      -18.90000188999997,
      1162.2999843791297
    ],
    [
      -243.6001841952094,
      1162.2999843791297
    ],
    [
      -243.6001841952094,
      1162.2999843791297
    ],
    [
      -243.6001841952094,
      1450.7000002308125
    ],
    [
      -18.900001889999952,
      1450.7000002308125
    ]
  ],
  [
    [
      -392.2502641782885,
      1224.6149999918116
    ],
    [
      -237.7502641782885,
      1224.6149999918116
    ],
    [
      -237.7502641782885,
      1388.3850000081884
    ],
    [
      -392.2502641782885,
      1388.3850000081884
    ],
    [
      -392.2502641782885,
      1224.6149999918116
    ]
  ]
]

difference

mozman commented 6 months ago

UPDATE: the is_inside_polygon() function is incorrect!

There is a bug in the intersection function for parallel or collinear lines. If I "jiggle" the points a little, the result is correct:

def jiggle(points: list[Vec2]) -> list[Vec2]:
    return [Vec2(random.random(), random.random()) + p for p in points]

image