Merge branch 'master' of github.com:Ultimaker/Cura

This commit is contained in:
Tim Kuipers 2016-07-19 13:17:54 +02:00
commit 10296362ec
4 changed files with 86 additions and 26 deletions

View file

@ -3,6 +3,7 @@
from cura.Settings.ExtruderManager import ExtruderManager
from UM.i18n import i18nCatalog
from UM.Scene.Platform import Platform
from UM.Scene.SceneNode import SceneNode
from UM.Application import Application
from UM.Resources import Resources
@ -18,12 +19,32 @@ from UM.View.GL.OpenGL import OpenGL
catalog = i18nCatalog("cura")
import numpy
import copy
# Setting for clearance around the prime
PRIME_CLEARANCE = 10
def approximatedCircleVertices(r):
"""
Return vertices from an approximated circle.
:param r: radius
:return: numpy 2-array with the vertices
"""
return numpy.array([
[-r, 0],
[-r * 0.707, r * 0.707],
[0, r],
[r * 0.707, r * 0.707],
[r, 0],
[r * 0.707, -r * 0.707],
[0, -r],
[-r * 0.707, -r * 0.707]
], numpy.float32)
## Build volume is a special kind of node that is responsible for rendering the printable area & disallowed areas.
class BuildVolume(SceneNode):
VolumeOutlineColor = Color(12, 169, 227, 255)
@ -46,6 +67,11 @@ class BuildVolume(SceneNode):
self.setCalculateBoundingBox(False)
self._volume_aabb = None
self._raft_thickness = 0.0
self._adhesion_type = None
self._raft_mesh = None
self._platform = Platform(self)
self._active_container_stack = None
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
self._onGlobalContainerStackChanged()
@ -77,6 +103,9 @@ class BuildVolume(SceneNode):
renderer.queueNode(self, mesh = self._grid_mesh, shader = self._grid_shader, backface_cull = True)
if self._disallowed_area_mesh:
renderer.queueNode(self, mesh = self._disallowed_area_mesh, shader = self._shader, transparent = True, backface_cull = True, sort = -9)
if self._raft_mesh and self._adhesion_type == "raft":
renderer.queueNode(self, mesh=self._raft_mesh, transparent=True, backface_cull=True, sort=-9)
return True
## Recalculates the build volume & disallowed areas.
@ -93,6 +122,7 @@ class BuildVolume(SceneNode):
mb = MeshBuilder()
# Outline 'cube' of the build volume
mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self.VolumeOutlineColor)
mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color = self.VolumeOutlineColor)
mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor)
@ -117,11 +147,23 @@ class BuildVolume(SceneNode):
Vector(max_w, min_h - 0.2, max_d),
Vector(min_w, min_h - 0.2, max_d)
)
for n in range(0, 6):
v = mb.getVertex(n)
mb.setVertexUVCoordinates(n, v[0], v[2])
self._grid_mesh = mb.build()
# Build raft mesh: a plane on the height of the raft.
mb = MeshBuilder()
mb.addQuad(
Vector(min_w, self._raft_thickness, min_d),
Vector(max_w, self._raft_thickness, min_d),
Vector(max_w, self._raft_thickness, max_d),
Vector(min_w, self._raft_thickness, max_d),
color=Color(128, 128, 128, 64)
)
self._raft_mesh = mb.build()
disallowed_area_height = 0.1
disallowed_area_size = 0
if self._disallowed_areas:
@ -177,6 +219,21 @@ class BuildVolume(SceneNode):
" \"Print Sequence\" setting to prevent the gantry from colliding"
" with printed objects."), lifetime=10).show()
def _updateRaftThickness(self):
old_raft_thickness = self._raft_thickness
self._adhesion_type = self._active_container_stack.getProperty("adhesion_type", "value")
self._raft_thickness = 0.0
if self._adhesion_type == "raft":
self._raft_thickness = (
self._active_container_stack.getProperty("raft_base_thickness", "value") +
self._active_container_stack.getProperty("raft_interface_thickness", "value") +
self._active_container_stack.getProperty("raft_surface_layers", "value") *
self._active_container_stack.getProperty("raft_surface_thickness", "value") +
self._active_container_stack.getProperty("raft_airgap", "value"))
# Rounding errors do not matter, we check if raft_thickness has changed at all
if old_raft_thickness != self._raft_thickness:
self.setPosition(Vector(0, -self._raft_thickness, 0), SceneNode.TransformSpace.World)
def _onGlobalContainerStackChanged(self):
if self._active_container_stack:
self._active_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
@ -195,6 +252,7 @@ class BuildVolume(SceneNode):
self._depth = self._active_container_stack.getProperty("machine_depth", "value")
self._updateDisallowedAreas()
self._updateRaftThickness()
self.rebuild()
@ -202,32 +260,40 @@ class BuildVolume(SceneNode):
if property_name != "value":
return
rebuild_me = False
if setting_key == "print_sequence":
if Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time":
self._height = self._active_container_stack.getProperty("gantry_height", "value")
self._buildVolumeMessage()
else:
self._height = self._active_container_stack.getProperty("machine_height", "value")
self.rebuild()
rebuild_me = True
if setting_key in self._skirt_settings:
self._updateDisallowedAreas()
rebuild_me = True
if setting_key in self._raft_settings:
self._updateRaftThickness()
rebuild_me = True
if rebuild_me:
self.rebuild()
def _updateDisallowedAreas(self):
if not self._active_container_stack:
return
disallowed_areas = self._active_container_stack.getProperty("machine_disallowed_areas", "value")
disallowed_areas = copy.deepcopy(
self._active_container_stack.getProperty("machine_disallowed_areas", "value"))
areas = []
# Add extruder prime locations as disallowed areas.
# Probably needs some rework after coordinate system change.
machine_definition = self._active_container_stack.getBottom()
current_machine_id = machine_definition.getId()
extruder_manager = ExtruderManager.getInstance()
extruders = extruder_manager.getMachineExtruders(current_machine_id)
machine_width = machine_definition.getProperty("machine_width", "value")
machine_depth = machine_definition.getProperty("machine_depth", "value")
extruders = extruder_manager.getMachineExtruders(self._active_container_stack.getId())
machine_width = self._active_container_stack.getProperty("machine_width", "value")
machine_depth = self._active_container_stack.getProperty("machine_depth", "value")
for single_extruder in extruders:
extruder_prime_pos_x = single_extruder.getProperty("extruder_prime_pos_x", "value")
extruder_prime_pos_y = single_extruder.getProperty("extruder_prime_pos_y", "value")
@ -249,16 +315,7 @@ class BuildVolume(SceneNode):
# Extend every area already in the disallowed_areas with the skirt size.
for area in disallowed_areas:
poly = Polygon(numpy.array(area, numpy.float32))
poly = poly.getMinkowskiHull(Polygon(numpy.array([
[-skirt_size, 0],
[-skirt_size * 0.707, skirt_size * 0.707],
[0, skirt_size],
[skirt_size * 0.707, skirt_size * 0.707],
[skirt_size, 0],
[skirt_size * 0.707, -skirt_size * 0.707],
[0, -skirt_size],
[-skirt_size * 0.707, -skirt_size * 0.707]
], numpy.float32)))
poly = poly.getMinkowskiHull(Polygon(approximatedCircleVertices(skirt_size)))
areas.append(poly)
@ -297,7 +354,7 @@ class BuildVolume(SceneNode):
self._disallowed_areas = areas
## Convenience function to calculate the size of the bed adhesion.
## Convenience function to calculate the size of the bed adhesion in directions x, y.
def _getSkirtSize(self, container_stack):
skirt_size = 0.0
@ -323,3 +380,4 @@ class BuildVolume(SceneNode):
return max(min(value, max_value), min_value)
_skirt_settings = ["adhesion_type", "skirt_gap", "skirt_line_count", "skirt_line_width", "brim_width", "brim_line_count", "raft_margin", "draft_shield_enabled", "draft_shield_dist", "xy_offset"]
_raft_settings = ["adhesion_type", "raft_base_thickness", "raft_interface_thickness", "raft_surface_layers", "raft_surface_thickness", "raft_airgap"]

