mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-19 12:47:49 -06:00
Better handling of degenerate convex hull cases.
Contributes to CURA-1504
This commit is contained in:
parent
7e3dd3d443
commit
5f638f6e69
2 changed files with 42 additions and 38 deletions
|
@ -130,46 +130,48 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
||||||
return rounded_hull
|
return rounded_hull
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if not self._node.getMeshData():
|
rounded_hull = None
|
||||||
return None
|
if self._node.getMeshData():
|
||||||
mesh = self._node.getMeshData()
|
mesh = self._node.getMeshData()
|
||||||
world_transform = self._node.getWorldTransformation()
|
world_transform = self._node.getWorldTransformation()
|
||||||
|
|
||||||
# Check the cache
|
# Check the cache
|
||||||
if mesh is self._2d_convex_hull_mesh and world_transform == self._2d_convex_hull_mesh_world_transform:
|
if mesh is self._2d_convex_hull_mesh and world_transform == self._2d_convex_hull_mesh_world_transform:
|
||||||
# Logger.log('d', 'Cache hit in _compute2DConvexHull mesh path')
|
# Logger.log('d', 'Cache hit in _compute2DConvexHull mesh path')
|
||||||
return self._2d_convex_hull_mesh_result
|
return self._2d_convex_hull_mesh_result
|
||||||
|
|
||||||
vertex_data = mesh.getConvexHullTransformedVertices(world_transform)
|
vertex_data = mesh.getConvexHullTransformedVertices(world_transform)
|
||||||
# Don't use data below 0.
|
# Don't use data below 0.
|
||||||
# TODO; We need a better check for this as this gives poor results for meshes with long edges.
|
# TODO; We need a better check for this as this gives poor results for meshes with long edges.
|
||||||
vertex_data = vertex_data[vertex_data[:,1] >= 0]
|
vertex_data = vertex_data[vertex_data[:,1] >= 0]
|
||||||
|
|
||||||
# Round the vertex data to 1/10th of a mm, then remove all duplicate vertices
|
if len(vertex_data) >= 4:
|
||||||
# This is done to greatly speed up further convex hull calculations as the convex hull
|
# Round the vertex data to 1/10th of a mm, then remove all duplicate vertices
|
||||||
# becomes much less complex when dealing with highly detailed models.
|
# This is done to greatly speed up further convex hull calculations as the convex hull
|
||||||
vertex_data = numpy.round(vertex_data, 1)
|
# becomes much less complex when dealing with highly detailed models.
|
||||||
|
vertex_data = numpy.round(vertex_data, 1)
|
||||||
|
|
||||||
vertex_data = vertex_data[:, [0, 2]] # Drop the Y components to project to 2D.
|
vertex_data = vertex_data[:, [0, 2]] # Drop the Y components to project to 2D.
|
||||||
|
|
||||||
# Grab the set of unique points.
|
# Grab the set of unique points.
|
||||||
#
|
#
|
||||||
# This basically finds the unique rows in the array by treating them as opaque groups of bytes
|
# This basically finds the unique rows in the array by treating them as opaque groups of bytes
|
||||||
# which are as long as the 2 float64s in each row, and giving this view to numpy.unique() to munch.
|
# which are as long as the 2 float64s in each row, and giving this view to numpy.unique() to munch.
|
||||||
# See http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array
|
# See http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array
|
||||||
vertex_byte_view = numpy.ascontiguousarray(vertex_data).view(
|
vertex_byte_view = numpy.ascontiguousarray(vertex_data).view(
|
||||||
numpy.dtype((numpy.void, vertex_data.dtype.itemsize * vertex_data.shape[1])))
|
numpy.dtype((numpy.void, vertex_data.dtype.itemsize * vertex_data.shape[1])))
|
||||||
_, idx = numpy.unique(vertex_byte_view, return_index=True)
|
_, idx = numpy.unique(vertex_byte_view, return_index=True)
|
||||||
vertex_data = vertex_data[idx] # Select the unique rows by index.
|
vertex_data = vertex_data[idx] # Select the unique rows by index.
|
||||||
|
|
||||||
hull = Polygon(vertex_data)
|
hull = Polygon(vertex_data)
|
||||||
|
|
||||||
# First, calculate the normal convex hull around the points
|
if len(vertex_data) >= 4:
|
||||||
convex_hull = hull.getConvexHull()
|
# First, calculate the normal convex hull around the points
|
||||||
|
convex_hull = hull.getConvexHull()
|
||||||
|
|
||||||
# Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
|
# Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
|
||||||
# This is done because of rounding errors.
|
# This is done because of rounding errors.
|
||||||
rounded_hull = convex_hull.getMinkowskiHull(Polygon(numpy.array([[-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5], [0.5, -0.5]], numpy.float32)))
|
rounded_hull = convex_hull.getMinkowskiHull(Polygon(numpy.array([[-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5], [0.5, -0.5]], numpy.float32)))
|
||||||
|
|
||||||
# Store the result in the cache
|
# Store the result in the cache
|
||||||
self._2d_convex_hull_mesh = mesh
|
self._2d_convex_hull_mesh = mesh
|
||||||
|
|
|
@ -39,9 +39,10 @@ class ConvexHullNode(SceneNode):
|
||||||
self._convex_hull_head_mesh = None
|
self._convex_hull_head_mesh = None
|
||||||
self._hull = hull
|
self._hull = hull
|
||||||
|
|
||||||
hull_mesh = self.createHullMesh(self._hull.getPoints())
|
if self._hull:
|
||||||
if hull_mesh:
|
hull_mesh = self.createHullMesh(self._hull.getPoints())
|
||||||
self.setMeshData(hull_mesh)
|
if hull_mesh:
|
||||||
|
self.setMeshData(hull_mesh)
|
||||||
convex_hull_head = self._node.callDecoration("getConvexHullHead")
|
convex_hull_head = self._node.callDecoration("getConvexHullHead")
|
||||||
if convex_hull_head:
|
if convex_hull_head:
|
||||||
self._convex_hull_head_mesh = self.createHullMesh(convex_hull_head.getPoints())
|
self._convex_hull_head_mesh = self.createHullMesh(convex_hull_head.getPoints())
|
||||||
|
@ -76,9 +77,10 @@ class ConvexHullNode(SceneNode):
|
||||||
self._shader.setUniformValue("u_color", self._color)
|
self._shader.setUniformValue("u_color", self._color)
|
||||||
|
|
||||||
if self.getParent():
|
if self.getParent():
|
||||||
renderer.queueNode(self, transparent = True, shader = self._shader, backface_cull = True, sort = -8)
|
if self.getMeshData():
|
||||||
if self._convex_hull_head_mesh:
|
renderer.queueNode(self, transparent = True, shader = self._shader, backface_cull = True, sort = -8)
|
||||||
renderer.queueNode(self, shader = self._shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
|
if self._convex_hull_head_mesh:
|
||||||
|
renderer.queueNode(self, shader = self._shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue