#include "ToolExtrinsicWidget.h" #include "ui_ToolExtrinsicWidget.h" #include #include #include #include ToolExtrinsicWidget::ToolExtrinsicWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::ToolExtrinsicWidget) , m_groupExtrinsic(nullptr) , m_comboCamera(nullptr) , m_comboEulerOrder(nullptr) , m_editRotX(nullptr) , m_editRotY(nullptr) , m_editRotZ(nullptr) , m_labelAxialAngleRange(nullptr) , m_widgetAxialAngleRangeRow(nullptr) , m_editAxialAngleMin(nullptr) , m_editAxialAngleMax(nullptr) , m_labelTargetOffset(nullptr) , m_widgetTargetOffsetRow(nullptr) , m_editOffsetX(nullptr) , m_editOffsetY(nullptr) , m_editOffsetZ(nullptr) , m_currentCameraIndex(-1) { setupUI(); } ToolExtrinsicWidget::~ToolExtrinsicWidget() { delete ui; } void ToolExtrinsicWidget::setCameraList(const QVector& cameras) { saveCurrentUiToCache(); if (!m_comboCamera) { return; } m_comboCamera->blockSignals(true); m_comboCamera->clear(); for (const ToolExtrinsicCameraInfo& camera : cameras) { m_comboCamera->addItem(camera.displayName, QVariant(camera.cameraIndex)); ensureData(camera.cameraIndex); } m_comboCamera->blockSignals(false); if (cameras.isEmpty()) { m_currentCameraIndex = -1; loadDataToUi(ToolExtrinsicData{}); } else { m_comboCamera->setCurrentIndex(0); m_currentCameraIndex = cameras.first().cameraIndex; loadDataToUi(ensureData(m_currentCameraIndex)); } } void ToolExtrinsicWidget::setData(int eulerOrder, double rotX, double rotY, double rotZ, double offsetX, double offsetY, double offsetZ) { setData(eulerOrder, rotX, rotY, rotZ, offsetX, offsetY, offsetZ, -180.0, 180.0); } void ToolExtrinsicWidget::setData(int eulerOrder, double rotX, double rotY, double rotZ, double offsetX, double offsetY, double offsetZ, double axialAngleMin, double axialAngleMax) { ToolExtrinsicData data; data.cameraIndex = m_currentCameraIndex; data.eulerOrder = eulerOrder; data.rotX = rotX; data.rotY = rotY; data.rotZ = rotZ; data.axialAngleMin = axialAngleMin; data.axialAngleMax = axialAngleMax; data.offsetX = offsetX; data.offsetY = offsetY; data.offsetZ = offsetZ; loadDataToUi(data); if (m_currentCameraIndex > 0) { ensureData(m_currentCameraIndex) = data; } } void ToolExtrinsicWidget::getData(int& eulerOrder, double& rotX, double& rotY, double& rotZ, double& offsetX, double& offsetY, double& offsetZ) const { double axialAngleMin = -180.0; double axialAngleMax = 180.0; getData(eulerOrder, rotX, rotY, rotZ, offsetX, offsetY, offsetZ, axialAngleMin, axialAngleMax); } void ToolExtrinsicWidget::getData(int& eulerOrder, double& rotX, double& rotY, double& rotZ, double& offsetX, double& offsetY, double& offsetZ, double& axialAngleMin, double& axialAngleMax) const { eulerOrder = m_comboEulerOrder ? m_comboEulerOrder->currentData().toInt() : 11; rotX = m_editRotX ? m_editRotX->text().trimmed().toDouble() : 0.0; rotY = m_editRotY ? m_editRotY->text().trimmed().toDouble() : 0.0; rotZ = m_editRotZ ? m_editRotZ->text().trimmed().toDouble() : 0.0; axialAngleMin = m_editAxialAngleMin ? m_editAxialAngleMin->text().trimmed().toDouble() : -180.0; axialAngleMax = m_editAxialAngleMax ? m_editAxialAngleMax->text().trimmed().toDouble() : 180.0; offsetX = m_editOffsetX ? m_editOffsetX->text().trimmed().toDouble() : 0.0; offsetY = m_editOffsetY ? m_editOffsetY->text().trimmed().toDouble() : 0.0; offsetZ = m_editOffsetZ ? m_editOffsetZ->text().trimmed().toDouble() : 0.0; } void ToolExtrinsicWidget::setData(int cameraIndex, int eulerOrder, double rotX, double rotY, double rotZ, double offsetX, double offsetY, double offsetZ) { setData(cameraIndex, eulerOrder, rotX, rotY, rotZ, offsetX, offsetY, offsetZ, -180.0, 180.0); } void ToolExtrinsicWidget::setData(int cameraIndex, int eulerOrder, double rotX, double rotY, double rotZ, double offsetX, double offsetY, double offsetZ, double axialAngleMin, double axialAngleMax) { ToolExtrinsicData& data = ensureData(cameraIndex); data.eulerOrder = eulerOrder; data.rotX = rotX; data.rotY = rotY; data.rotZ = rotZ; data.axialAngleMin = axialAngleMin; data.axialAngleMax = axialAngleMax; data.offsetX = offsetX; data.offsetY = offsetY; data.offsetZ = offsetZ; if (currentCameraIndex() == cameraIndex) { loadDataToUi(data); } } bool ToolExtrinsicWidget::getData(int cameraIndex, int& eulerOrder, double& rotX, double& rotY, double& rotZ, double& offsetX, double& offsetY, double& offsetZ) const { double axialAngleMin = -180.0; double axialAngleMax = 180.0; return getData(cameraIndex, eulerOrder, rotX, rotY, rotZ, offsetX, offsetY, offsetZ, axialAngleMin, axialAngleMax); } bool ToolExtrinsicWidget::getData(int cameraIndex, int& eulerOrder, double& rotX, double& rotY, double& rotZ, double& offsetX, double& offsetY, double& offsetZ, double& axialAngleMin, double& axialAngleMax) const { if (currentCameraIndex() == cameraIndex) { getData(eulerOrder, rotX, rotY, rotZ, offsetX, offsetY, offsetZ, axialAngleMin, axialAngleMax); return true; } const ToolExtrinsicData* data = findData(cameraIndex); if (!data) { return false; } eulerOrder = data->eulerOrder; rotX = data->rotX; rotY = data->rotY; rotZ = data->rotZ; axialAngleMin = data->axialAngleMin; axialAngleMax = data->axialAngleMax; offsetX = data->offsetX; offsetY = data->offsetY; offsetZ = data->offsetZ; return true; } int ToolExtrinsicWidget::currentCameraIndex() const { if (!m_comboCamera || m_comboCamera->count() == 0 || m_comboCamera->currentIndex() < 0) { return -1; } return m_comboCamera->currentData().toInt(); } void ToolExtrinsicWidget::setTargetOffsetVisible(bool visible) { if (m_labelTargetOffset) m_labelTargetOffset->setVisible(visible); if (m_widgetTargetOffsetRow) m_widgetTargetOffsetRow->setVisible(visible); } void ToolExtrinsicWidget::setAxialAngleRangeVisible(bool visible) { if (m_labelAxialAngleRange) m_labelAxialAngleRange->setVisible(visible); if (m_widgetAxialAngleRangeRow) m_widgetAxialAngleRangeRow->setVisible(visible); } void ToolExtrinsicWidget::onCameraSelectionChanged(int index) { saveCurrentUiToCache(); if (index < 0 || !m_comboCamera || m_comboCamera->count() == 0) { m_currentCameraIndex = -1; loadDataToUi(ToolExtrinsicData{}); return; } m_currentCameraIndex = m_comboCamera->itemData(index).toInt(); loadDataToUi(ensureData(m_currentCameraIndex)); } void ToolExtrinsicWidget::loadDataToUi(const ToolExtrinsicData& data) { if (m_comboEulerOrder) { int idx = m_comboEulerOrder->findData(data.eulerOrder); if (idx < 0) idx = 0; m_comboEulerOrder->setCurrentIndex(idx); } if (m_editRotX) m_editRotX->setText(QString::number(data.rotX, 'f', 3)); if (m_editRotY) m_editRotY->setText(QString::number(data.rotY, 'f', 3)); if (m_editRotZ) m_editRotZ->setText(QString::number(data.rotZ, 'f', 3)); if (m_editAxialAngleMin) m_editAxialAngleMin->setText(QString::number(data.axialAngleMin, 'f', 3)); if (m_editAxialAngleMax) m_editAxialAngleMax->setText(QString::number(data.axialAngleMax, 'f', 3)); if (m_editOffsetX) m_editOffsetX->setText(QString::number(data.offsetX, 'f', 3)); if (m_editOffsetY) m_editOffsetY->setText(QString::number(data.offsetY, 'f', 3)); if (m_editOffsetZ) m_editOffsetZ->setText(QString::number(data.offsetZ, 'f', 3)); } void ToolExtrinsicWidget::saveCurrentUiToCache() { if (m_currentCameraIndex <= 0) { return; } ToolExtrinsicData& data = ensureData(m_currentCameraIndex); data.cameraIndex = m_currentCameraIndex; getData(data.eulerOrder, data.rotX, data.rotY, data.rotZ, data.offsetX, data.offsetY, data.offsetZ, data.axialAngleMin, data.axialAngleMax); } ToolExtrinsicData* ToolExtrinsicWidget::findData(int cameraIndex) { for (ToolExtrinsicData& data : m_dataCache) { if (data.cameraIndex == cameraIndex) { return &data; } } return nullptr; } const ToolExtrinsicData* ToolExtrinsicWidget::findData(int cameraIndex) const { for (const ToolExtrinsicData& data : m_dataCache) { if (data.cameraIndex == cameraIndex) { return &data; } } return nullptr; } ToolExtrinsicData& ToolExtrinsicWidget::ensureData(int cameraIndex) { if (ToolExtrinsicData* data = findData(cameraIndex)) { return *data; } ToolExtrinsicData data; data.cameraIndex = cameraIndex; m_dataCache.append(data); return m_dataCache.last(); } void ToolExtrinsicWidget::initEulerOrderComboBox() { if (!m_comboEulerOrder) return; m_comboEulerOrder->addItem(QStringLiteral("RZ-RY-RX (外旋ZYX)"), 11); m_comboEulerOrder->addItem(QStringLiteral("RX-RY-RZ (外旋XYZ)"), 10); m_comboEulerOrder->addItem(QStringLiteral("RZ-RX-RY (外旋ZXY)"), 12); m_comboEulerOrder->addItem(QStringLiteral("RY-RX-RZ (外旋YXZ)"), 13); m_comboEulerOrder->addItem(QStringLiteral("RY-RZ-RX (外旋YZX)"), 14); m_comboEulerOrder->addItem(QStringLiteral("RX-RZ-RY (外旋XZY)"), 15); m_comboEulerOrder->setCurrentIndex(0); } void ToolExtrinsicWidget::setupUI() { ui->setupUi(this); QFont font; font.setPointSize(16); setStyleSheet( "QLabel { color: rgb(221, 225, 233); }" "QLineEdit { color: rgb(221, 225, 233); background-color: rgb(47, 48, 52); " "border: 1px solid rgb(70, 72, 78); padding: 4px; }" "QComboBox { color: rgb(221, 225, 233); background-color: rgb(47, 48, 52); " "border: 1px solid rgb(70, 72, 78); padding: 6px; }" "QComboBox QAbstractItemView { color: rgb(221, 225, 233); background-color: rgb(47, 48, 52); " "selection-background-color: rgb(70, 100, 150); }" "QGroupBox { color: rgb(221, 225, 233); border: 1px solid rgb(100, 100, 100); " "border-radius: 4px; margin-top: 12px; padding-top: 8px; }" "QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px; }"); const QList widgets = findChildren(); for (QWidget* widget : widgets) { widget->setFont(font); } m_groupExtrinsic = ui->groupExtrinsic; m_comboCamera = ui->comboCamera; m_comboEulerOrder = ui->comboEulerOrder; m_editRotX = ui->editRotX; m_editRotY = ui->editRotY; m_editRotZ = ui->editRotZ; m_labelAxialAngleRange = ui->labelAxialAngleRange; m_widgetAxialAngleRangeRow = ui->widgetAxialAngleRangeRow; m_editAxialAngleMin = ui->editAxialAngleMin; m_editAxialAngleMax = ui->editAxialAngleMax; m_labelTargetOffset = ui->labelTargetOffset; m_widgetTargetOffsetRow = ui->widgetTargetOffsetRow; m_editOffsetX = ui->editOffsetX; m_editOffsetY = ui->editOffsetY; m_editOffsetZ = ui->editOffsetZ; initEulerOrderComboBox(); connect(m_comboCamera, QOverload::of(&QComboBox::currentIndexChanged), this, &ToolExtrinsicWidget::onCameraSelectionChanged); auto* validatorX = new QDoubleValidator(-360.0, 360.0, 3, this); validatorX->setNotation(QDoubleValidator::StandardNotation); auto* validatorY = new QDoubleValidator(-360.0, 360.0, 3, this); validatorY->setNotation(QDoubleValidator::StandardNotation); auto* validatorZ = new QDoubleValidator(-360.0, 360.0, 3, this); validatorZ->setNotation(QDoubleValidator::StandardNotation); m_editRotX->setValidator(validatorX); m_editRotY->setValidator(validatorY); m_editRotZ->setValidator(validatorZ); auto* validatorAxialAngle = new QDoubleValidator(-180.0, 180.0, 3, this); validatorAxialAngle->setNotation(QDoubleValidator::StandardNotation); m_editAxialAngleMin->setValidator(validatorAxialAngle); m_editAxialAngleMax->setValidator(validatorAxialAngle); auto* validatorTargetOffset = new QDoubleValidator(-10000.0, 10000.0, 3, this); validatorTargetOffset->setNotation(QDoubleValidator::StandardNotation); m_editOffsetX->setValidator(validatorTargetOffset); m_editOffsetY->setValidator(validatorTargetOffset); m_editOffsetZ->setValidator(validatorTargetOffset); setTargetOffsetVisible(false); setAxialAngleRangeVisible(false); QVector defaultCameras; ToolExtrinsicCameraInfo defaultCamera; defaultCamera.cameraIndex = 1; defaultCamera.displayName = QStringLiteral("相机 1"); defaultCameras.append(defaultCamera); setCameraList(defaultCameras); setData(11, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); }