mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 15:07:28 -06:00
Update documentation & code cleanup
This commit is contained in:
parent
4c233e75f4
commit
97d16ae3bd
7 changed files with 63 additions and 51 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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,6 +65,7 @@ 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)
|
||||||
|
@ -73,6 +77,7 @@ class ConvexHullJob(Job):
|
||||||
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)
|
||||||
|
|
|
@ -9,7 +9,11 @@ from UM.Mesh.MeshBuilder import MeshBuilder #To create a mesh to display the con
|
||||||
|
|
||||||
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,6 +49,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())
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
@ -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():
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -58,6 +58,7 @@ try:
|
||||||
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:
|
||||||
QmlFiles = Resources.UserType + 1
|
QmlFiles = Resources.UserType + 1
|
||||||
|
@ -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()
|
|
||||||
if machine:
|
|
||||||
pass
|
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()
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
# Copyright (c) 2015 Ultimaker B.V.
|
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
|
||||||
|
|
||||||
CuraVersion = "@CURA_VERSION@"
|
|
Loading…
Add table
Add a link
Reference in a new issue