View file

@ -4,7 +4,6 @@
from UM.Qt.QtApplication import QtApplication
from UM.Scene.SceneNode import SceneNode
from UM.Scene.Camera import Camera
from UM.Scene.Platform import Platform as Scene_Platform
from UM.Math.Vector import Vector
from UM.Math.Quaternion import Quaternion
from UM.Math.AxisAlignedBox import AxisAlignedBox
@ -144,7 +143,6 @@ class CuraApplication(QtApplication):
])
self._physics = None
self._volume = None
self._platform = None
self._output_devices = {}
self._print_information = None
self._previous_active_tool = None
@ -377,8 +375,8 @@ class CuraApplication(QtApplication):
Selection.selectionChanged.connect(self.onSelectionChanged)
root = controller.getScene().getRoot()
self._platform = Scene_Platform(root)
# The platform is a child of BuildVolume
self._volume = BuildVolume.BuildVolume(root)
self.getRenderer().setBackgroundColor(QColor(245, 245, 245))
@ -857,3 +855,6 @@ class CuraApplication(QtApplication):
@pyqtSlot("QSize")
def setMinimumWindowSize(self, size):
self.getMainWindow().setMinimumSize(size)
def getBuildVolume(self):
return self._volume

View file

@ -40,6 +40,7 @@ class PlatformPhysics:
return
root = self._controller.getScene().getRoot()
for node in BreadthFirstIterator(root):
if node is root or type(node) is not SceneNode or node.getBoundingBox() is None:
continue
@ -58,10 +59,7 @@ class PlatformPhysics:
move_vector = Vector()
if not (node.getParent() and node.getParent().callDecoration("isGroup")): #If an object is grouped, don't move it down
z_offset = node.callDecoration("getZOffset") if node.getDecorator(ZOffsetDecorator.ZOffsetDecorator) else 0
if bbox.bottom > 0:
move_vector = move_vector.set(y=-bbox.bottom + z_offset)
elif bbox.bottom < z_offset:
move_vector = move_vector.set(y=(-bbox.bottom) - z_offset)
move_vector = move_vector.set(y=-bbox.bottom + z_offset)
# If there is no convex hull for the node, start calculating it and continue.
if not node.getDecorator(ConvexHullDecorator):

View file

@ -128,7 +128,10 @@ class ProcessSlicedLayersJob(Job):
new_node.addDecorator(decorator)
new_node.setMeshData(mesh)
new_node.setParent(self._scene.getRoot()) # Note: After this we can no longer abort!
# Set build volume as parent, the build volume can move as a result of raft settings.
# It makes sense to set the build volume as parent: the print is actually printed on it.
new_node_parent = Application.getInstance().getBuildVolume()
new_node.setParent(new_node_parent) # Note: After this we can no longer abort!
settings = Application.getInstance().getGlobalContainerStack()
if not settings.getProperty("machine_center_is_zero", "value"):