Update documentation & code cleanup

This commit is contained in:
Jaime van Kessel 2016-04-08 14:26:28 +02:00
parent 4c233e75f4
commit 97d16ae3bd
7 changed files with 63 additions and 51 deletions

View file

@ -15,6 +15,8 @@ from UM.View.GL.OpenGL import OpenGL
import numpy import numpy
## Build volume is a special kind of node that is responsible for rendering the printable area & disallowed areas.
class BuildVolume(SceneNode): class BuildVolume(SceneNode):
VolumeOutlineColor = Color(12, 169, 227, 255) VolumeOutlineColor = Color(12, 169, 227, 255)
@ -72,6 +74,7 @@ class BuildVolume(SceneNode):
renderer.queueNode(self, mesh = self._disallowed_area_mesh, shader = self._shader, transparent = True, backface_cull = True, sort = -9) renderer.queueNode(self, mesh = self._disallowed_area_mesh, shader = self._shader, transparent = True, backface_cull = True, sort = -9)
return True return True
## Recalculates the build volume & disallowed areas.
def rebuild(self): def rebuild(self):
if self._width == 0 or self._height == 0 or self._depth == 0: if self._width == 0 or self._height == 0 or self._depth == 0:
return return
@ -127,9 +130,10 @@ class BuildVolume(SceneNode):
new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d)) new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d))
mb.addFace(first, previous_point, new_point, color = color) mb.addFace(first, previous_point, new_point, color = color)
previous_point = new_point previous_point = new_point
# Find the largest disallowed area to exclude it from the maximum scale bounds. # Find the largest disallowed area to exclude it from the maximum scale bounds.
# This is a very nasty hack. This pretty much only works for UM machines. This disallowed area_size needs # This is a very nasty hack. This pretty much only works for UM machines.
# A -lot- of rework at some point in the future: TODO # This disallowed area_size needs a -lot- of rework at some point in the future: TODO
if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area. if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1])) size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
else: else:
@ -148,7 +152,7 @@ class BuildVolume(SceneNode):
if profile: if profile:
skirt_size = self._getSkirtSize(profile) skirt_size = self._getSkirtSize(profile)
# As this works better for UM machines, we only add the dissallowed_area_size for the z direction. # As this works better for UM machines, we only add the disallowed_area_size for the z direction.
# This is probably wrong in all other cases. TODO! # This is probably wrong in all other cases. TODO!
# The +1 and -1 is added as there is always a bit of extra room required to work properly. # The +1 and -1 is added as there is always a bit of extra room required to work properly.
scale_to_max_bounds = AxisAlignedBox( scale_to_max_bounds = AxisAlignedBox(
@ -194,8 +198,6 @@ class BuildVolume(SceneNode):
self._updateDisallowedAreas() self._updateDisallowedAreas()
self.rebuild() self.rebuild()
def _updateDisallowedAreas(self): def _updateDisallowedAreas(self):
if not self._active_instance or not self._active_profile: if not self._active_instance or not self._active_profile:
return return
@ -224,7 +226,7 @@ class BuildVolume(SceneNode):
areas.append(poly) areas.append(poly)
# Add the skirt areas arround the borders of the build plate. # Add the skirt areas around the borders of the build plate.
if skirt_size > 0: if skirt_size > 0:
half_machine_width = self._active_instance.getMachineSettingValue("machine_width") / 2 half_machine_width = self._active_instance.getMachineSettingValue("machine_width") / 2
half_machine_depth = self._active_instance.getMachineSettingValue("machine_depth") / 2 half_machine_depth = self._active_instance.getMachineSettingValue("machine_depth") / 2
@ -259,6 +261,7 @@ class BuildVolume(SceneNode):
self._disallowed_areas = areas self._disallowed_areas = areas
## Convenience function to calculate the size of the bed adhesion.
def _getSkirtSize(self, profile): def _getSkirtSize(self, profile):
skirt_size = 0.0 skirt_size = 0.0

View file

@ -1,17 +1,24 @@
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
from UM.Application import Application from UM.Application import Application
## 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.
class ConvexHullDecorator(SceneNodeDecorator): class ConvexHullDecorator(SceneNodeDecorator):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self._convex_hull = None 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. # 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 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 # 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 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
# 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_head_full = None
self._convex_hull_node = None self._convex_hull_node = None
@ -27,19 +34,27 @@ class ConvexHullDecorator(SceneNodeDecorator):
copy = ConvexHullDecorator() copy = ConvexHullDecorator()
return copy return copy
## Get the unmodified convex hull of the node
def getConvexHull(self): def getConvexHull(self):
return self._convex_hull return self._convex_hull
## 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: if not self._convex_hull_head_full:
return self.getConvexHull() return self.getConvexHull()
return self._convex_hull_head_full return self._convex_hull_head_full
## Get convex hull of the object + head size
# 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
def getConvexHullHead(self): def getConvexHullHead(self):
if not self._convex_hull_head: if not self._convex_hull_head:
return self.getConvexHull() return self.getConvexHull()
return self._convex_hull_head return self._convex_hull_head
## Get convex hull of the node
# 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.
def getConvexHullBoundary(self): def getConvexHullBoundary(self):
if not self._convex_hull_boundary: if not self._convex_hull_boundary:
return self.getConvexHull() return self.getConvexHull()

View file

@ -9,6 +9,7 @@ import numpy
import copy import copy
from . import ConvexHullNode from . import ConvexHullNode
## Job to async calculate the convex hull of a node.
class ConvexHullJob(Job): class ConvexHullJob(Job):
def __init__(self, node): def __init__(self, node):
super().__init__() super().__init__()
@ -38,7 +39,8 @@ class ConvexHullJob(Job):
return 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()
# Don't use data below 0. TODO; We need a better check for this as this gives poor results for meshes with long edges. # 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] vertex_data = vertex_data[vertex_data[:,1] >= 0]
hull = Polygon(numpy.rint(vertex_data[:, [0, 2]]).astype(int)) hull = Polygon(numpy.rint(vertex_data[:, [0, 2]]).astype(int))
@ -55,6 +57,7 @@ class ConvexHullJob(Job):
# Printing one at a time and it's not an object in a group # Printing one at a time and it's not an object in a group
self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull)) self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
head_and_fans = Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"), numpy.float32)) head_and_fans = Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"), numpy.float32))
# Full head hull is used to actually check the order. # Full head hull is used to actually check the order.
full_head_hull = hull.getMinkowskiHull(head_and_fans) full_head_hull = hull.getMinkowskiHull(head_and_fans)
self._node.callDecoration("setConvexHullHeadFull", full_head_hull) self._node.callDecoration("setConvexHullHeadFull", full_head_hull)
@ -62,17 +65,19 @@ class ConvexHullJob(Job):
mirrored.mirror([0, 0], [0, 1]) #Mirror horizontally. mirrored.mirror([0, 0], [0, 1]) #Mirror horizontally.
mirrored.mirror([0, 0], [1, 0]) #Mirror vertically. mirrored.mirror([0, 0], [1, 0]) #Mirror vertically.
head_and_fans = head_and_fans.intersectionConvexHulls(mirrored) head_and_fans = head_and_fans.intersectionConvexHulls(mirrored)
# Min head hull is used for the push free # Min head hull is used for the push free
min_head_hull = hull.getMinkowskiHull(head_and_fans) min_head_hull = hull.getMinkowskiHull(head_and_fans)
self._node.callDecoration("setConvexHullHead", min_head_hull) self._node.callDecoration("setConvexHullHead", min_head_hull)
hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32))) hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32)))
else: else:
self._node.callDecoration("setConvexHullHead", None) self._node.callDecoration("setConvexHullHead", None)
if self._node.getParent() is None: #Node was already deleted before job is done. if self._node.getParent() is None: # Node was already deleted before job is done.
self._node.callDecoration("setConvexHullNode",None) self._node.callDecoration("setConvexHullNode",None)
self._node.callDecoration("setConvexHull", None) self._node.callDecoration("setConvexHull", None)
self._node.callDecoration("setConvexHullJob", None) self._node.callDecoration("setConvexHullJob", None)
return return
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("setConvexHullNode", hull_node)
self._node.callDecoration("setConvexHull", hull) self._node.callDecoration("setConvexHull", hull)

