230 lines
7.6 KiB
QML
230 lines
7.6 KiB
QML
import QtQuick
|
|
import QtDataVisualization
|
|
import QtQuick.Controls
|
|
|
|
Item {
|
|
property int selectedAxisLabel: -1
|
|
property real dragSpeedModifier: 25.0
|
|
property int currentMouseX: -1
|
|
property int currentMouseY: -1
|
|
property int previousMouseX: -1
|
|
property int previousMouseY: -1
|
|
property alias model: itemModelScatterDataProxy.itemModel
|
|
|
|
property alias selectedItem: scatterSeries.selectedItem
|
|
|
|
// ThemeColor {
|
|
// id: dynamicColor
|
|
// ColorAnimation on color {
|
|
// from: "red"
|
|
// to: "yellow"
|
|
// duration: 2000
|
|
// loops: Animation.Infinite
|
|
// }
|
|
// }
|
|
|
|
Theme3D {
|
|
id: dynamicColorTheme
|
|
type: Theme3D.ThemeEbony
|
|
// baseColors: [dynamicColor]
|
|
font.pointSize: 50
|
|
labelBorderEnabled: true
|
|
labelBackgroundColor: "gold"
|
|
labelTextColor: "black"
|
|
}
|
|
|
|
Theme3D {
|
|
id: isabelleTheme
|
|
type: Theme3D.ThemeIsabelle
|
|
font.pointSize: 50
|
|
labelBorderEnabled: true
|
|
labelBackgroundColor: "gold"
|
|
labelTextColor: "black"
|
|
}
|
|
|
|
Item {
|
|
id: dataView
|
|
anchors.bottom: parent.bottom
|
|
width: parent.width
|
|
height: parent.height
|
|
|
|
//! [0]
|
|
Scatter3D {
|
|
id: scatterGraph
|
|
inputHandler: null
|
|
width: dataView.width
|
|
height: dataView.height
|
|
theme: isabelleTheme
|
|
shadowQuality: AbstractGraph3D.ShadowQualityLow
|
|
scene.activeCamera.yRotation: 45.0
|
|
scene.activeCamera.xRotation: 45.0
|
|
scene.activeCamera.zoomLevel: 75.0
|
|
axisX.min: -10
|
|
axisX.max: 10
|
|
axisY.min: -10
|
|
axisY.max: 10
|
|
axisZ.min: -10
|
|
axisZ.max: 10
|
|
|
|
Scatter3DSeries {
|
|
id: scatterSeries
|
|
itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel"
|
|
mesh: Abstract3DSeries.MeshCube
|
|
|
|
ItemModelScatterDataProxy {
|
|
id: itemModelScatterDataProxy
|
|
xPosRole: "positionX"
|
|
yPosRole: "positionY"
|
|
zPosRole: "positionZ"
|
|
//rotationRole: "rotation"
|
|
}
|
|
}
|
|
onSelectedElementChanged: {
|
|
switch (selectedElement) {
|
|
case Scatter3D.ElementSeries:
|
|
// console.log('series');
|
|
break;
|
|
case Scatter3D.ElementAxisXLabel:
|
|
case Scatter3D.ElementAxisYLabel:
|
|
case Scatter3D.ElementAxisZLabel:
|
|
// console.log('axis');
|
|
if (selectedElement >= AbstractGraph3D.ElementAxisXLabel
|
|
&& selectedElement <= AbstractGraph3D.ElementAxisZLabel)
|
|
selectedAxisLabel = selectedElement
|
|
else
|
|
selectedAxisLabel = -1
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
acceptedButtons: Qt.LeftButton
|
|
|
|
onPositionChanged: (mouse)=> {
|
|
currentMouseX = mouse.x;
|
|
currentMouseY = mouse.y;
|
|
|
|
if (pressed && selectedAxisLabel != -1)
|
|
dragAxis();
|
|
|
|
previousMouseX = currentMouseX;
|
|
previousMouseY = currentMouseY;
|
|
}
|
|
|
|
onPressed: (mouse)=> {
|
|
scatterGraph.scene.selectionQueryPosition = Qt.point(mouse.x, mouse.y);
|
|
}
|
|
|
|
onReleased: {
|
|
// We need to clear mouse positions and selected axis, because touch devices cannot
|
|
// track position all the time
|
|
selectedAxisLabel = -1
|
|
currentMouseX = -1
|
|
currentMouseY = -1
|
|
previousMouseX = -1
|
|
previousMouseY = -1
|
|
}
|
|
}
|
|
}
|
|
|
|
function dragAxis() {
|
|
// Do nothing if previous mouse position is uninitialized
|
|
if (previousMouseX === -1)
|
|
return
|
|
|
|
// Directional drag multipliers based on rotation. Camera is locked to 45 degrees, so we
|
|
// can use one precalculated value instead of calculating xx, xy, zx and zy individually
|
|
var cameraMultiplier = 0.70710678
|
|
|
|
// Calculate the mouse move amount
|
|
var moveX = currentMouseX - previousMouseX
|
|
var moveY = currentMouseY - previousMouseY
|
|
|
|
// Adjust axes
|
|
switch (selectedAxisLabel) {
|
|
case AbstractGraph3D.ElementAxisXLabel:
|
|
var distance = ((moveX - moveY) * cameraMultiplier) / dragSpeedModifier
|
|
// Check if we need to change min or max first to avoid invalid ranges
|
|
if (distance > 0) {
|
|
scatterGraph.axisX.min -= distance
|
|
scatterGraph.axisX.max -= distance
|
|
} else {
|
|
scatterGraph.axisX.max -= distance
|
|
scatterGraph.axisX.min -= distance
|
|
}
|
|
break
|
|
case AbstractGraph3D.ElementAxisYLabel:
|
|
distance = moveY / dragSpeedModifier
|
|
// Check if we need to change min or max first to avoid invalid ranges
|
|
if (distance > 0) {
|
|
scatterGraph.axisY.max += distance
|
|
scatterGraph.axisY.min += distance
|
|
} else {
|
|
scatterGraph.axisY.min += distance
|
|
scatterGraph.axisY.max += distance
|
|
}
|
|
break
|
|
case AbstractGraph3D.ElementAxisZLabel:
|
|
distance = ((moveX + moveY) * cameraMultiplier) / dragSpeedModifier
|
|
// Check if we need to change min or max first to avoid invalid ranges
|
|
if (distance > 0) {
|
|
scatterGraph.axisZ.max += distance
|
|
scatterGraph.axisZ.min += distance
|
|
} else {
|
|
scatterGraph.axisZ.min += distance
|
|
scatterGraph.axisZ.max += distance
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
Button {
|
|
id: rangeToggle
|
|
width: parent.width / 2 // We're adding 3 buttons and want to divide them equally
|
|
text: "Use Preset Range"
|
|
anchors.left: parent.left
|
|
property bool autoRange: true
|
|
onClicked: {
|
|
if (autoRange) {
|
|
text = "Use Automatic Range"
|
|
scatterGraph.axisX.min = -10
|
|
scatterGraph.axisX.max = 10
|
|
scatterGraph.axisY.min = -10
|
|
scatterGraph.axisY.max = 10
|
|
scatterGraph.axisZ.min = -10
|
|
scatterGraph.axisZ.max = 10
|
|
autoRange = false
|
|
dragSpeedModifier = 25.0
|
|
} else {
|
|
text = "Use Preset Range"
|
|
autoRange = true
|
|
dragSpeedModifier = 25.0
|
|
}
|
|
scatterGraph.axisX.autoAdjustRange = autoRange
|
|
scatterGraph.axisY.autoAdjustRange = autoRange
|
|
scatterGraph.axisZ.autoAdjustRange = autoRange
|
|
}
|
|
}
|
|
|
|
Button {
|
|
id: orthoToggle
|
|
width: parent.width / 2
|
|
text: "Display Orthographic"
|
|
anchors.left: rangeToggle.right
|
|
onClicked: {
|
|
if (scatterGraph.orthoProjection) {
|
|
text = "Display Orthographic";
|
|
scatterGraph.orthoProjection = false
|
|
// Orthographic projection disables shadows, so we need to switch them back on
|
|
scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityLow
|
|
} else {
|
|
text = "Display Perspective";
|
|
scatterGraph.orthoProjection = true
|
|
}
|
|
}
|
|
}
|
|
}
|