mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-04-23 22:29:41 +08:00
Finally, use the new convex hull code to compute the object 'shadow' and exclusion zones.
Contributes to CURA-1504
This commit is contained in:
parent
0b858f3878
commit
d7127b800c
@ -1,28 +1,20 @@
|
|||||||
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
|
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
|
||||||
|
from UM.Math.Polygon import Polygon
|
||||||
|
from UM.Logger import Logger
|
||||||
|
from . import ConvexHullNode
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
## The convex hull decorator is a scene node decorator that adds the convex hull functionality to a scene node.
|
## The convex hull decorator is a scene node decorator that adds the convex hull functionality to a scene node.
|
||||||
# If a scene node has a convex hull decorator, it will have a shadow in which other objects can not be printed.
|
# If a scene node has a convex hull decorator, it will have a shadow in which other objects can not be printed.
|
||||||
class ConvexHullDecorator(SceneNodeDecorator):
|
class ConvexHullDecorator(SceneNodeDecorator):
|
||||||
def __init__(self):
|
def __init__(self,):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._convex_hull = None
|
|
||||||
|
|
||||||
# In case of printing all at once this is the same as the convex hull.
|
|
||||||
# For one at the time this is the area without the head.
|
|
||||||
self._convex_hull_boundary = None
|
|
||||||
|
|
||||||
# In case of printing all at once this is the same as the convex hull.
|
|
||||||
# For one at the time this is area with intersection of mirrored head
|
|
||||||
self._convex_hull_head = None
|
|
||||||
|
|
||||||
# In case of printing all at once this is the same as the convex hull.
|
|
||||||
# For one at the time this is area with intersection of full head
|
|
||||||
self._convex_hull_head_full = None
|
|
||||||
|
|
||||||
self._convex_hull_node = None
|
self._convex_hull_node = None
|
||||||
self._convex_hull_job = None
|
self._init2DConvexHullCache()
|
||||||
|
|
||||||
self._profile = None
|
self._profile = None
|
||||||
Application.getInstance().getMachineManager().activeProfileChanged.connect(self._onActiveProfileChanged)
|
Application.getInstance().getMachineManager().activeProfileChanged.connect(self._onActiveProfileChanged)
|
||||||
@ -31,58 +23,55 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||||||
|
|
||||||
## Force that a new (empty) object is created upon copy.
|
## Force that a new (empty) object is created upon copy.
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
copy = ConvexHullDecorator()
|
return ConvexHullDecorator()
|
||||||
return copy
|
|
||||||
|
|
||||||
## Get the unmodified convex hull of the node
|
## Get the unmodified 2D projected convex hull of the node
|
||||||
def getConvexHull(self):
|
def getConvexHull(self):
|
||||||
return self._convex_hull
|
hull = self._compute2DConvexHull()
|
||||||
|
profile = Application.getInstance().getMachineManager().getWorkingProfile()
|
||||||
|
if profile:
|
||||||
|
if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"):
|
||||||
|
hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"), numpy.float32)))
|
||||||
|
return hull
|
||||||
|
|
||||||
## Get the convex hull of the node with the full head size
|
## Get the convex hull of the node with the full head size
|
||||||
def getConvexHullHeadFull(self):
|
def getConvexHullHeadFull(self):
|
||||||
if not self._convex_hull_head_full:
|
return self._compute2DConvexHeadFull()
|
||||||
return self.getConvexHull()
|
|
||||||
return self._convex_hull_head_full
|
|
||||||
|
|
||||||
## Get convex hull of the object + head size
|
## Get convex hull of the object + head size
|
||||||
# In case of printing all at once this is the same as the convex hull.
|
# In case of printing all at once this is the same as the convex hull.
|
||||||
# For one at the time this is area with intersection of mirrored head
|
# For one at the time this is area with intersection of mirrored head
|
||||||
def getConvexHullHead(self):
|
def getConvexHullHead(self):
|
||||||
if not self._convex_hull_head:
|
profile = Application.getInstance().getMachineManager().getWorkingProfile()
|
||||||
return self.getConvexHull()
|
if profile:
|
||||||
return self._convex_hull_head
|
if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration(
|
||||||
|
"isGroup"):
|
||||||
|
return self._compute2DConvexHeadMin()
|
||||||
|
return None
|
||||||
|
|
||||||
## Get convex hull of the node
|
## Get convex hull of the node
|
||||||
# In case of printing all at once this is the same as the convex hull.
|
# In case of printing all at once this is the same as the convex hull.
|
||||||
# For one at the time this is the area without the head.
|
# For one at the time this is the area without the head.
|
||||||
def getConvexHullBoundary(self):
|
def getConvexHullBoundary(self):
|
||||||
if not self._convex_hull_boundary:
|
profile = Application.getInstance().getMachineManager().getWorkingProfile()
|
||||||
return self.getConvexHull()
|
if profile:
|
||||||
return self._convex_hull_boundary
|
if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration(
|
||||||
|
"isGroup"):
|
||||||
|
# Printing one at a time and it's not an object in a group
|
||||||
|
return self._compute2DConvexHull()
|
||||||
|
return None
|
||||||
|
|
||||||
def setConvexHullBoundary(self, hull):
|
def recomputeConvexHull(self):
|
||||||
self._convex_hull_boundary = hull
|
convex_hull = self.getConvexHull()
|
||||||
|
if self._convex_hull_node:
|
||||||
def setConvexHullHeadFull(self, hull):
|
if self._convex_hull_node.getHull() == convex_hull:
|
||||||
self._convex_hull_head_full = hull
|
Logger.log('d', 'ConvexHullDecorator not creating a new ConvexHullNode')
|
||||||
|
return
|
||||||
def setConvexHullHead(self, hull):
|
self._convex_hull_node.setParent(None)
|
||||||
self._convex_hull_head = hull
|
Logger.log('d', 'ConvexHullDecorator creating ConvexHullNode')
|
||||||
|
hull_node = ConvexHullNode.ConvexHullNode(self._node, convex_hull,
|
||||||
def setConvexHull(self, hull):
|
Application.getInstance().getController().getScene().getRoot())
|
||||||
self._convex_hull = hull
|
self._convex_hull_node = hull_node
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def _onActiveProfileChanged(self):
|
def _onActiveProfileChanged(self):
|
||||||
if self._profile:
|
if self._profile:
|
||||||
@ -94,18 +83,118 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||||||
self._profile.settingValueChanged.connect(self._onSettingValueChanged)
|
self._profile.settingValueChanged.connect(self._onSettingValueChanged)
|
||||||
|
|
||||||
def _onActiveMachineInstanceChanged(self):
|
def _onActiveMachineInstanceChanged(self):
|
||||||
if self._convex_hull_job:
|
|
||||||
self._convex_hull_job.cancel()
|
|
||||||
self.setConvexHull(None)
|
|
||||||
if self._convex_hull_node:
|
if self._convex_hull_node:
|
||||||
self._convex_hull_node.setParent(None)
|
self._convex_hull_node.setParent(None)
|
||||||
self._convex_hull_node = None
|
self._convex_hull_node = None
|
||||||
|
|
||||||
def _onSettingValueChanged(self, setting):
|
def _onSettingValueChanged(self, setting):
|
||||||
if setting == "print_sequence":
|
if setting == "print_sequence":
|
||||||
if self._convex_hull_job:
|
self.recomputeConvexHull()
|
||||||
self._convex_hull_job.cancel()
|
|
||||||
self.setConvexHull(None)
|
def _init2DConvexHullCache(self):
|
||||||
if self._convex_hull_node:
|
# Cache for the group code path in _compute2DConvexHull()
|
||||||
self._convex_hull_node.setParent(None)
|
self._2d_convex_hull_group_child_polygon = None
|
||||||
self._convex_hull_node = None
|
self._2d_convex_hull_group_result = None
|
||||||
|
|
||||||
|
# Cache for the mesh code path in _compute2DConvexHull()
|
||||||
|
self._2d_convex_hull_mesh = None
|
||||||
|
self._2d_convex_hull_mesh_world_transform = None
|
||||||
|
self._2d_convex_hull_mesh_result = None
|
||||||
|
|
||||||
|
def _compute2DConvexHull(self):
|
||||||
|
if self._node.callDecoration("isGroup"):
|
||||||
|
points = numpy.zeros((0, 2), dtype=numpy.int32)
|
||||||
|
for child in self._node.getChildren():
|
||||||
|
child_hull = child.callDecoration("_compute2DConvexHull")
|
||||||
|
if child_hull:
|
||||||
|
points = numpy.append(points, child_hull.getPoints(), axis = 0)
|
||||||
|
|
||||||
|
if points.size < 3:
|
||||||
|
return None
|
||||||
|
child_polygon = Polygon(points)
|
||||||
|
|
||||||
|
# Check the cache
|
||||||
|
if child_polygon == self._2d_convex_hull_group_child_polygon:
|
||||||
|
# Logger.log('d', 'Cache hit in _compute2DConvexHull group path')
|
||||||
|
return self._2d_convex_hull_group_result
|
||||||
|
|
||||||
|
# First, calculate the normal convex hull around the points
|
||||||
|
convex_hull = child_polygon.getConvexHull()
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
rounded_hull = self._roundHull(convex_hull)
|
||||||
|
|
||||||
|
# Store the result in the cache
|
||||||
|
self._2d_convex_hull_group_child_polygon = child_polygon
|
||||||
|
self._2d_convex_hull_group_result = rounded_hull
|
||||||
|
|
||||||
|
return rounded_hull
|
||||||
|
|
||||||
|
else:
|
||||||
|
if not self._node.getMeshData():
|
||||||
|
return None
|
||||||
|
mesh = self._node.getMeshData()
|
||||||
|
world_transform = self._node.getWorldTransformation()
|
||||||
|
|
||||||
|
# Check the cache
|
||||||
|
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')
|
||||||
|
return self._2d_convex_hull_mesh_result
|
||||||
|
|
||||||
|
vertex_data = mesh.getConvexHullTransformedVertices(world_transform)
|
||||||
|
# Don't use data below 0.
|
||||||
|
# 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]
|
||||||
|
|
||||||
|
# Round the vertex data to 1/10th of a mm, then remove all duplicate vertices
|
||||||
|
# This is done to greatly speed up further convex hull calculations as the convex hull
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# Grab the set of unique points.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
# See http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array
|
||||||
|
vertex_byte_view = numpy.ascontiguousarray(vertex_data).view(
|
||||||
|
numpy.dtype((numpy.void, vertex_data.dtype.itemsize * vertex_data.shape[1])))
|
||||||
|
_, idx = numpy.unique(vertex_byte_view, return_index=True)
|
||||||
|
vertex_data = vertex_data[idx] # Select the unique rows by index.
|
||||||
|
|
||||||
|
hull = Polygon(vertex_data)
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
# 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)))
|
||||||
|
|
||||||
|
# Store the result in the cache
|
||||||
|
self._2d_convex_hull_mesh = mesh
|
||||||
|
self._2d_convex_hull_mesh_world_transform = world_transform
|
||||||
|
self._2d_convex_hull_mesh_result = rounded_hull
|
||||||
|
|
||||||
|
return rounded_hull
|
||||||
|
|
||||||
|
def _getHeadAndFans(self):
|
||||||
|
profile = Application.getInstance().getMachineManager().getWorkingProfile()
|
||||||
|
return Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"), numpy.float32))
|
||||||
|
|
||||||
|
def _compute2DConvexHeadFull(self):
|
||||||
|
return self._compute2DConvexHull().getMinkowskiHull(self._getHeadAndFans())
|
||||||
|
|
||||||
|
def _compute2DConvexHeadMin(self):
|
||||||
|
headAndFans = self._getHeadAndFans()
|
||||||
|
mirrored = headAndFans.mirror([0, 0], [0, 1]).mirror([0, 0], [1, 0]) # Mirror horizontally & vertically.
|
||||||
|
head_and_fans = self._getHeadAndFans().intersectionConvexHulls(mirrored)
|
||||||
|
|
||||||
|
# Min head hull is used for the push free
|
||||||
|
min_head_hull = self._compute2DConvexHull().getMinkowskiHull(head_and_fans)
|
||||||
|
return min_head_hull
|
||||||
|
|
||||||
|
def _roundHull(self, convex_hull):
|
||||||
|
return convex_hull.getMinkowskiHull(Polygon(numpy.array([[-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5], [0.5, -0.5]], numpy.float32)))
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
from UM.Job import Job
|
from UM.Job import Job
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Math.Polygon import Polygon
|
from UM.Math.Polygon import Polygon
|
||||||
|
from UM.Logger import Logger
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
import copy
|
import copy
|
||||||
@ -19,6 +20,11 @@ class ConvexHullJob(Job):
|
|||||||
def run(self):
|
def run(self):
|
||||||
if not self._node:
|
if not self._node:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Node Convex Hull
|
||||||
|
#################################################################
|
||||||
|
|
||||||
## If the scene node is a group, use the hull of the children to calculate its hull.
|
## If the scene node is a group, use the hull of the children to calculate its hull.
|
||||||
if self._node.callDecoration("isGroup"):
|
if self._node.callDecoration("isGroup"):
|
||||||
hull = Polygon(numpy.zeros((0, 2), dtype=numpy.int32))
|
hull = Polygon(numpy.zeros((0, 2), dtype=numpy.int32))
|
||||||
@ -47,10 +53,20 @@ class ConvexHullJob(Job):
|
|||||||
# This is done to greatly speed up further convex hull calculations as the convex hull
|
# This is done to greatly speed up further convex hull calculations as the convex hull
|
||||||
# becomes much less complex when dealing with highly detailed models.
|
# becomes much less complex when dealing with highly detailed models.
|
||||||
vertex_data = numpy.round(vertex_data, 1)
|
vertex_data = numpy.round(vertex_data, 1)
|
||||||
duplicates = (vertex_data[:,0] == vertex_data[:,1]) | (vertex_data[:,1] == vertex_data[:,2]) | (vertex_data[:,0] == vertex_data[:,2])
|
|
||||||
vertex_data = numpy.delete(vertex_data, numpy.where(duplicates), axis = 0)
|
|
||||||
|
|
||||||
hull = Polygon(vertex_data[:, [0, 2]])
|
vertex_data = vertex_data[:, [0, 2]] # Drop the Y components to project to 2D.
|
||||||
|
|
||||||
|
# Grab the set of unique points.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
# See http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array
|
||||||
|
vertex_byte_view = numpy.ascontiguousarray(vertex_data).view(
|
||||||
|
numpy.dtype((numpy.void, vertex_data.dtype.itemsize * vertex_data.shape[1])))
|
||||||
|
_, idx = numpy.unique(vertex_byte_view, return_index=True)
|
||||||
|
vertex_data = vertex_data[idx] # Select the unique rows by index.
|
||||||
|
|
||||||
|
hull = Polygon(vertex_data)
|
||||||
|
|
||||||
# First, calculate the normal convex hull around the points
|
# First, calculate the normal convex hull around the points
|
||||||
hull = hull.getConvexHull()
|
hull = hull.getConvexHull()
|
||||||
@ -59,6 +75,16 @@ class ConvexHullJob(Job):
|
|||||||
# This is done because of rounding errors.
|
# This is done because of rounding errors.
|
||||||
hull = hull.getMinkowskiHull(Polygon(numpy.array([[-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5], [0.5, -0.5]], numpy.float32)))
|
hull = hull.getMinkowskiHull(Polygon(numpy.array([[-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5], [0.5, -0.5]], numpy.float32)))
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Print Head Exclusion Zone
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# TODO
|
||||||
|
# ConvexHullDecorator should use a memoization strategy in its getters.
|
||||||
|
# Make MeshData immutable
|
||||||
|
|
||||||
profile = Application.getInstance().getMachineManager().getWorkingProfile()
|
profile = Application.getInstance().getMachineManager().getWorkingProfile()
|
||||||
if profile:
|
if profile:
|
||||||
if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"):
|
if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"):
|
||||||
@ -99,3 +125,33 @@ class ConvexHullJob(Job):
|
|||||||
hull_node = self._node.getParent().callDecoration("getConvexHullNode")
|
hull_node = self._node.getParent().callDecoration("getConvexHullNode")
|
||||||
if hull_node:
|
if hull_node:
|
||||||
hull_node.setParent(None)
|
hull_node.setParent(None)
|
||||||
|
|
||||||
|
try:
|
||||||
|
Logger.log('d', 'ConvexHullJob getConvexHull:' + dumpPoly(self._node.callDecoration("getConvexHull")))
|
||||||
|
Logger.log('d', 'ConvexHullJob new getConvexHull:' + dumpPoly(self._node.callDecoration("newGetConvexHull")))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
Logger.log('d', 'ConvexHullJob getConvexHullHeadFull:' + dumpPoly(self._node.callDecoration("getConvexHullHeadFull")))
|
||||||
|
Logger.log('d', 'ConvexHullJob new getConvexHullHeadFull:' + dumpPoly(self._node.callDecoration("newGetConvexHullHeadFull")))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
Logger.log('d', 'ConvexHullJob getConvexHullHead:' + dumpPoly(self._node.callDecoration("getConvexHullHead")))
|
||||||
|
Logger.log('d', 'ConvexHullJob new getConvexHullHead:' + dumpPoly(self._node.callDecoration("newGetConvexHullHead")))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
Logger.log('d', 'ConvexHullJob getConvexHullBoundary:' + dumpPoly(self._node.callDecoration("getConvexHullBoundary")))
|
||||||
|
Logger.log('d', 'ConvexHullJob new getConvexHullBoundary:' + dumpPoly(self._node.callDecoration("newGetConvexHullBoundary")))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def dumpPoly(poly):
|
||||||
|
if poly is None:
|
||||||
|
return "None"
|
||||||
|
else:
|
||||||
|
return repr(poly.getPoints())
|
||||||
|
@ -8,7 +8,7 @@ from UM.Math.Vector import Vector
|
|||||||
from UM.Mesh.MeshBuilder import MeshBuilder # To create a mesh to display the convex hull with.
|
from UM.Mesh.MeshBuilder import MeshBuilder # To create a mesh to display the convex hull with.
|
||||||
|
|
||||||
from UM.View.GL.OpenGL import OpenGL
|
from UM.View.GL.OpenGL import OpenGL
|
||||||
|
from UM.Logger import spy
|
||||||
|
|
||||||
class ConvexHullNode(SceneNode):
|
class ConvexHullNode(SceneNode):
|
||||||
## Convex hull node is a special type of scene node that is used to display a 2D area, to indicate the
|
## Convex hull node is a special type of scene node that is used to display a 2D area, to indicate the
|
||||||
@ -46,6 +46,9 @@ class ConvexHullNode(SceneNode):
|
|||||||
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())
|
||||||
|
|
||||||
|
def getHull(self):
|
||||||
|
return self._hull
|
||||||
|
|
||||||
## Actually create the mesh from the hullpoints
|
## Actually create the mesh from the hullpoints
|
||||||
# /param hull_points list of xy values
|
# /param hull_points list of xy values
|
||||||
# /return meshData
|
# /return meshData
|
||||||
@ -62,7 +65,7 @@ class ConvexHullNode(SceneNode):
|
|||||||
mesh_builder.addFace(point_first, point_previous, point_new, color = self._color)
|
mesh_builder.addFace(point_first, point_previous, point_new, color = self._color)
|
||||||
point_previous = point_new # Prepare point_previous for the next triangle.
|
point_previous = point_new # Prepare point_previous for the next triangle.
|
||||||
|
|
||||||
return mesh_builder.getData()
|
return mesh_builder.build()
|
||||||
|
|
||||||
def getWatchedNode(self):
|
def getWatchedNode(self):
|
||||||
return self._node
|
return self._node
|
||||||
@ -81,8 +84,6 @@ class ConvexHullNode(SceneNode):
|
|||||||
|
|
||||||
def _onNodePositionChanged(self, node):
|
def _onNodePositionChanged(self, node):
|
||||||
if node.callDecoration("getConvexHull"):
|
if node.callDecoration("getConvexHull"):
|
||||||
node.callDecoration("setConvexHull", None)
|
|
||||||
node.callDecoration("setConvexHullNode", None)
|
|
||||||
self.setParent(None) # Garbage collection should delete this node after a while.
|
self.setParent(None) # Garbage collection should delete this node after a while.
|
||||||
|
|
||||||
def _onNodeParentChanged(self, node):
|
def _onNodeParentChanged(self, node):
|
||||||
|
@ -278,9 +278,11 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
count += 1
|
count += 1
|
||||||
if not scene_boundingbox:
|
if not scene_boundingbox:
|
||||||
scene_boundingbox = copy.deepcopy(node.getBoundingBox())
|
scene_boundingbox = node.getBoundingBox()
|
||||||
else:
|
else:
|
||||||
scene_boundingbox += node.getBoundingBox()
|
other_bb = node.getBoundingBox()
|
||||||
|
if other_bb is not None:
|
||||||
|
scene_boundingbox = scene_boundingbox + node.getBoundingBox()
|
||||||
|
|
||||||
if not scene_boundingbox:
|
if not scene_boundingbox:
|
||||||
scene_boundingbox = AxisAlignedBox.Null
|
scene_boundingbox = AxisAlignedBox.Null
|
||||||
|
@ -45,7 +45,7 @@ class PlatformPhysics:
|
|||||||
|
|
||||||
root = self._controller.getScene().getRoot()
|
root = self._controller.getScene().getRoot()
|
||||||
for node in BreadthFirstIterator(root):
|
for node in BreadthFirstIterator(root):
|
||||||
if node is root or type(node) is not SceneNode:
|
if node is root or type(node) is not SceneNode or node.getBoundingBox() is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
bbox = node.getBoundingBox()
|
bbox = node.getBoundingBox()
|
||||||
@ -73,14 +73,9 @@ class PlatformPhysics:
|
|||||||
# 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 node.getDecorator(ConvexHullDecorator):
|
if not node.getDecorator(ConvexHullDecorator):
|
||||||
node.addDecorator(ConvexHullDecorator())
|
node.addDecorator(ConvexHullDecorator())
|
||||||
|
node.callDecoration("recomputeConvexHull")
|
||||||
|
|
||||||
if not node.callDecoration("getConvexHull"):
|
if Preferences.getInstance().getValue("physics/automatic_push_free"):
|
||||||
if not node.callDecoration("getConvexHullJob"):
|
|
||||||
job = ConvexHullJob.ConvexHullJob(node)
|
|
||||||
job.start()
|
|
||||||
node.callDecoration("setConvexHullJob", job)
|
|
||||||
|
|
||||||
elif Preferences.getInstance().getValue("physics/automatic_push_free"):
|
|
||||||
# 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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user