Move patch for buildvolume into BlackBelt plugin

This commit is contained in:
fieldOfView 2017-09-19 13:33:11 +02:00
parent 00980dcde2
commit 2f9889c350
3 changed files with 224 additions and 15 deletions

View file

@ -258,18 +258,12 @@ class BuildVolume(SceneNode):
self._disallowed_area_color = Color(*theme.getColor("disallowed_area").getRgb())
self._error_area_color = Color(*theme.getColor("error_area").getRgb())
# Get a dict from the machine metadata optionally overriding the build volume
# Note that CuraEngine is blissfully unaware of this; it is just what the user is shown in Cura
limit_buildvolume = self._global_container_stack.getMetaDataEntry("limit_buildvolume", {})
if not isinstance(limit_buildvolume, dict):
limit_buildvolume = {}
min_w = limit_buildvolume.get("width", {}).get("minimum",-self._width / 2)
max_w = limit_buildvolume.get("width", {}).get("maximum", self._width / 2)
min_h = limit_buildvolume.get("height", {}).get("minimum", 0.0)
max_h = limit_buildvolume.get("height", {}).get("maximum", self._height)
min_d = limit_buildvolume.get("depth", {}).get("minimum",-self._depth / 2)
max_d = limit_buildvolume.get("depth", {}).get("maximum", self._depth / 2)
min_w = -self._width / 2
max_w = self._width / 2
min_h = 0.0
max_h = self._height
min_d = -self._depth / 2
max_d = self._depth / 2
z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting

View file

@ -9,7 +9,7 @@ from UM.Math.Vector import Vector
from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("BlackBeltPlugin")
from PyQt5.QtGui import QPixmap
from . import BuildVolumePatches
import math
import os.path
@ -21,6 +21,8 @@ class BlackBeltPlugin(Extension):
self._application = Application.getInstance()
self._build_volume_patches = None
self._global_container_stack = None
self._application.globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
self._onGlobalContainerStackChanged()
@ -29,7 +31,7 @@ class BlackBeltPlugin(Extension):
self._scene_root.addDecorator(BlackBeltDecorator())
self._application.getBackend().slicingStarted.connect(self._onSlicingStarted)
self._application.engineCreatedSignal.connect(self._fixPreferences)
self._application.engineCreatedSignal.connect(self._onEngineCreated)
def _onGlobalContainerStackChanged(self):
if self._global_container_stack:
@ -53,7 +55,11 @@ class BlackBeltPlugin(Extension):
# This is a bit of a hack, but it seems quick enough.
self._application.globalContainerStackChanged.emit()
def _fixPreferences(self):
def _onEngineCreated(self):
# Apply patches
self._build_volume_patches = BuildVolumePatches.BuildVolumePatches(self._application.getBuildVolume())
# Fix preferences
preferences = Preferences.getInstance()
visible_settings = preferences.getValue("general/visible_settings")
if not visible_settings:

View file

