diff options
author | Nino van Hooff <ninovanhooff@gmail.com> | 2019-11-01 12:51:21 +0300 |
---|---|---|
committer | Nino van Hooff <ninovanhooff@gmail.com> | 2019-11-01 12:51:21 +0300 |
commit | 94d291a20c3e5e9bd84d3476cd8844bd9bf8930c (patch) | |
tree | d322550e0a12c0661fec06bfa1b1e573b732c94b /plugins | |
parent | 888c3f51a5718c80f9b3736aa86e5953e1c4ed8d (diff) | |
parent | 71fe01d7f20b76a79ff7b259b97fe13a4afa98c2 (diff) |
Merge branch 'master' into CURA-6854_align_layer_label_top_bottom
# Conflicts:
# plugins/SimulationView/SimulationViewMainComponent.qml
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/ImageReader/ConfigUI.qml | 46 | ||||
-rw-r--r-- | plugins/ImageReader/ImageReader.py | 25 | ||||
-rw-r--r-- | plugins/ImageReader/ImageReaderUI.py | 11 | ||||
-rw-r--r-- | plugins/PreviewStage/PreviewMain.qml | 23 | ||||
-rw-r--r-- | plugins/SimulationView/PathSlider.qml | 5 | ||||
-rw-r--r-- | plugins/SimulationView/SimulationViewMainComponent.qml | 23 |
6 files changed, 112 insertions, 21 deletions
diff --git a/plugins/ImageReader/ConfigUI.qml b/plugins/ImageReader/ConfigUI.qml index 47ba10778c..0429fae4e1 100644 --- a/plugins/ImageReader/ConfigUI.qml +++ b/plugins/ImageReader/ConfigUI.qml @@ -146,6 +146,52 @@ UM.Dialog UM.TooltipArea { Layout.fillWidth:true height: childrenRect.height + text: catalog.i18nc("@info:tooltip","For lithophanes a simple logarithmic model for translucency is available. For height maps the pixel values correspond to heights linearly.") + Row { + width: parent.width + + Label { + text: "Color Model" + width: 150 * screenScaleFactor + anchors.verticalCenter: parent.verticalCenter + } + ComboBox { + id: color_model + objectName: "ColorModel" + model: [ catalog.i18nc("@item:inlistbox","Linear"), catalog.i18nc("@item:inlistbox","Translucency") ] + width: 180 * screenScaleFactor + onCurrentIndexChanged: { manager.onColorModelChanged(currentIndex) } + } + } + } + + UM.TooltipArea { + Layout.fillWidth:true + height: childrenRect.height + text: catalog.i18nc("@info:tooltip","The percentage of light penetrating a print with a thickness of 1 millimeter. Lowering this value increases the contrast in dark regions and decreases the contrast in light regions of the image.") + visible: color_model.currentText == catalog.i18nc("@item:inlistbox","Translucency") + Row { + width: parent.width + + Label { + text: catalog.i18nc("@action:label", "1mm Transmittance (%)") + width: 150 * screenScaleFactor + anchors.verticalCenter: parent.verticalCenter + } + TextField { + id: transmittance + objectName: "Transmittance" + focus: true + validator: RegExpValidator {regExp: /^[1-9]\d{0,2}([\,|\.]\d*)?$/} + width: 180 * screenScaleFactor + onTextChanged: { manager.onTransmittanceChanged(text) } + } + } + } + + UM.TooltipArea { + Layout.fillWidth:true + height: childrenRect.height text: catalog.i18nc("@info:tooltip","The amount of smoothing to apply to the image.") Row { width: parent.width diff --git a/plugins/ImageReader/ImageReader.py b/plugins/ImageReader/ImageReader.py index e720ce4854..d6c2827d16 100644 --- a/plugins/ImageReader/ImageReader.py +++ b/plugins/ImageReader/ImageReader.py @@ -3,6 +3,8 @@ import numpy +import math + from PyQt5.QtGui import QImage, qRed, qGreen, qBlue from PyQt5.QtCore import Qt @@ -46,9 +48,9 @@ class ImageReader(MeshReader): def _read(self, file_name): size = max(self._ui.getWidth(), self._ui.getDepth()) - return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.lighter_is_higher) + return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.lighter_is_higher, self._ui.use_transparency_model, self._ui.transmittance_1mm) - def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, lighter_is_higher): + def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, lighter_is_higher, use_transparency_model, transmittance_1mm): scene_node = SceneNode() mesh = MeshBuilder() @@ -99,12 +101,14 @@ class ImageReader(MeshReader): for x in range(0, width): for y in range(0, height): qrgb = img.pixel(x, y) - avg = float(qRed(qrgb) + qGreen(qrgb) + qBlue(qrgb)) / (3 * 255) - height_data[y, x] = avg + if use_transparency_model: + height_data[y, x] = (0.299 * math.pow(qRed(qrgb) / 255.0, 2.2) + 0.587 * math.pow(qGreen(qrgb) / 255.0, 2.2) + 0.114 * math.pow(qBlue(qrgb) / 255.0, 2.2)) + else: + height_data[y, x] = (0.212655 * qRed(qrgb) + 0.715158 * qGreen(qrgb) + 0.072187 * qBlue(qrgb)) / 255 # fast computation ignoring gamma and degamma Job.yieldThread() - if not lighter_is_higher: + if lighter_is_higher == use_transparency_model: height_data = 1 - height_data for _ in range(0, blur_iterations): @@ -124,8 +128,15 @@ class ImageReader(MeshReader): Job.yieldThread() - height_data *= scale_vector.y - height_data += base_height + if use_transparency_model: + divisor = 1.0 / math.log(transmittance_1mm / 100.0) # log-base doesn't matter here. Precompute this value for faster computation of each pixel. + min_luminance = (transmittance_1mm / 100.0) ** (peak_height - base_height) + for (y, x) in numpy.ndindex(height_data.shape): + mapped_luminance = min_luminance + (1.0 - min_luminance) * height_data[y, x] + height_data[y, x] = base_height + divisor * math.log(mapped_luminance) # use same base as a couple lines above this + else: + height_data *= scale_vector.y + height_data += base_height heightmap_face_count = 2 * height_minus_one * width_minus_one total_face_count = heightmap_face_count + (width_minus_one * 2) * (height_minus_one * 2) + 2 diff --git a/plugins/ImageReader/ImageReaderUI.py b/plugins/ImageReader/ImageReaderUI.py index 213468a2ab..a61fabb742 100644 --- a/plugins/ImageReader/ImageReaderUI.py +++ b/plugins/ImageReader/ImageReaderUI.py @@ -34,6 +34,8 @@ class ImageReaderUI(QObject): self.peak_height = 2.5 self.smoothing = 1 self.lighter_is_higher = False; + self.use_transparency_model = True; + self.transmittance_1mm = 50.0; # based on pearl PLA self._ui_lock = threading.Lock() self._cancelled = False @@ -75,6 +77,7 @@ class ImageReaderUI(QObject): self._ui_view.findChild(QObject, "Base_Height").setProperty("text", str(self.base_height)) self._ui_view.findChild(QObject, "Peak_Height").setProperty("text", str(self.peak_height)) + self._ui_view.findChild(QObject, "Transmittance").setProperty("text", str(self.transmittance_1mm)) self._ui_view.findChild(QObject, "Smoothing").setProperty("value", self.smoothing) def _createConfigUI(self): @@ -144,3 +147,11 @@ class ImageReaderUI(QObject): @pyqtSlot(int) def onImageColorInvertChanged(self, value): self.lighter_is_higher = (value == 1) + + @pyqtSlot(int) + def onColorModelChanged(self, value): + self.use_transparency_model = (value == 0) + + @pyqtSlot(int) + def onTransmittanceChanged(self, value): + self.transmittance_1mm = value diff --git a/plugins/PreviewStage/PreviewMain.qml b/plugins/PreviewStage/PreviewMain.qml index 4ef10e5dbb..2926f0d012 100644 --- a/plugins/PreviewStage/PreviewMain.qml +++ b/plugins/PreviewStage/PreviewMain.qml @@ -12,14 +12,18 @@ import Cura 1.0 as Cura Item { + // An Item whose bounds are guaranteed to be safe for overlays to be placed. + // Defaults to parent, ie. the entire available area + property var safeArea: parent + // Subtract the actionPanel from the safe area. This way the view won't draw interface elements under/over it - Item { - id: safeArea - visible: false - anchors.left: parent.left - anchors.right: actionPanelWidget.left - anchors.top: parent.top - anchors.bottom: actionPanelWidget.top + Item + { + id: childSafeArea + x: safeArea.x - parent.x + y: safeArea.y - parent.y + width: actionPanelWidget.x - x + height: actionPanelWidget.y - y } Loader @@ -29,9 +33,10 @@ Item source: UM.Controller.activeView != null && UM.Controller.activeView.mainComponent != null ? UM.Controller.activeView.mainComponent : "" - onLoaded: { + onLoaded: + { if (previewMain.item.safeArea !== undefined){ - previewMain.item.safeArea = Qt.binding(function() { return safeArea }); + previewMain.item.safeArea = Qt.binding(function() { return childSafeArea }); } } } diff --git a/plugins/SimulationView/PathSlider.qml b/plugins/SimulationView/PathSlider.qml index c7a43c6407..facdbb6a53 100644 --- a/plugins/SimulationView/PathSlider.qml +++ b/plugins/SimulationView/PathSlider.qml @@ -56,6 +56,11 @@ Item return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue) } + onWidthChanged : { + // After a width change, the pixel-position of the handle is out of sync with the property value + setHandleValue(handleValue) + } + // slider track Rectangle { diff --git a/plugins/SimulationView/SimulationViewMainComponent.qml b/plugins/SimulationView/SimulationViewMainComponent.qml index 8d32e50654..bfd8799673 100644 --- a/plugins/SimulationView/SimulationViewMainComponent.qml +++ b/plugins/SimulationView/SimulationViewMainComponent.qml @@ -18,7 +18,10 @@ Item property bool isSimulationPlaying: false - readonly property var layerSliderSafeYMax: safeArea.y + safeArea.height + readonly property real layerSliderSafeYMin: safeArea.y + readonly property real layerSliderSafeYMax: safeArea.y + safeArea.height + readonly property real pathSliderSafeXMin: safeArea.x + playButton.width + readonly property real pathSliderSafeXMax: safeArea.x + safeArea.width visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity @@ -26,13 +29,21 @@ Item PathSlider { id: pathSlider + + readonly property real preferredWidth: UM.Theme.getSize("slider_layerview_size").height // not a typo, should be as long as layerview slider + readonly property real margin: UM.Theme.getSize("default_margin").width + readonly property real pathSliderSafeWidth: pathSliderSafeXMax - pathSliderSafeXMin + height: UM.Theme.getSize("slider_handle").width - width: UM.Theme.getSize("slider_layerview_size").height + width: preferredWidth + margin * 2 < pathSliderSafeWidth ? preferredWidth : pathSliderSafeWidth - margin * 2 + anchors.bottom: parent.bottom - anchors.bottomMargin: UM.Theme.getSize("default_margin").height + anchors.bottomMargin: margin anchors.horizontalCenter: parent.horizontalCenter + anchors.horizontalCenterOffset: -(parent.width - pathSliderSafeXMax - pathSliderSafeXMin) / 2 // center between parent top and layerSliderSafeYMax + visible: !UM.SimulationView.compatibilityMode @@ -184,16 +195,18 @@ Item { property var preferredHeight: UM.Theme.getSize("slider_layerview_size").height property double heightMargin: UM.Theme.getSize("default_margin").height * 3 // extra margin to accomodate layer number tooltips + property double layerSliderSafeHeight: layerSliderSafeYMax - layerSliderSafeYMin + id: layerSlider width: UM.Theme.getSize("slider_handle").width - height: preferredHeight + heightMargin * 2 < layerSliderSafeYMax ? preferredHeight : layerSliderSafeYMax - heightMargin * 2 + height: preferredHeight + heightMargin * 2 < layerSliderSafeHeight ? preferredHeight : layerSliderSafeHeight - heightMargin * 2 anchors { right: parent.right verticalCenter: parent.verticalCenter - verticalCenterOffset: -(parent.height - layerSliderSafeYMax) / 2 // center between parent top and layerSliderSafeYMax + verticalCenterOffset: -(parent.height - layerSliderSafeYMax - layerSliderSafeYMin) / 2 // center between parent top and layerSliderSafeYMax rightMargin: UM.Theme.getSize("default_margin").width bottomMargin: heightMargin topMargin: heightMargin |