View file

@ -5,11 +5,15 @@ from UM.Scene.SceneNode import SceneNode
from UM.Resources import Resources from UM.Resources import Resources
from UM.Math.Color import Color from UM.Math.Color import Color
from UM.Math.Vector import Vector 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
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
# location an object uses on the buildplate. This area (or area's in case of one at a time printing) is
# then displayed as a transparent shadow.
def __init__(self, node, hull, parent = None): def __init__(self, node, hull, parent = None):
super().__init__(parent) super().__init__(parent)
@ -22,18 +26,22 @@ class ConvexHullNode(SceneNode):
self._inherit_orientation = False self._inherit_orientation = False
self._inherit_scale = False self._inherit_scale = False
# Color of the drawn convex hull
self._color = Color(35, 35, 35, 128) self._color = Color(35, 35, 35, 128)
self._mesh_height = 0.1 #The y-coordinate of the convex hull mesh. Must not be 0, to prevent z-fighting.
# The y-coordinate of the convex hull mesh. Must not be 0, to prevent z-fighting.
self._mesh_height = 0.1
# The node this mesh is "watching"
self._node = node self._node = node
self._node.transformationChanged.connect(self._onNodePositionChanged) self._node.transformationChanged.connect(self._onNodePositionChanged)
self._node.parentChanged.connect(self._onNodeParentChanged) self._node.parentChanged.connect(self._onNodeParentChanged)
self._node.decoratorsChanged.connect(self._onNodeDecoratorsChanged) self._node.decoratorsChanged.connect(self._onNodeDecoratorsChanged)
self._onNodeDecoratorsChanged(self._node) self._onNodeDecoratorsChanged(self._node)
self._convex_hull_head_mesh = None self._convex_hull_head_mesh = None
self._hull = hull self._hull = hull
hull_points = self._hull.getPoints() # TODO: @UnusedVariable
hull_mesh = self.createHullMesh(self._hull.getPoints()) hull_mesh = self.createHullMesh(self._hull.getPoints())
if hull_mesh: if hull_mesh:
self.setMeshData(hull_mesh) self.setMeshData(hull_mesh)
@ -41,18 +49,21 @@ 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())
## Actually create the mesh from the hullpoints
# /param hull_points list of xy values
# /return meshData
def createHullMesh(self, hull_points): def createHullMesh(self, hull_points):
#Input checking. # Input checking.
if len(hull_points) < 3: if len(hull_points) < 3:
return None return None
mesh_builder = MeshBuilder() mesh_builder = MeshBuilder()
point_first = Vector(hull_points[0][0], self._mesh_height, hull_points[0][1]) point_first = Vector(hull_points[0][0], self._mesh_height, hull_points[0][1])
point_previous = Vector(hull_points[1][0], self._mesh_height, hull_points[1][1]) point_previous = Vector(hull_points[1][0], self._mesh_height, hull_points[1][1])
for point in hull_points[2:]: #Add the faces in the order of a triangle fan. for point in hull_points[2:]: # Add the faces in the order of a triangle fan.
point_new = Vector(point[0], self._mesh_height, point[1]) point_new = Vector(point[0], self._mesh_height, point[1])
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.getData()
@ -75,7 +86,7 @@ class ConvexHullNode(SceneNode):
if node.callDecoration("getConvexHull"): if node.callDecoration("getConvexHull"):
node.callDecoration("setConvexHull", None) node.callDecoration("setConvexHull", None)
node.callDecoration("setConvexHullNode", None) node.callDecoration("setConvexHullNode", None)
self.setParent(None) self.setParent(None) # Garbage collection should delete this node after a while.
def _onNodeParentChanged(self, node): def _onNodeParentChanged(self, node):
if node.getParent(): if node.getParent():

