mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-04-29 18:27:23 +02:00
Merge pull request #2235 from alicevision/dev/resectionIdFiltering
[Viewer3D] Add slider to display cameras based on their resection IDs
This commit is contained in:
commit
df6d38f391
9 changed files with 301 additions and 18 deletions
76
meshroom/ui/qml/Controls/ExpandableGroup.qml
Normal file
76
meshroom/ui/qml/Controls/ExpandableGroup.qml
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.11
|
||||||
|
import MaterialIcons 2.2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom GroupBox with predefined header that can be hidden and expanded.
|
||||||
|
*/
|
||||||
|
GroupBox {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
title: ""
|
||||||
|
property int sidePadding: 6
|
||||||
|
property alias labelBackground: labelBg
|
||||||
|
property alias toolBarContent: toolBar.data
|
||||||
|
property bool expanded: expandButton.checked
|
||||||
|
|
||||||
|
padding: 2
|
||||||
|
leftPadding: sidePadding
|
||||||
|
rightPadding: sidePadding
|
||||||
|
topPadding: label.height + padding
|
||||||
|
background: Item {}
|
||||||
|
|
||||||
|
label: Pane {
|
||||||
|
background: Rectangle {
|
||||||
|
id: labelBg
|
||||||
|
color: palette.base
|
||||||
|
opacity: 0.8
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
expandButton.checked = !expandButton.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
padding: 2
|
||||||
|
width: root.width
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
width: parent.width
|
||||||
|
Label {
|
||||||
|
text: root.title
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
padding: 3
|
||||||
|
font.bold: true
|
||||||
|
font.pointSize: 8
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
id: toolBar
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
MaterialToolButton {
|
||||||
|
id: expandButton
|
||||||
|
ToolTip.text: "Expand More"
|
||||||
|
text: MaterialIcons.expand_more
|
||||||
|
font.pointSize: 10
|
||||||
|
implicitHeight: parent.height
|
||||||
|
checkable: true
|
||||||
|
checked: false
|
||||||
|
|
||||||
|
onCheckedChanged: {
|
||||||
|
if (checked) {
|
||||||
|
ToolTip.text = "Expand Less"
|
||||||
|
text = MaterialIcons.expand_less
|
||||||
|
} else {
|
||||||
|
ToolTip.text = "Expand More"
|
||||||
|
text = MaterialIcons.expand_more
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
module Controls
|
module Controls
|
||||||
|
|
||||||
ColorChart 1.0 ColorChart.qml
|
ColorChart 1.0 ColorChart.qml
|
||||||
|
ExpandableGroup 1.0 ExpandableGroup.qml
|
||||||
FloatingPane 1.0 FloatingPane.qml
|
FloatingPane 1.0 FloatingPane.qml
|
||||||
Group 1.0 Group.qml
|
Group 1.0 Group.qml
|
||||||
KeyValue 1.0 KeyValue.qml
|
KeyValue 1.0 KeyValue.qml
|
||||||
|
|
|
@ -92,6 +92,7 @@ QtObject {
|
||||||
readonly property string attachment: "\ue2bc"
|
readonly property string attachment: "\ue2bc"
|
||||||
readonly property string audiotrack: "\ue3a1"
|
readonly property string audiotrack: "\ue3a1"
|
||||||
readonly property string autorenew: "\ue863"
|
readonly property string autorenew: "\ue863"
|
||||||
|
readonly property string auto_awesome_motion: "\ue661"
|
||||||
readonly property string av_timer: "\ue01b"
|
readonly property string av_timer: "\ue01b"
|
||||||
readonly property string backspace: "\ue14a"
|
readonly property string backspace: "\ue14a"
|
||||||
readonly property string backup: "\ue864"
|
readonly property string backup: "\ue864"
|
||||||
|
|
|
@ -31,7 +31,8 @@ FloatingPane {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 4
|
spacing: 4
|
||||||
|
|
||||||
Group {
|
ExpandableGroup {
|
||||||
|
id: displayGroup
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
title: "DISPLAY"
|
title: "DISPLAY"
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ FloatingPane {
|
||||||
Flow {
|
Flow {
|
||||||
Layout.columnSpan: 2
|
Layout.columnSpan: 2
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
visible: displayGroup.expanded
|
||||||
spacing: 1
|
spacing: 1
|
||||||
MaterialToolButton {
|
MaterialToolButton {
|
||||||
text: MaterialIcons.grid_on
|
text: MaterialIcons.grid_on
|
||||||
|
@ -63,8 +65,13 @@ FloatingPane {
|
||||||
onClicked: Viewer3DSettings.displayOrigin = !Viewer3DSettings.displayOrigin
|
onClicked: Viewer3DSettings.displayOrigin = !Viewer3DSettings.displayOrigin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MaterialLabel { text: MaterialIcons.grain; padding: 2 }
|
MaterialLabel {
|
||||||
|
text: MaterialIcons.grain
|
||||||
|
padding: 2
|
||||||
|
visible: displayGroup.expanded
|
||||||
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
visible: displayGroup.expanded
|
||||||
Slider {
|
Slider {
|
||||||
Layout.fillWidth: true; from: 0; to: 5; stepSize: 0.001
|
Layout.fillWidth: true; from: 0; to: 5; stepSize: 0.001
|
||||||
value: Viewer3DSettings.pointSize
|
value: Viewer3DSettings.pointSize
|
||||||
|
@ -83,8 +90,13 @@ FloatingPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
MaterialLabel { text: MaterialIcons.videocam; padding: 2 }
|
MaterialLabel {
|
||||||
|
text: MaterialIcons.videocam
|
||||||
|
padding: 2
|
||||||
|
visible: displayGroup.expanded
|
||||||
|
}
|
||||||
Slider {
|
Slider {
|
||||||
|
visible: displayGroup.expanded
|
||||||
value: Viewer3DSettings.cameraScale
|
value: Viewer3DSettings.cameraScale
|
||||||
from: 0
|
from: 0
|
||||||
to: 2
|
to: 2
|
||||||
|
@ -99,25 +111,30 @@ FloatingPane {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Group {
|
ExpandableGroup {
|
||||||
|
id: cameraGroup
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
title: "CAMERA"
|
title: "CAMERA"
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
// Image/Camera synchronization
|
// Image/Camera synchronization
|
||||||
Flow {
|
Flow {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
visible: cameraGroup.expanded
|
||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
// Synchronization
|
// Synchronization
|
||||||
MaterialToolButton {
|
MaterialToolButton {
|
||||||
id: syncViewpointCamera
|
id: syncViewpointCamera
|
||||||
enabled: _reconstruction ? _reconstruction.sfmReport : false
|
enabled: _reconstruction ? _reconstruction.sfmReport : false
|
||||||
text: MaterialIcons.linked_camera
|
text: MaterialIcons.linked_camera
|
||||||
ToolTip.text: "Sync with Image Selection"
|
ToolTip.text: "View Through The Active Camera"
|
||||||
checked: enabled && Viewer3DSettings.syncViewpointCamera
|
checked: enabled && Viewer3DSettings.syncViewpointCamera
|
||||||
onClicked: Viewer3DSettings.syncViewpointCamera = !Viewer3DSettings.syncViewpointCamera
|
onClicked: Viewer3DSettings.syncViewpointCamera = !Viewer3DSettings.syncViewpointCamera
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image Overlay controls
|
// Image Overlay controls
|
||||||
RowLayout {
|
RowLayout {
|
||||||
visible: syncViewpointCamera.enabled && Viewer3DSettings.syncViewpointCamera
|
visible: syncViewpointCamera.enabled && Viewer3DSettings.syncViewpointCamera
|
||||||
|
@ -152,6 +169,109 @@ FloatingPane {
|
||||||
onClicked: Viewer3DSettings.viewpointImageFrame = !Viewer3DSettings.viewpointImageFrame
|
onClicked: Viewer3DSettings.viewpointImageFrame = !Viewer3DSettings.viewpointImageFrame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 2
|
||||||
|
visible: cameraGroup.expanded
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
spacing: 2
|
||||||
|
|
||||||
|
MaterialToolButton {
|
||||||
|
id: resectionIdButton
|
||||||
|
text: MaterialIcons.switch_video
|
||||||
|
ToolTip.text: "Timeline Of Camera Reconstruction Groups"
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
enabled: Viewer3DSettings.resectionIdCount
|
||||||
|
checked: enabled && Viewer3DSettings.displayResectionIds
|
||||||
|
onClicked: {
|
||||||
|
Viewer3DSettings.displayResectionIds = !Viewer3DSettings.displayResectionIds
|
||||||
|
Viewer3DSettings.resectionId = Viewer3DSettings.resectionIdCount
|
||||||
|
resectionIdSlider.value = Viewer3DSettings.resectionId
|
||||||
|
}
|
||||||
|
|
||||||
|
onEnabledChanged: {
|
||||||
|
Viewer3DSettings.resectionId = Viewer3DSettings.resectionIdCount
|
||||||
|
resectionIdSlider.value = Viewer3DSettings.resectionId
|
||||||
|
if (!enabled) {
|
||||||
|
Viewer3DSettings.displayResectionIds = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Slider {
|
||||||
|
id: resectionIdSlider
|
||||||
|
value: Viewer3DSettings.resectionId
|
||||||
|
from: 0
|
||||||
|
to: Viewer3DSettings.resectionIdCount
|
||||||
|
stepSize: 1
|
||||||
|
onMoved: Viewer3DSettings.resectionId = value
|
||||||
|
Layout.fillWidth: true
|
||||||
|
leftPadding: 2
|
||||||
|
rightPadding: 2
|
||||||
|
visible: Viewer3DSettings.displayResectionIds
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: resectionIdSlider.value + "/" + Viewer3DSettings.resectionIdCount
|
||||||
|
visible: Viewer3DSettings.displayResectionIds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 10
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 2
|
||||||
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
|
||||||
|
MaterialToolLabel {
|
||||||
|
iconText: MaterialIcons.stop
|
||||||
|
label: {
|
||||||
|
var id = undefined
|
||||||
|
// Ensure there are entries in resectionGroups and a valid resectionId before accessing anything
|
||||||
|
if (Viewer3DSettings.resectionId !== undefined && Viewer3DSettings.resectionGroups.length > 0)
|
||||||
|
id = Math.min(Viewer3DSettings.resectionId, Viewer3DSettings.resectionIdCount)
|
||||||
|
if (id !== undefined && Viewer3DSettings.resectionGroups[id] !== undefined)
|
||||||
|
return Viewer3DSettings.resectionGroups[id]
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
||||||
|
ToolTip.text: "Number Of Cameras In Current Resection Group"
|
||||||
|
visible: Viewer3DSettings.displayResectionIds
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialToolLabel {
|
||||||
|
iconText: MaterialIcons.auto_awesome_motion
|
||||||
|
label: {
|
||||||
|
let currentCameras = 0
|
||||||
|
for (let i = 0; i <= Viewer3DSettings.resectionIdCount; i++) {
|
||||||
|
if (i <= Viewer3DSettings.resectionId)
|
||||||
|
currentCameras += Viewer3DSettings.resectionGroups[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentCameras
|
||||||
|
}
|
||||||
|
ToolTip.text: "Number Of Cumulated Cameras"
|
||||||
|
visible: Viewer3DSettings.displayResectionIds
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialToolLabel {
|
||||||
|
iconText: MaterialIcons.videocam
|
||||||
|
label: {
|
||||||
|
let totalCameras = 0
|
||||||
|
for (let i = 0; i <= Viewer3DSettings.resectionIdCount; i++) {
|
||||||
|
totalCameras += Viewer3DSettings.resectionGroups[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalCameras
|
||||||
|
}
|
||||||
|
ToolTip.text: "Total Number Of Cameras"
|
||||||
|
visible: Viewer3DSettings.displayResectionIds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +312,12 @@ FloatingPane {
|
||||||
|
|
||||||
ScrollBar.vertical: ScrollBar { id: scrollBar }
|
ScrollBar.vertical: ScrollBar { id: scrollBar }
|
||||||
|
|
||||||
|
onCountChanged: {
|
||||||
|
if (mediaListView.count === 0) {
|
||||||
|
Viewer3DSettings.resectionIdCount = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
currentIndex: -1
|
currentIndex: -1
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
@ -223,7 +349,19 @@ FloatingPane {
|
||||||
onIsSelectedNodeChanged: updateCurrentIndex()
|
onIsSelectedNodeChanged: updateCurrentIndex()
|
||||||
|
|
||||||
function updateCurrentIndex() {
|
function updateCurrentIndex() {
|
||||||
if(isSelectedNode) { mediaListView.currentIndex = index }
|
if (isSelectedNode) {
|
||||||
|
mediaListView.currentIndex = index
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the index is updated, and the resection ID count is available, update every resection-related variable:
|
||||||
|
// this covers the changes of index that occur when a node whose output is already loaded in the 3D viewer is
|
||||||
|
// clicked/double-clicked, and when the active entry is removed from the list.
|
||||||
|
if (model.resectionIdCount) {
|
||||||
|
Viewer3DSettings.resectionIdCount = model.resectionIdCount
|
||||||
|
Viewer3DSettings.resectionGroups = model.resectionGroups
|
||||||
|
Viewer3DSettings.resectionId = model.resectionId
|
||||||
|
resectionIdSlider.value = model.resectionId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
|
@ -234,22 +372,41 @@ FloatingPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: { if (model.attribute) uigraph.hoveredNode = model.attribute.node }
|
onEntered: {
|
||||||
onExited: { if (model.attribute) uigraph.hoveredNode = null }
|
if (model.attribute)
|
||||||
|
uigraph.hoveredNode = model.attribute.node
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
if (model.attribute)
|
||||||
|
uigraph.hoveredNode = null
|
||||||
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (model.attribute)
|
if (model.attribute)
|
||||||
uigraph.selectedNode = model.attribute.node;
|
uigraph.selectedNode = model.attribute.node
|
||||||
else
|
else
|
||||||
uigraph.selectedNode = null;
|
uigraph.selectedNode = null
|
||||||
if (mouse.button == Qt.RightButton)
|
if (mouse.button == Qt.RightButton)
|
||||||
contextMenu.popup();
|
contextMenu.popup()
|
||||||
mediaListView.currentIndex = index;
|
mediaListView.currentIndex = index
|
||||||
|
|
||||||
|
// Update the resection ID-related objects based on the active model
|
||||||
|
Viewer3DSettings.resectionIdCount = model.resectionIdCount
|
||||||
|
Viewer3DSettings.resectionGroups = model.resectionGroups
|
||||||
|
Viewer3DSettings.resectionId = model.resectionId
|
||||||
|
resectionIdSlider.value = model.resectionId
|
||||||
}
|
}
|
||||||
onDoubleClicked: {
|
onDoubleClicked: {
|
||||||
model.visible = true;
|
model.visible = true;
|
||||||
nodeActivated(model.attribute.node);
|
nodeActivated(model.attribute.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: resectionIdSlider
|
||||||
|
function onValueChanged() {
|
||||||
|
model.resectionId = resectionIdSlider.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
|
@ -58,6 +58,9 @@ Entity {
|
||||||
"faceCount": 0,
|
"faceCount": 0,
|
||||||
"cameraCount": 0,
|
"cameraCount": 0,
|
||||||
"textureCount": 0,
|
"textureCount": 0,
|
||||||
|
"resectionIdCount": 0,
|
||||||
|
"resectionId": 0,
|
||||||
|
"resectionGroups": [],
|
||||||
"status": SceneLoader.None
|
"status": SceneLoader.None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -308,12 +311,11 @@ Entity {
|
||||||
if (object) {
|
if (object) {
|
||||||
// bind media info to corresponding model roles
|
// bind media info to corresponding model roles
|
||||||
// (test for object validity to avoid error messages right after object has been deleted)
|
// (test for object validity to avoid error messages right after object has been deleted)
|
||||||
var boundProperties = ["vertexCount", "faceCount", "cameraCount", "textureCount"]
|
var boundProperties = ["vertexCount", "faceCount", "cameraCount", "textureCount", "resectionIdCount", "resectionId", "resectionGroups"]
|
||||||
boundProperties.forEach(function(prop) {
|
boundProperties.forEach(function(prop) {
|
||||||
model[prop] = Qt.binding(function() { return object ? object[prop] : 0 })
|
model[prop] = Qt.binding(function() { return object ? object[prop] : 0 })
|
||||||
})
|
})
|
||||||
}
|
} else if (finalSource && status === Component.Ready) {
|
||||||
else if (finalSource && status === Component.Ready) {
|
|
||||||
// source was valid but no loader was created, remove element
|
// source was valid but no loader was created, remove element
|
||||||
// check if component is ready to avoid removing element from the model before adding instance to the node
|
// check if component is ready to avoid removing element from the model before adding instance to the node
|
||||||
remove(index)
|
remove(index)
|
||||||
|
|
|
@ -99,8 +99,9 @@ import Utils 1.0
|
||||||
'source': source,
|
'source': source,
|
||||||
'pointSize': Qt.binding(function() { return 0.01 * Viewer3DSettings.pointSize }),
|
'pointSize': Qt.binding(function() { return 0.01 * Viewer3DSettings.pointSize }),
|
||||||
'locatorScale': Qt.binding(function() { return Viewer3DSettings.cameraScale }),
|
'locatorScale': Qt.binding(function() { return Viewer3DSettings.cameraScale }),
|
||||||
'cameraPickingEnabled': Qt.binding(function() { return root.enabled })
|
'cameraPickingEnabled': Qt.binding(function() { return root.enabled }),
|
||||||
})
|
'resectionId': Qt.binding(function() { return Viewer3DSettings.resectionId })
|
||||||
|
});
|
||||||
|
|
||||||
obj.statusChanged.connect(function() {
|
obj.statusChanged.connect(function() {
|
||||||
if (obj.status === SceneLoader.Ready) {
|
if (obj.status === SceneLoader.Ready) {
|
||||||
|
@ -109,6 +110,11 @@ import Utils 1.0
|
||||||
}
|
}
|
||||||
cameraCount = obj.spawnCameraSelectors();
|
cameraCount = obj.spawnCameraSelectors();
|
||||||
}
|
}
|
||||||
|
Viewer3DSettings.resectionIdCount = obj.countResectionIds();
|
||||||
|
Viewer3DSettings.resectionGroups = obj.countResectionGroups(Viewer3DSettings.resectionIdCount + 1);
|
||||||
|
resectionIdCount = Viewer3DSettings.resectionIdCount
|
||||||
|
resectionGroups = Viewer3DSettings.resectionGroups
|
||||||
|
resectionId = Viewer3DSettings.resectionIdCount
|
||||||
root.status = obj.status;
|
root.status = obj.status;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,10 @@ Entity {
|
||||||
property int cameraCount
|
property int cameraCount
|
||||||
/// Number of textures
|
/// Number of textures
|
||||||
property int textureCount
|
property int textureCount
|
||||||
|
/// Number of resection IDs
|
||||||
|
property int resectionIdCount
|
||||||
|
/// Current resection ID
|
||||||
|
property int resectionId
|
||||||
|
/// Groups of cameras based on resection IDs
|
||||||
|
property var resectionGroups
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,34 @@ SfmDataEntity {
|
||||||
return validCameras;
|
return validCameras;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function countResectionIds() {
|
||||||
|
var maxResectionId = 0
|
||||||
|
for (var i = 0; i < root.cameras.length; i++) {
|
||||||
|
var cam = root.cameras[i]
|
||||||
|
var resectionId = cam.resectionId
|
||||||
|
if (resectionId === undefined || resectionId === 4294967295)
|
||||||
|
continue
|
||||||
|
if (resectionId > maxResectionId)
|
||||||
|
maxResectionId = resectionId
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxResectionId
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function countResectionGroups(resectionIdCount) {
|
||||||
|
var arr = Array(resectionIdCount).fill(0)
|
||||||
|
for (var i = 0; i < root.cameras.length; i++) {
|
||||||
|
var cam = root.cameras[i]
|
||||||
|
var resectionId = cam.resectionId
|
||||||
|
if (resectionId === undefined || resectionId === 4294967295)
|
||||||
|
continue
|
||||||
|
arr[resectionId] = arr[resectionId] + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
SystemPalette {
|
SystemPalette {
|
||||||
id: activePalette
|
id: activePalette
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,4 +56,10 @@ Item {
|
||||||
readonly property bool showViewpointImageOverlay: syncViewpointCamera && viewpointImageOverlay
|
readonly property bool showViewpointImageOverlay: syncViewpointCamera && viewpointImageOverlay
|
||||||
property bool viewpointImageFrame: false
|
property bool viewpointImageFrame: false
|
||||||
readonly property bool showViewpointImageFrame: syncViewpointCamera && viewpointImageFrame
|
readonly property bool showViewpointImageFrame: syncViewpointCamera && viewpointImageFrame
|
||||||
|
|
||||||
|
// Cameras' resection IDs
|
||||||
|
property bool displayResectionIds: false
|
||||||
|
property int resectionIdCount: 0
|
||||||
|
property int resectionId: resectionIdCount
|
||||||
|
property var resectionGroups: [] // Number of cameras for each resection ID
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue