Cura: intersectsPolygon function crash

Created on 7 Dec 2019  路  12Comments  路  Source: Ultimaker/Cura

Application version
Cura 4.4.0
CuraEngine 4.4.0

Platform
Arch Linux
Qt 5.13.2
PyQt 5.13.2
Python 3.8

Printer
Ender 3 Pro

Reproduction steps

  1. Manually update the PKGBUILDs for cura, curaengine, uranium and arcus
  2. Start Cura
  3. Load an STL file (Should crash with every STL)

Actual results
Crash with an error message

Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/cura/PlatformPhysics.py", line 53, in _onChangeTimerFinished
    build_volume.updateNodeBoundaryCheck()
  File "/usr/lib/python3.8/site-packages/cura/BuildVolume.py", line 258, in updateNodeBoundaryCheck
    if node.collidesWithAreas(self.getDisallowedAreas()):
  File "/usr/lib/python3.8/site-packages/cura/Scene/CuraSceneNode.py", line 98, in collidesWithAreas
    overlap = convex_hull.intersectsPolygon(area)
  File "/usr/lib/python3.8/site-packages/UM/Math/Polygon.py", line 183, in intersectsPolygon
    ret_size = (polygon_intersection.bounds[2] - polygon_intersection.bounds[0],
IndexError: tuple index out of range

Additional information
Tracing this down in UM.Math.Polygon shows that the polygon_intersection conditional does not work correctly in line 182.
In line 161 this expression is used: if polygon_union.area == 0: which probably should also be adapted to if polygon_union.area > 0: in line 182 (as this also resolves the crash).

Needs Info Bug

Most helpful comment

--- Polygon.py  2019-12-12 16:38:55.083688740 +0100
+++ Polygon.py  2019-12-12 16:39:53.600398137 +0100
@@ -177,10 +177,9 @@
             return None
         if not (polygon_me.is_valid and polygon_other.is_valid):  # If not valid
             return None
-
         polygon_intersection = polygon_me.intersection(polygon_other)
         ret_size = None
-        if polygon_intersection:
+        if polygon_intersection.area > 0:
             ret_size = (polygon_intersection.bounds[2] - polygon_intersection.bounds[0],
                         polygon_intersection.bounds[3] - polygon_intersection.bounds[1],
                         )

Hope this helps

All 12 comments

Unable to reproduce this error here, running Cura, Uranium, CuraEngine and libArcus from source on latest master. I wonder what your set-up has differently. Perhaps it's only happening in Python 3.8? I'm still on 3.7. Can't imagine that would make a difference like this though. Perhaps Arch is a bit behind and ended up in a weird state when this was broken?

The expression polygon_union.area == 0 seems correct to me since this is meant as an edge case handling if we create a polygon that has no area but still has vertices (like a single point). Perhaps such a check needs to be done in the intersection code as well?

I get the same error with Cura 4.3.0 and 4.4.0 on fully updated arch linux

Arch linux, Cura 4.3.0 and python 3.8. Same problem:

Traceback (most recent call last):

  File "/usr/lib/python3.8/site-packages/cura/PlatformPhysics.py", line 53, in _onChangeTimerFinished
    build_volume.updateNodeBoundaryCheck()
  File "/usr/lib/python3.8/site-packages/cura/BuildVolume.py", line 262, in updateNodeBoundaryCheck
    if node.collidesWithAreas(self.getDisallowedAreas()):
  File "/usr/lib/python3.8/site-packages/cura/Scene/CuraSceneNode.py", line 98, in collidesWithAreas
    overlap = convex_hull.intersectsPolygon(area)
  File "/usr/lib/python3.8/site-packages/UM/Math/Polygon.py", line 184, in intersectsPolygon
    ret_size = (polygon_intersection.bounds[2] - polygon_intersection.bounds[0],
IndexError: tuple index out of range

Same issue here
Cura 4.4-PPA
Qt 5.12.5
PyQt 5.12.3

2019-12-12 09:54:40,456 - INFO - [Thread-3] STLReader.STLReader.load_file [46]: Using NumPy-STL to load STL data.
/usr/lib/python3/dist-packages/UM/Mesh/MeshData.py:476: RuntimeWarning: invalid value encountered in true_divide
n[:, 0] /= l
/usr/lib/python3/dist-packages/UM/Mesh/MeshData.py:477: RuntimeWarning: invalid value encountered in true_divide
n[:, 1] /= l
/usr/lib/python3/dist-packages/UM/Mesh/MeshData.py:478: RuntimeWarning: invalid value encountered in true_divide
n[:, 2] /= l
2019-12-12 09:54:40,458 - DEBUG - [Thread-3] UM.Mesh.MeshData.calculateNormalsFromVertices [484]: Calculating normals took 0.00035643577575683594 seconds
2019-12-12 09:54:40,458 - DEBUG - [Thread-3] STLReader.STLReader._read [97]: Loaded a mesh with 8598 vertices
2019-12-12 09:54:40,462 - DEBUG - [Thread-3] UM.Mesh.MeshData.approximateConvexHull [441]: approximateConvexHull(target_count=1024) Calculating 3D convex hull took 0.003796100616455078 seconds. 107 input vertices. 107 output vertices.
2019-12-12 09:54:40,464 - DEBUG - [Thread-3] UM.FileHandler.ReadFileJob.run [71]: Loading file took 0.0 seconds
2019-12-12 09:54:40,471 - DEBUG - [Thread-3] UM.Mesh.MeshData.approximateConvexHull [441]: approximateConvexHull(target_count=1024) Calculating 3D convex hull took 0.00749659538269043 seconds. 107 input vertices. 107 output vertices.
2019-12-12 09:54:40,502 - DEBUG - [MainThread] UM.Operations.OperationStack.push [67]: , took 9ms
2019-12-12 09:54:40,507 - DEBUG - [MainThread] UM.View.GL.ShaderProgram.load [56]: Loading shader file [/usr/share/cura/resources/shaders/transparent_object.shader]...
/usr/lib/python3/dist-packages/cura/Settings/PerObjectContainerStack.py:48: DeprecationWarning: is deprecated (since 4.4): Please use extruderList instead.
if limit_to_extruder is not None and limit_to_extruder != "-1" and limit_to_extruder in global_stack.extruders:
2019-12-12 09:54:40,636 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [61]: An uncaught error has occurred!
2019-12-12 09:54:40,636 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: Traceback (most recent call last):
2019-12-12 09:54:40,637 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/cura/BuildVolume.py", line 156, in _onSceneChangeTimerFinished
2019-12-12 09:54:40,637 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: self.rebuild()
2019-12-12 09:54:40,637 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/cura/BuildVolume.py", line 536, in rebuild
2019-12-12 09:54:40,637 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: self.updateNodeBoundaryCheck()
2019-12-12 09:54:40,637 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/cura/BuildVolume.py", line 258, in updateNodeBoundaryCheck
2019-12-12 09:54:40,637 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: if node.collidesWithAreas(self.getDisallowedAreas()):
2019-12-12 09:54:40,637 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/cura/Scene/CuraSceneNode.py", line 98, in collidesWithAreas
2019-12-12 09:54:40,637 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: overlap = convex_hull.intersectsPolygon(area)
2019-12-12 09:54:40,638 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/UM/Math/Polygon.py", line 187, in intersectsPolygon
2019-12-12 09:54:40,638 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: ret_size = (polygon_intersection.bounds[2] - polygon_intersection.bounds[0],
2019-12-12 09:54:40,638 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: IndexError: tuple index out of range
2019-12-12 09:54:40,651 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [61]: An uncaught error has occurred!
2019-12-12 09:54:40,651 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: Traceback (most recent call last):
2019-12-12 09:54:40,651 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/cura/PlatformPhysics.py", line 53, in _onChangeTimerFinished
2019-12-12 09:54:40,651 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: build_volume.updateNodeBoundaryCheck()
2019-12-12 09:54:40,651 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/cura/BuildVolume.py", line 258, in updateNodeBoundaryCheck
2019-12-12 09:54:40,651 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: if node.collidesWithAreas(self.getDisallowedAreas()):
2019-12-12 09:54:40,651 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/cura/Scene/CuraSceneNode.py", line 98, in collidesWithAreas
2019-12-12 09:54:40,652 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: overlap = convex_hull.intersectsPolygon(area)
2019-12-12 09:54:40,652 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: File "/usr/lib/python3/dist-packages/UM/Math/Polygon.py", line 187, in intersectsPolygon
2019-12-12 09:54:40,652 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: ret_size = (polygon_intersection.bounds[2] - polygon_intersection.bounds[0],
2019-12-12 09:54:40,652 - CRITICAL - [MainThread] cura.CrashHandler.__init__ [64]: IndexError: tuple index out of range

Tracing this down in UM.Math.Polygon shows that the polygon_intersection conditional does not work correctly in line 182.
In line 161 this expression is used: if polygon_union.area == 0: which probably should also be adapted to if polygon_union.area > 0: in line 182 (as this also resolves the crash).

Can you provide a patch, i could test that here.

--- Polygon.py  2019-12-12 16:38:55.083688740 +0100
+++ Polygon.py  2019-12-12 16:39:53.600398137 +0100
@@ -177,10 +177,9 @@
             return None
         if not (polygon_me.is_valid and polygon_other.is_valid):  # If not valid
             return None
-
         polygon_intersection = polygon_me.intersection(polygon_other)
         ret_size = None
-        if polygon_intersection:
+        if polygon_intersection.area > 0:
             ret_size = (polygon_intersection.bounds[2] - polygon_intersection.bounds[0],
                         polygon_intersection.bounds[3] - polygon_intersection.bounds[1],
                         )

Hope this helps

--- Polygon.py    2019-12-12 16:38:55.083688740 +0100
+++ Polygon.py    2019-12-12 16:39:53.600398137 +0100
@@ -177,10 +177,9 @@
             return None
         if not (polygon_me.is_valid and polygon_other.is_valid):  # If not valid
             return None
-
         polygon_intersection = polygon_me.intersection(polygon_other)
         ret_size = None
-        if polygon_intersection:
+        if polygon_intersection.area > 0:
             ret_size = (polygon_intersection.bounds[2] - polygon_intersection.bounds[0],
                         polygon_intersection.bounds[3] - polygon_intersection.bounds[1],
                         )

Hope this helps

I can confirm that patching
/usr/lib/python3/dist-packages/UM/Math/Polygon.py
with the abova patch fixes the issue for
cura-4.4~201910291625~rev4146~pkg325~ubuntu20.04.1

Fun fact: The AppImage version of the 4.4 release does NOT throw the error in the first place ;)

@dgiebert wanna file a PR? ;)

Also running from source doesn't throw the error.

I'm worried that with that patch it could crash if polygon_me.intersection returns None, so be sure to also check for that.

I got the same issue even after updating to cura=4.4.0-1 on Arch.

Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/cura/BuildVolume.py", line 684, in _onSettingChangeTimerFinished
    self.rebuild()
  File "/usr/lib/python3.8/site-packages/cura/BuildVolume.py", line 536, in rebuild
    self.updateNodeBoundaryCheck()
  File "/usr/lib/python3.8/site-packages/cura/BuildVolume.py", line 258, in updateNodeBoundaryCheck
    if node.collidesWithAreas(self.getDisallowedAreas()):
  File "/usr/lib/python3.8/site-packages/cura/Scene/CuraSceneNode.py", line 98, in collidesWithAreas
    overlap = convex_hull.intersectsPolygon(area)
  File "/usr/lib/python3.8/site-packages/UM/Math/Polygon.py", line 184, in intersectsPolygon
    ret_size = (polygon_intersection.bounds[2] - polygon_intersection.bounds[0],
IndexError: tuple index out of range

The AppImage version works, but the Arch package is broken since the update to Python 3.8.

@Ghostkeeper you can add a check for both,
if polygon_intersection and polygon_intersection.area > 0:

Since Cura will use python 3.8 eventually, fixing this is worthwile. @rephlex, could you create a pull request for this?

Nevermind that. I made the change to Uranium. Please try again with the latest sources. It should be fixed!

For me the behaviour is exactly the same on Python 3.7. I can't test with 3.8 right now (as I'm only using that on a computer at home). Honestly I think the problem is more related to the version of Geos you're using or the Python bindings for that, though.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mnswamp1 picture mnswamp1  路  3Comments

thopiekar picture thopiekar  路  3Comments

DmitryBychkov picture DmitryBychkov  路  3Comments

jellewie picture jellewie  路  3Comments

mubarak111nsu picture mubarak111nsu  路  3Comments