View file

@ -4,6 +4,7 @@ from PyQt5.QtGui import QDesktopServices
from UM.Event import CallFunctionEvent from UM.Event import CallFunctionEvent
from UM.Application import Application from UM.Application import Application
class CuraActions(QObject): class CuraActions(QObject):
def __init__(self, parent = None): def __init__(self, parent = None):
super().__init__(parent) super().__init__(parent)

View file

@ -56,7 +56,8 @@ if platform.system() == "Linux": # Needed for platform.linux_distribution, which
try: try:
from cura.CuraVersion import CuraVersion from cura.CuraVersion import CuraVersion
except ImportError: except ImportError:
CuraVersion = "master" # [CodeStyle: Reflecting imported value] CuraVersion = "master" # [CodeStyle: Reflecting imported value]
class CuraApplication(QtApplication): class CuraApplication(QtApplication):
class ResourceTypes: class ResourceTypes:
@ -69,7 +70,7 @@ class CuraApplication(QtApplication):
if not hasattr(sys, "frozen"): if not hasattr(sys, "frozen"):
Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..")) Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))
self._open_file_queue = [] #Files to open when plug-ins are loaded. self._open_file_queue = [] # Files to open when plug-ins are loaded.
super().__init__(name = "cura", version = CuraVersion) super().__init__(name = "cura", version = CuraVersion)
@ -96,6 +97,8 @@ class CuraApplication(QtApplication):
self._scene_boundingbox = AxisAlignedBox() self._scene_boundingbox = AxisAlignedBox()
self._job_name = None self._job_name = None
self._center_after_select = False self._center_after_select = False
self._camera_animation = None
self._cura_actions = None
self.getMachineManager().activeMachineInstanceChanged.connect(self._onActiveMachineChanged) self.getMachineManager().activeMachineInstanceChanged.connect(self._onActiveMachineChanged)
self.getMachineManager().addMachineRequested.connect(self._onAddMachineRequested) self.getMachineManager().addMachineRequested.connect(self._onAddMachineRequested)
@ -205,7 +208,7 @@ class CuraApplication(QtApplication):
self.exec_() self.exec_()
# Handle Qt events ## Handle Qt events
def event(self, event): def event(self, event):
if event.type() == QEvent.FileOpen: if event.type() == QEvent.FileOpen:
if self._plugins_loaded: if self._plugins_loaded:
@ -215,6 +218,7 @@ class CuraApplication(QtApplication):
return super().event(event) return super().event(event)
## Get print information (duration / material used)
def getPrintInformation(self): def getPrintInformation(self):
return self._print_information return self._print_information
@ -585,30 +589,7 @@ class CuraApplication(QtApplication):
return CuraSplashScreen.CuraSplashScreen() return CuraSplashScreen.CuraSplashScreen()
def _onActiveMachineChanged(self): def _onActiveMachineChanged(self):
machine = self.getMachineManager().getActiveMachineInstance() pass
if machine:
pass
#Preferences.getInstance().setValue("cura/active_machine", machine.getName())
#self._volume.setWidth(machine.getSettingValueByKey("machine_width"))
#self._volume.setHeight(machine.getSettingValueByKey("machine_height"))
#self._volume.setDepth(machine.getSettingValueByKey("machine_depth"))
#disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas")
#areas = []
#if disallowed_areas:
#for area in disallowed_areas:
#areas.append(Polygon(numpy.array(area, numpy.float32)))
#self._volume.setDisallowedAreas(areas)
#self._volume.rebuild()
#offset = machine.getSettingValueByKey("machine_platform_offset")
#if offset:
#self._platform.setPosition(Vector(offset[0], offset[1], offset[2]))
#else:
#self._platform.setPosition(Vector(0.0, 0.0, 0.0))
def _onFileLoaded(self, job): def _onFileLoaded(self, job):
node = job.getResult() node = job.getResult()

View file

@ -1,4 +0,0 @@
# Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
CuraVersion = "@CURA_VERSION@"