From 8e6dd2486f5bb6a6153cdc6f91971064ddbd9db3 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 14 Jul 2015 16:41:59 +0200 Subject: [PATCH] Groups now also have a convexHull --- cura/ConvexHullDecorator.py | 28 ++++++++++++++++++++++ cura/ConvexHullJob.py | 47 +++++++++++++++++++++++++++++-------- cura/ConvexHullNode.py | 6 ++--- cura/PlatformPhysics.py | 25 ++++++++++++-------- 4 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 cura/ConvexHullDecorator.py diff --git a/cura/ConvexHullDecorator.py b/cura/ConvexHullDecorator.py new file mode 100644 index 0000000000..ed0b2c890f --- /dev/null +++ b/cura/ConvexHullDecorator.py @@ -0,0 +1,28 @@ +from UM.Scene.SceneNodeDecorator import SceneNodeDecorator + +class ConvexHullDecorator(SceneNodeDecorator): + def __init__(self): + super().__init__() + self._convex_hull = None + self._convex_hull_node = None + self._convex_hull_job = None + + def getConvexHull(self): + return self._convex_hull + + def setConvexHull(self, hull): + self._convex_hull = hull + + def getConvexHullJob(self): + return self._convex_hull_job + + def setConvexHullJob(self, job): + self._convex_hull_job = job + + def getConvexHullNode(self): + return self._convex_hull_node + + def setConvexHullNode(self, node): + self._convex_hull_node = node + + \ No newline at end of file diff --git a/cura/ConvexHullJob.py b/cura/ConvexHullJob.py index 6ee1b1abe6..c639528ec2 100644 --- a/cura/ConvexHullJob.py +++ b/cura/ConvexHullJob.py @@ -16,20 +16,47 @@ class ConvexHullJob(Job): self._node = node def run(self): - if not self._node or not self._node.getMeshData(): + if not self._node: return + ## If the scene node is a group, use the hull of the children to calculate its hull. + if self._node.callDecoration("isGroup"): + hull = Polygon(numpy.zeros((0, 2), dtype=numpy.int32)) + for child in self._node.getChildren(): + child_hull = child.callDecoration("getConvexHull") + if child_hull: + hull.setPoints(numpy.append(hull.getPoints(), child_hull.getPoints(), axis = 0)) + + if hull.getPoints().size < 3: + self._node.callDecoration("setConvexHull", None) + self._node.callDecoration("setConvexHullJob", None) + return + + else: + if not self._node.getMeshData(): + return + mesh = self._node.getMeshData() + vertex_data = mesh.getTransformed(self._node.getWorldTransformation()).getVertices() - mesh = self._node.getMeshData() - vertex_data = mesh.getTransformed(self._node.getWorldTransformation()).getVertices() - - hull = Polygon(numpy.rint(vertex_data[:, [0, 2]]).astype(int)) - + hull = Polygon(numpy.rint(vertex_data[:, [0, 2]]).astype(int)) + # First, calculate the normal convex hull around the points hull = hull.getConvexHull() + #print("hull: " , self._node.callDecoration("isGroup"), " " , hull.getPoints()) # Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull. hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32))) - + hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot()) - - self._node._convex_hull = hull - delattr(self._node, "_convex_hull_job") + self._node.callDecoration("setConvexHullNode", hull_node) + self._node.callDecoration("setConvexHull", hull) + self._node.callDecoration("setConvexHullJob", None) + #if self._node.getParent().callDecoration("isGroup"): + # if self._node.getParent().callDecoration("getConvexHull"): + + # self._node.getParent().callDecoration("getConvexHullNode").setParent(None) + # self._node.getParent().callDecoration("setConvexHull", None) + # self._node.getParent().callDecoration("setConvexHullJob", None) + #if hasattr(self._node.getParent(), "_convex_hull"): + # convex_hull = getattr(self._node.getParent(), "_convex_hull") + + #delattr(self._node.getParent(), "_convex_hull") + diff --git a/cura/ConvexHullNode.py b/cura/ConvexHullNode.py index 5be5820982..87da8f9a3d 100644 --- a/cura/ConvexHullNode.py +++ b/cura/ConvexHullNode.py @@ -63,11 +63,11 @@ class ConvexHullNode(SceneNode): def _onNodePositionChanged(self, node): #self.setPosition(node.getWorldPosition()) - if hasattr(node, "_convex_hull"): - delattr(node, "_convex_hull") + if node.callDecoration("getConvexHull"): + node.callDecoration("setConvexHull", None) + node.callDecoration("setConvexHullNode", None) self.setParent(None) - #self._node.transformationChanged.disconnect(self._onNodePositionChanged) #self._node.parentChanged.disconnect(self._onNodeParentChanged) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 9dcd15ad54..0de91eb091 100644 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -12,6 +12,7 @@ from UM.Math.Vector import Vector from UM.Math.AxisAlignedBox import AxisAlignedBox from UM.Application import Application from UM.Scene.Selection import Selection +from cura.ConvexHullDecorator import ConvexHullDecorator from . import PlatformPhysicsOperation from . import ConvexHullJob @@ -64,22 +65,26 @@ class PlatformPhysics: move_vector.setY(-bbox.bottom) # If there is no convex hull for the node, start calculating it and continue. - if not hasattr(node, "_convex_hull"): - if not hasattr(node, "_convex_hull_job"): + if not node.getDecorator(ConvexHullDecorator): + node.addDecorator(ConvexHullDecorator()) + + if not node.callDecoration("getConvexHull"): + if not node.callDecoration("getConvexHullJob"): job = ConvexHullJob.ConvexHullJob(node) job.start() - node._convex_hull_job = job + node.callDecoration("setConvexHullJob", job) + elif Selection.isSelected(node): pass else: # Check for collisions between convex hulls for other_node in BreadthFirstIterator(root): # Ignore root, ourselves and anything that is not a normal SceneNode. - if other_node is root or type(other_node) is not SceneNode or other_node is node: + if other_node is root or type(other_node) is not SceneNode or other_node is node or other_node in node.getChildren() or node in other_node.getChildren(): continue - + # Ignore nodes that do not have the right properties set. - if not hasattr(other_node, "_convex_hull") or not other_node.getBoundingBox(): + if not other_node.callDecoration("getConvexHull") or not other_node.getBoundingBox(): continue # Check to see if the bounding boxes intersect. If not, we can ignore the node as there is no way the hull intersects. @@ -87,17 +92,17 @@ class PlatformPhysics: continue # Get the overlap distance for both convex hulls. If this returns None, there is no intersection. - overlap = node._convex_hull.intersectsPolygon(other_node._convex_hull) + overlap = node.callDecoration("getConvexHull").intersectsPolygon(other_node.callDecoration("getConvexHull")) if overlap is None: continue move_vector.setX(overlap[0] * 1.1) move_vector.setZ(overlap[1] * 1.1) - - if hasattr(node, "_convex_hull"): + convex_hull = node.callDecoration("getConvexHull") + if convex_hull: # Check for collisions between disallowed areas and the object for area in self._build_volume.getDisallowedAreas(): - overlap = node._convex_hull.intersectsPolygon(area) + overlap = convex_hull.intersectsPolygon(area) if overlap is None: continue