Groups now also have a convexHull

This commit is contained in:
Jaime van Kessel 2015-07-14 16:41:59 +02:00
parent 9475c8e0c1
commit 8e6dd2486f
4 changed files with 83 additions and 23 deletions

View File

@ -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

View File

@ -16,9 +16,24 @@ class ConvexHullJob(Job):
self._node = node self._node = node
def run(self): 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 return
else:
if not self._node.getMeshData():
return
mesh = self._node.getMeshData() mesh = self._node.getMeshData()
vertex_data = mesh.getTransformed(self._node.getWorldTransformation()).getVertices() vertex_data = mesh.getTransformed(self._node.getWorldTransformation()).getVertices()
@ -26,10 +41,22 @@ class ConvexHullJob(Job):
# First, calculate the normal convex hull around the points # First, calculate the normal convex hull around the points
hull = hull.getConvexHull() 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. # 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 = 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()) hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())
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")
self._node._convex_hull = hull
delattr(self._node, "_convex_hull_job")

View File

@ -63,11 +63,11 @@ class ConvexHullNode(SceneNode):
def _onNodePositionChanged(self, node): def _onNodePositionChanged(self, node):
#self.setPosition(node.getWorldPosition()) #self.setPosition(node.getWorldPosition())
if hasattr(node, "_convex_hull"): if node.callDecoration("getConvexHull"):
delattr(node, "_convex_hull") node.callDecoration("setConvexHull", None)
node.callDecoration("setConvexHullNode", None)
self.setParent(None) self.setParent(None)
#self._node.transformationChanged.disconnect(self._onNodePositionChanged) #self._node.transformationChanged.disconnect(self._onNodePositionChanged)
#self._node.parentChanged.disconnect(self._onNodeParentChanged) #self._node.parentChanged.disconnect(self._onNodeParentChanged)

View File

@ -12,6 +12,7 @@ from UM.Math.Vector import Vector
from UM.Math.AxisAlignedBox import AxisAlignedBox from UM.Math.AxisAlignedBox import AxisAlignedBox
from UM.Application import Application from UM.Application import Application
from UM.Scene.Selection import Selection from UM.Scene.Selection import Selection
from cura.ConvexHullDecorator import ConvexHullDecorator
from . import PlatformPhysicsOperation from . import PlatformPhysicsOperation
from . import ConvexHullJob from . import ConvexHullJob
@ -64,22 +65,26 @@ class PlatformPhysics:
move_vector.setY(-bbox.bottom) move_vector.setY(-bbox.bottom)
# If there is no convex hull for the node, start calculating it and continue. # If there is no convex hull for the node, start calculating it and continue.
if not hasattr(node, "_convex_hull"): if not node.getDecorator(ConvexHullDecorator):
if not hasattr(node, "_convex_hull_job"): node.addDecorator(ConvexHullDecorator())
if not node.callDecoration("getConvexHull"):
if not node.callDecoration("getConvexHullJob"):
job = ConvexHullJob.ConvexHullJob(node) job = ConvexHullJob.ConvexHullJob(node)
job.start() job.start()
node._convex_hull_job = job node.callDecoration("setConvexHullJob", job)
elif Selection.isSelected(node): elif Selection.isSelected(node):
pass pass
else: else:
# Check for collisions between convex hulls # Check for collisions between convex hulls
for other_node in BreadthFirstIterator(root): for other_node in BreadthFirstIterator(root):
# Ignore root, ourselves and anything that is not a normal SceneNode. # 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 continue
# Ignore nodes that do not have the right properties set. # 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 continue
# Check to see if the bounding boxes intersect. If not, we can ignore the node as there is no way the hull intersects. # 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 continue
# Get the overlap distance for both convex hulls. If this returns None, there is no intersection. # 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: if overlap is None:
continue continue
move_vector.setX(overlap[0] * 1.1) move_vector.setX(overlap[0] * 1.1)
move_vector.setZ(overlap[1] * 1.1) move_vector.setZ(overlap[1] * 1.1)
convex_hull = node.callDecoration("getConvexHull")
if hasattr(node, "_convex_hull"): if convex_hull:
# Check for collisions between disallowed areas and the object # Check for collisions between disallowed areas and the object
for area in self._build_volume.getDisallowedAreas(): for area in self._build_volume.getDisallowedAreas():
overlap = node._convex_hull.intersectsPolygon(area) overlap = convex_hull.intersectsPolygon(area)
if overlap is None: if overlap is None:
continue continue