mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 06:57: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
|
||||
|
||||
|
||||
## 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)
|
||||
|
||||
|
@ -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)
|
||||
return True
|
||||
|
||||
## Recalculates the build volume & disallowed areas.
|
||||
def rebuild(self):
|
||||
if self._width == 0 or self._height == 0 or self._depth == 0:
|
||||
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))
|
||||
mb.addFace(first, previous_point, new_point, color = color)
|
||||
previous_point = new_point
|
||||
|
||||
# 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
|
||||
# A -lot- of rework at some point in the future: TODO
|
||||
# This is a very nasty hack. This pretty much only works for UM machines.
|
||||
# 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.
|
||||
size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
|
||||
else:
|
||||
|
@ -148,7 +152,7 @@ class BuildVolume(SceneNode):
|
|||
if 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!
|
||||
# The +1 and -1 is added as there is always a bit of extra room required to work properly.
|
||||
scale_to_max_bounds = AxisAlignedBox(
|
||||
|
@ -194,8 +198,6 @@ class BuildVolume(SceneNode):
|
|||
self._updateDisallowedAreas()
|
||||
self.rebuild()
|
||||
|
||||
|
||||
|
||||
def _updateDisallowedAreas(self):
|
||||
if not self._active_instance or not self._active_profile:
|
||||
return
|
||||
|
@ -224,7 +226,7 @@ class BuildVolume(SceneNode):
|
|||
|
||||
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:
|
||||
half_machine_width = self._active_instance.getMachineSettingValue("machine_width") / 2
|
||||
half_machine_depth = self._active_instance.getMachineSettingValue("machine_depth") / 2
|
||||
|
@ -259,6 +261,7 @@ class BuildVolume(SceneNode):
|
|||
|
||||
self._disallowed_areas = areas
|
||||
|
||||
## Convenience function to calculate the size of the bed adhesion.
|
||||
def _getSkirtSize(self, profile):
|
||||
skirt_size = 0.0
|
||||
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
|
||||
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):
|
||||
def __init__(self):
|
||||
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.
|
||||
# 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
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
@ -27,19 +34,27 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
copy = ConvexHullDecorator()
|
||||
return copy
|
||||
|
||||
## Get the unmodified convex hull of the node
|
||||
def getConvexHull(self):
|
||||
return self._convex_hull
|
||||
|
||||
|
||||
## Get the convex hull of the node with the full head size
|
||||
def getConvexHullHeadFull(self):
|
||||
if not self._convex_hull_head_full:
|
||||
return self.getConvexHull()
|
||||
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):
|
||||
if not self._convex_hull_head:
|
||||
return self.getConvexHull()
|
||||
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):
|
||||
if not self._convex_hull_boundary:
|
||||
return self.getConvexHull()
|
||||
|
|
|
@ -9,6 +9,7 @@ import numpy
|
|||
import copy
|
||||
from . import ConvexHullNode
|
||||
|
||||
## Job to async calculate the convex hull of a node.
|
||||
class ConvexHullJob(Job):
|
||||
def __init__(self, node):
|
||||
super().__init__()
|
||||
|
@ -38,7 +39,8 @@ class ConvexHullJob(Job):
|
|||
return
|
||||
mesh = self._node.getMeshData()
|
||||
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]
|
||||
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
|
||||
self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
|
||||
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 = hull.getMinkowskiHull(head_and_fans)
|
||||
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], [1, 0]) #Mirror vertically.
|
||||
head_and_fans = head_and_fans.intersectionConvexHulls(mirrored)
|
||||
|
||||
# Min head hull is used for the push free
|
||||
min_head_hull = hull.getMinkowskiHull(head_and_fans)
|
||||
self._node.callDecoration("setConvexHullHead", min_head_hull)
|
||||
hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32)))
|
||||
else:
|
||||
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("setConvexHull", None)
|
||||
self._node.callDecoration("setConvexHullJob", None)
|
||||
return
|
||||
|
||||
hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())
|
||||
self._node.callDecoration("setConvexHullNode", hull_node)
|
||||
self._node.callDecoration("setConvexHull", hull)
|
||||
|
|
|
@ -5,11 +5,15 @@ from UM.Scene.SceneNode import SceneNode
|
|||
from UM.Resources import Resources
|
||||
from UM.Math.Color import Color
|
||||
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
|
||||
|
||||
|
||||
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):
|
||||
super().__init__(parent)
|
||||
|
||||
|
@ -22,18 +26,22 @@ class ConvexHullNode(SceneNode):
|
|||
self._inherit_orientation = False
|
||||
self._inherit_scale = False
|
||||
|
||||
# Color of the drawn convex hull
|
||||
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.transformationChanged.connect(self._onNodePositionChanged)
|
||||
self._node.parentChanged.connect(self._onNodeParentChanged)
|
||||
self._node.decoratorsChanged.connect(self._onNodeDecoratorsChanged)
|
||||
self._onNodeDecoratorsChanged(self._node)
|
||||
|
||||
self._convex_hull_head_mesh = None
|
||||
self._hull = hull
|
||||
|
||||
hull_points = self._hull.getPoints() # TODO: @UnusedVariable
|
||||
hull_mesh = self.createHullMesh(self._hull.getPoints())
|
||||
if hull_mesh:
|
||||
self.setMeshData(hull_mesh)
|
||||
|
@ -41,18 +49,21 @@ class ConvexHullNode(SceneNode):
|
|||
if convex_hull_head:
|
||||
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):
|
||||
#Input checking.
|
||||
# Input checking.
|
||||
if len(hull_points) < 3:
|
||||
return None
|
||||
|
||||
mesh_builder = MeshBuilder()
|
||||
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])
|
||||
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])
|
||||
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()
|
||||
|
||||
|
@ -75,7 +86,7 @@ class ConvexHullNode(SceneNode):
|
|||
if node.callDecoration("getConvexHull"):
|
||||
node.callDecoration("setConvexHull", None)
|
||||
node.callDecoration("setConvexHullNode", None)
|
||||
self.setParent(None)
|
||||
self.setParent(None) # Garbage collection should delete this node after a while.
|
||||
|
||||
def _onNodeParentChanged(self, node):
|
||||
if node.getParent():
|
||||
|
|
|
@ -4,6 +4,7 @@ from PyQt5.QtGui import QDesktopServices
|
|||
from UM.Event import CallFunctionEvent
|
||||
from UM.Application import Application
|
||||
|
||||
|
||||
class CuraActions(QObject):
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
|
|
|
@ -56,7 +56,8 @@ if platform.system() == "Linux": # Needed for platform.linux_distribution, which
|
|||
try:
|
||||
from cura.CuraVersion import CuraVersion
|
||||
except ImportError:
|
||||
CuraVersion = "master" # [CodeStyle: Reflecting imported value]
|
||||
CuraVersion = "master" # [CodeStyle: Reflecting imported value]
|
||||
|
||||
|
||||
class CuraApplication(QtApplication):
|
||||
class ResourceTypes:
|
||||
|
@ -69,7 +70,7 @@ class CuraApplication(QtApplication):
|
|||
if not hasattr(sys, "frozen"):
|
||||
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)
|
||||
|
||||
|
@ -96,6 +97,8 @@ class CuraApplication(QtApplication):
|
|||
self._scene_boundingbox = AxisAlignedBox()
|
||||
self._job_name = None
|
||||
self._center_after_select = False
|
||||
self._camera_animation = None
|
||||
self._cura_actions = None
|
||||
|
||||
self.getMachineManager().activeMachineInstanceChanged.connect(self._onActiveMachineChanged)
|
||||
self.getMachineManager().addMachineRequested.connect(self._onAddMachineRequested)
|
||||
|
@ -205,7 +208,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
self.exec_()
|
||||
|
||||
# Handle Qt events
|
||||
## Handle Qt events
|
||||
def event(self, event):
|
||||
if event.type() == QEvent.FileOpen:
|
||||
if self._plugins_loaded:
|
||||
|
@ -215,6 +218,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
return super().event(event)
|
||||
|
||||
## Get print information (duration / material used)
|
||||
def getPrintInformation(self):
|
||||
return self._print_information
|
||||
|
||||
|
@ -585,30 +589,7 @@ class CuraApplication(QtApplication):
|
|||
return CuraSplashScreen.CuraSplashScreen()
|
||||
|
||||
def _onActiveMachineChanged(self):
|
||||
machine = self.getMachineManager().getActiveMachineInstance()
|
||||
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))
|
||||
pass
|
||||
|
||||
def _onFileLoaded(self, job):
|
||||
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