@ -0,0 +1,209 @@
from UM.Application import Application
from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Math.Vector import Vector
from UM.Math.Matrix import Matrix
from UM.Math.Color import Color
from UM.Math.AxisAlignedBox import AxisAlignedBox
import numpy
import math
class BuildVolumePatches():
def __init__(self, build_volume):
self._build_volume = build_volume
self._build_volume.rebuild = self._rebuild
## Recalculates the build volume & disallowed areas.
# Copied verbatim from Buildvolume.rebuild, with a minor patch to limit the buildvolume asymmetrically
def _rebuild(self):
if not self._build_volume._width or not self._build_volume._height or not self._build_volume._depth:
return
if not Application.getInstance()._engine:
return
if not self._build_volume._volume_outline_color:
theme = Application.getInstance().getTheme()
self._build_volume._volume_outline_color = Color(*theme.getColor("volume_outline").getRgb())
self._build_volume._x_axis_color = Color(*theme.getColor("x_axis").getRgb())
self._build_volume._y_axis_color = Color(*theme.getColor("y_axis").getRgb())
self._build_volume._z_axis_color = Color(*theme.getColor("z_axis").getRgb())
self._build_volume._disallowed_area_color = Color(*theme.getColor("disallowed_area").getRgb())
self._build_volume._error_area_color = Color(*theme.getColor("error_area").getRgb())
### START PATCH
# Get a dict from the machine metadata optionally overriding the build volume
# Note that CuraEngine is blissfully unaware of this; it is just what the user is shown in Cura
limit_buildvolume = self._build_volume._global_container_stack.getMetaDataEntry("limit_buildvolume", {})
if not isinstance(limit_buildvolume, dict):
limit_buildvolume = {}
min_w = limit_buildvolume.get("width", {}).get("minimum",-self._build_volume._width / 2)
max_w = limit_buildvolume.get("width", {}).get("maximum", self._build_volume._width / 2)
min_h = limit_buildvolume.get("height", {}).get("minimum", 0.0)
max_h = limit_buildvolume.get("height", {}).get("maximum", self._build_volume._height)
min_d = limit_buildvolume.get("depth", {}).get("minimum",-self._build_volume._depth / 2)
max_d = limit_buildvolume.get("depth", {}).get("maximum", self._build_volume._depth / 2)
### END PATCH
z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting
if self._build_volume._shape != "elliptic":
# Outline 'cube' of the build volume
mb = MeshBuilder()
mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, max_h, min_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(min_w, min_h, max_d), Vector(max_w, min_h, max_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(min_w, min_h, max_d), Vector(min_w, max_h, max_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(min_w, max_h, max_d), Vector(max_w, max_h, max_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(max_w, min_h, max_d), Vector(max_w, max_h, max_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, min_h, max_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, min_h, max_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color = self._build_volume._volume_outline_color)
mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color = self._build_volume._volume_outline_color)
self._build_volume.setMeshData(mb.build())
# Build plate grid mesh
mb = MeshBuilder()
mb.addQuad(
Vector(min_w, min_h - z_fight_distance, min_d),
Vector(max_w, min_h - z_fight_distance, min_d),
Vector(max_w, min_h - z_fight_distance, max_d),
Vector(min_w, min_h - z_fight_distance, max_d)
)
for n in range(0, 6):
v = mb.getVertex(n)
mb.setVertexUVCoordinates(n, v[0], v[2])
self._build_volume._grid_mesh = mb.build()
else:
# Bottom and top 'ellipse' of the build volume
aspect = 1.0
scale_matrix = Matrix()
if self._build_volume._width != 0:
# Scale circular meshes by aspect ratio if width != height
aspect = self._build_volume._depth / self._build_volume._width
scale_matrix.compose(scale = Vector(1, 1, aspect))
mb = MeshBuilder()
mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - z_fight_distance, 0), color = self._build_volume._volume_outline_color)
mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self._build_volume._volume_outline_color)
self._build_volume.setMeshData(mb.build().getTransformed(scale_matrix))
# Build plate grid mesh
mb = MeshBuilder()
mb.addVertex(0, min_h - z_fight_distance, 0)
mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - z_fight_distance, 0))
sections = mb.getVertexCount() - 1 # Center point is not an arc section
indices = []
for n in range(0, sections - 1):
indices.append([0, n + 2, n + 1])
mb.addIndices(numpy.asarray(indices, dtype = numpy.int32))
mb.calculateNormals()
for n in range(0, mb.getVertexCount()):
v = mb.getVertex(n)
mb.setVertexUVCoordinates(n, v[0], v[2] * aspect)
self._build_volume._grid_mesh = mb.build().getTransformed(scale_matrix)
# Indication of the machine origin
if self._build_volume._global_container_stack.getProperty("machine_center_is_zero", "value"):
origin = (Vector(min_w, min_h, min_d) + Vector(max_w, min_h, max_d)) / 2
else:
origin = Vector(min_w, min_h, max_d)
mb = MeshBuilder()
mb.addCube(
width = self._build_volume._origin_line_length,
height = self._build_volume._origin_line_width,
depth = self._build_volume._origin_line_width,
center = origin + Vector(self._build_volume._origin_line_length / 2, 0, 0),
color = self._build_volume._x_axis_color
)
mb.addCube(
width = self._build_volume._origin_line_width,
height = self._build_volume._origin_line_length,
depth = self._build_volume._origin_line_width,
center = origin + Vector(0, self._build_volume._origin_line_length / 2, 0),
color = self._build_volume._y_axis_color
)
mb.addCube(
width = self._build_volume._origin_line_width,
height = self._build_volume._origin_line_width,
depth = self._build_volume._origin_line_length,
center = origin - Vector(0, 0, self._build_volume._origin_line_length / 2),
color = self._build_volume._z_axis_color
)
self._build_volume._origin_mesh = mb.build()
disallowed_area_height = 0.1
disallowed_area_size = 0
if self._build_volume._disallowed_areas:
mb = MeshBuilder()
color = self._build_volume._disallowed_area_color
for polygon in self._build_volume._disallowed_areas:
points = polygon.getPoints()
if len(points) == 0:
continue
first = Vector(self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(points[0][1], min_d, max_d))
previous_point = Vector(self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(points[0][1], min_d, max_d))
for point in points:
new_point = Vector(self._build_volume._clamp(point[0], min_w, max_w), disallowed_area_height, self._build_volume._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
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:
size = 0
disallowed_area_size = max(size, disallowed_area_size)
self._build_volume._disallowed_area_mesh = mb.build()
else:
self._build_volume._disallowed_area_mesh = None
if self._build_volume._error_areas:
mb = MeshBuilder()
for error_area in self._build_volume._error_areas:
color = self._build_volume._error_area_color
points = error_area.getPoints()
first = Vector(self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height,
self._build_volume._clamp(points[0][1], min_d, max_d))
previous_point = Vector(self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height,
self._build_volume._clamp(points[0][1], min_d, max_d))
for point in points:
new_point = Vector(self._build_volume._clamp(point[0], min_w, max_w), disallowed_area_height,
self._build_volume._clamp(point[1], min_d, max_d))
mb.addFace(first, previous_point, new_point, color=color)
previous_point = new_point
self._build_volume._error_mesh = mb.build()
else:
self._build_volume._error_mesh = None
self._build_volume._volume_aabb = AxisAlignedBox(
minimum = Vector(min_w, min_h - 1.0, min_d),
maximum = Vector(max_w, max_h - self._build_volume._raft_thickness - self._build_volume._extra_z_clearance, max_d))
bed_adhesion_size = self._build_volume._getEdgeDisallowedSize()
# 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(
minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1),
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._build_volume._raft_thickness - self._build_volume._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)
)
Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
self._build_volume.updateNodeBoundaryCheck()