386 lines
14 KiB
C++
386 lines
14 KiB
C++
#include "ToolExtrinsicWidget.h"
|
|
#include "ui_ToolExtrinsicWidget.h"
|
|
|
|
#include <QDoubleValidator>
|
|
#include <QFont>
|
|
#include <QList>
|
|
#include <QVariant>
|
|
|
|
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<ToolExtrinsicCameraInfo>& 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', 6));
|
|
if (m_editRotY) m_editRotY->setText(QString::number(data.rotY, 'f', 6));
|
|
if (m_editRotZ) m_editRotZ->setText(QString::number(data.rotZ, 'f', 6));
|
|
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<QWidget*> widgets = findChildren<QWidget*>();
|
|
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<int>::of(&QComboBox::currentIndexChanged),
|
|
this, &ToolExtrinsicWidget::onCameraSelectionChanged);
|
|
|
|
auto* validatorX = new QDoubleValidator(-360.0, 360.0, 6, this);
|
|
validatorX->setNotation(QDoubleValidator::StandardNotation);
|
|
auto* validatorY = new QDoubleValidator(-360.0, 360.0, 6, this);
|
|
validatorY->setNotation(QDoubleValidator::StandardNotation);
|
|
auto* validatorZ = new QDoubleValidator(-360.0, 360.0, 6, 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<ToolExtrinsicCameraInfo> 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);
|
|
}
|