modified surfacepanel
This commit is contained in:
parent
863e0867ce
commit
843d2cf158
@ -4,9 +4,9 @@
|
|||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
// Forward declarations for future panel types
|
// Forward declarations for future panel types
|
||||||
// #include "SurfacePanel.h"
|
#include "SurfacePanel.h"
|
||||||
#include "TablePanel.h"
|
#include "TablePanel.h"
|
||||||
// #include "LightPanel.h"
|
#include "LightPanel.h"
|
||||||
|
|
||||||
DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, const QString& filePath, QWidget* parent)
|
DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, const QString& filePath, QWidget* parent)
|
||||||
{
|
{
|
||||||
@ -19,7 +19,7 @@ DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, cons
|
|||||||
case FileEntryType::Surface:
|
case FileEntryType::Surface:
|
||||||
// TODO: Implement SurfacePanel
|
// TODO: Implement SurfacePanel
|
||||||
LOG_WARN("SurfacePanel not implemented yet, creating base DataPanel");
|
LOG_WARN("SurfacePanel not implemented yet, creating base DataPanel");
|
||||||
return new DataPanel(index, fileType, filePath, parent);
|
return new SurfacePanel(index, filePath, parent);
|
||||||
|
|
||||||
case FileEntryType::Table:
|
case FileEntryType::Table:
|
||||||
// TODO: Implement TablePanel
|
// TODO: Implement TablePanel
|
||||||
@ -29,7 +29,7 @@ DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, cons
|
|||||||
case FileEntryType::Light:
|
case FileEntryType::Light:
|
||||||
// TODO: Implement LightPanel
|
// TODO: Implement LightPanel
|
||||||
LOG_WARN("LightPanel not implemented yet, creating base DataPanel");
|
LOG_WARN("LightPanel not implemented yet, creating base DataPanel");
|
||||||
return new DataPanel(index, fileType, filePath, parent);
|
return new LightPanel(index, filePath, parent);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Unsupported file type: {}", static_cast<int>(fileType));
|
LOG_ERROR("Unsupported file type: {}", static_cast<int>(fileType));
|
||||||
|
|||||||
85
src/ui/Panel/LightPanel.cpp
Normal file
85
src/ui/Panel/LightPanel.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include "ui/Panel/LightPanel.h"
|
||||||
|
#include "ui/DockWidget.h"
|
||||||
|
#include "ui/DockTitleBar.h"
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
LightPanel::LightPanel(int index, const QString& filePath, QWidget* parent)
|
||||||
|
: DataPanel(index, FileEntryType::Curve, filePath, parent)
|
||||||
|
{
|
||||||
|
LOG_INFO("Created LightPanel {} for file: {}", index, filePath.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
LightPanel::LightPanel(int index, std::shared_ptr<FileEntryLight> fileEntry, QWidget* parent)
|
||||||
|
: DataPanel(index, fileEntry, parent)
|
||||||
|
{
|
||||||
|
if (fileEntry) {
|
||||||
|
LOG_INFO("Created LightPanel {} for chart: {}", index, fileEntry->GetName().toStdString());
|
||||||
|
// Override the title with chart name
|
||||||
|
title_ = QString("Light Panel %1 - %2").arg(index).arg(fileEntry->GetName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_WARN("Created LightPanel {} with null chart data", index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LightPanel::~LightPanel()
|
||||||
|
{
|
||||||
|
LOG_INFO("Destroyed LightPanel {}", GetIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightPanel::RefreshPanel()
|
||||||
|
{
|
||||||
|
// Implement curve-specific refresh logic here
|
||||||
|
DataPanel::RefreshPanel();
|
||||||
|
|
||||||
|
if (auto fileEntry = fileEntry_->AsLight()) {
|
||||||
|
OnDataPanelUpdated(fileEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Refreshed TablePanel {}", GetIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightPanel::InitUI()
|
||||||
|
{
|
||||||
|
|
||||||
|
QHBoxLayout* mainLayout = new QHBoxLayout(this);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
//mainLayout->addWidget(m_pTableWidget);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LightPanel::GetTypeDisplayName() const
|
||||||
|
{
|
||||||
|
return "Light";
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightPanel::OnDataPanelUpdated(FileEntryLight* fileEntry)
|
||||||
|
{
|
||||||
|
QString strName = fileEntry->GetName();
|
||||||
|
updateTitle(strName);
|
||||||
|
|
||||||
|
//FileEntryTable::ChartProperties propChart = fileEntry->GetChartProperties();
|
||||||
|
|
||||||
|
//QStringList tableHeader = propChart.headerString.split(',', Qt::SkipEmptyParts);
|
||||||
|
//SetHeader(tableHeader);
|
||||||
|
|
||||||
|
//QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName();
|
||||||
|
//FileEntryTable::TableProperties listCurve = fileEntry->GetTableProperties();
|
||||||
|
//updateParseFile(strFile, propChart.timeParam, listCurve);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightPanel::OnTimeChanged(double time)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightPanel::updateTitle(const QString & title)
|
||||||
|
{
|
||||||
|
if (nullptr != dockWidget_)
|
||||||
|
{
|
||||||
|
dockWidget_->setWindowTitle(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/ui/Panel/LightPanel.h
Normal file
63
src/ui/Panel/LightPanel.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DataPanel.h"
|
||||||
|
#include "workspace/FileEntry.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class LightPanel : public DataPanel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
* @param index Panel index
|
||||||
|
* @param filePath Associated file path
|
||||||
|
* @param parent Parent widget
|
||||||
|
*/
|
||||||
|
explicit LightPanel(int index, const QString& filePath, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor with chart data
|
||||||
|
* @param index Panel index
|
||||||
|
* @param chartData Chart data containing curve information
|
||||||
|
* @param parent Parent widget
|
||||||
|
*/
|
||||||
|
explicit LightPanel(int index, std::shared_ptr<FileEntryLight> fileEntry, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
|
virtual ~LightPanel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get file type
|
||||||
|
* @return File type (always Curve for this class)
|
||||||
|
*/
|
||||||
|
FileEntryType GetFileType() const override { return FileEntryType::Light; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Refresh panel content
|
||||||
|
*/
|
||||||
|
void RefreshPanel() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief Initialize UI for curve-specific layout
|
||||||
|
*/
|
||||||
|
virtual void InitUI();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get type display name
|
||||||
|
* @return Display name for curve type
|
||||||
|
*/
|
||||||
|
QString GetTypeDisplayName() const override;
|
||||||
|
|
||||||
|
void OnDataPanelUpdated(FileEntryLight* fileEntry);
|
||||||
|
|
||||||
|
virtual void OnTimeChanged(double time);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateTitle(const QString& title);
|
||||||
|
};
|
||||||
|
|
||||||
388
src/ui/Panel/SurfacePanel.cpp
Normal file
388
src/ui/Panel/SurfacePanel.cpp
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
#include "ui/Panel/SurfacePanel.h"
|
||||||
|
#include "ui/DockWidget.h"
|
||||||
|
#include "ui/DockTitleBar.h"
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <Q3DCamera>
|
||||||
|
|
||||||
|
SurfacePanel::SurfacePanel(int index, const QString& filePath, QWidget* parent)
|
||||||
|
: DataPanel(index, FileEntryType::Curve, filePath, parent)
|
||||||
|
{
|
||||||
|
m_iMinX = 0; m_iMaxX = 0;
|
||||||
|
m_iMinY = 0; m_iMaxY = 0;
|
||||||
|
m_iMinZ = 0; m_iMaxZ = 0;
|
||||||
|
|
||||||
|
LOG_INFO("Created SurfacePanel {} for file: {}", index, filePath.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfacePanel::SurfacePanel(int index, std::shared_ptr<FileEntrySurface> fileEntry, QWidget* parent)
|
||||||
|
: DataPanel(index, fileEntry, parent)
|
||||||
|
{
|
||||||
|
m_iMinX = 0; m_iMaxX = 0;
|
||||||
|
m_iMinY = 0; m_iMaxY = 0;
|
||||||
|
m_iMinZ = 0; m_iMaxZ = 0;
|
||||||
|
|
||||||
|
if (fileEntry) {
|
||||||
|
LOG_INFO("Created SurfacePanel {} for chart: {}", index, fileEntry->GetName().toStdString());
|
||||||
|
// Override the title with chart name
|
||||||
|
title_ = QString("Surface Panel %1 - %2").arg(index).arg(fileEntry->GetName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_WARN("Created SurfacePanel {} with null chart data", index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfacePanel::~SurfacePanel()
|
||||||
|
{
|
||||||
|
LOG_INFO("Destroyed SurfacePanel {}", GetIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::RefreshPanel()
|
||||||
|
{
|
||||||
|
// Implement curve-specific refresh logic here
|
||||||
|
DataPanel::RefreshPanel();
|
||||||
|
|
||||||
|
if (auto fileEntry = fileEntry_->AsSurface()) {
|
||||||
|
OnDataPanelUpdated(fileEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Refreshed TablePanel {}", GetIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::InitUI()
|
||||||
|
{
|
||||||
|
m_Surface.setFlags(m_Surface.flags());
|
||||||
|
m_Surface.setFlipHorizontalGrid(false);
|
||||||
|
|
||||||
|
m_p3DXAxis = new QValue3DAxis;
|
||||||
|
m_p3DXAxis->setSegmentCount(10);
|
||||||
|
m_p3DXAxis->setRange(-10, 10);
|
||||||
|
|
||||||
|
m_p3DYAxis = new QValue3DAxis;
|
||||||
|
m_p3DYAxis->setSegmentCount(10);
|
||||||
|
m_p3DYAxis->setRange(-10, 10);
|
||||||
|
|
||||||
|
m_p3DZAxis = new QValue3DAxis;
|
||||||
|
m_p3DZAxis->setSegmentCount(10);
|
||||||
|
m_p3DZAxis->setRange(-10, 10);
|
||||||
|
|
||||||
|
m_Surface.setAxisX(m_p3DXAxis);
|
||||||
|
m_Surface.setAxisY(m_p3DYAxis);
|
||||||
|
m_Surface.setAxisZ(m_p3DZAxis);
|
||||||
|
|
||||||
|
m_Surface.activeTheme()->setType(Q3DTheme::Theme(2));
|
||||||
|
|
||||||
|
m_pSeries = new QSurface3DSeries;
|
||||||
|
m_pSeries->setDrawMode(QSurface3DSeries::DrawSurface);
|
||||||
|
m_Surface.addSeries(m_pSeries);
|
||||||
|
|
||||||
|
QWidget* containerHandle = QWidget::createWindowContainer(&m_Surface);
|
||||||
|
containerHandle->setAutoFillBackground(true);
|
||||||
|
containerHandle->setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||||
|
containerHandle->setAttribute(Qt::WA_NoSystemBackground, false);
|
||||||
|
containerHandle->setUpdatesEnabled(false);
|
||||||
|
|
||||||
|
m_pSeries->setBaseColor(Qt::green);
|
||||||
|
m_pSeries->setColorStyle(Q3DTheme::ColorStyleUniform);
|
||||||
|
m_pSeries->setSingleHighlightColor(Qt::green);
|
||||||
|
|
||||||
|
m_pSeries->setMeshSmooth(false);
|
||||||
|
m_pSeries->setFlatShadingEnabled(false);
|
||||||
|
|
||||||
|
m_Surface.scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPreset(13));
|
||||||
|
|
||||||
|
QHBoxLayout* mainLayout = new QHBoxLayout(this);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
mainLayout->addWidget(containerHandle);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SurfacePanel::GetTypeDisplayName() const
|
||||||
|
{
|
||||||
|
return "Surface";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::OnDataPanelUpdated(FileEntrySurface* fileEntry)
|
||||||
|
{
|
||||||
|
QString strName = fileEntry->GetName();
|
||||||
|
updateTitle(strName);
|
||||||
|
|
||||||
|
FileEntrySurface::ChartProperties propChart = fileEntry->GetChartProperties();
|
||||||
|
|
||||||
|
updateTitleAxis(propChart.xTitle, propChart.yTitle, propChart.zTitle);
|
||||||
|
updateMinMaxX(propChart.xMin, propChart.xMax, propChart.xCount);
|
||||||
|
updateMinMaxY(propChart.yMin, propChart.yMax, propChart.yCount);
|
||||||
|
updateMinMaxZ(propChart.zMin, propChart.zMax, propChart.zCount);
|
||||||
|
|
||||||
|
QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName();
|
||||||
|
FileEntrySurface::SurfaceProperties listCurve = fileEntry->GetSurfaceProperties();
|
||||||
|
updateParseFile(strFile, propChart.timeParam, listCurve);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::OnTimeChanged(double time)
|
||||||
|
{
|
||||||
|
if (m_data.size() > 0)
|
||||||
|
{
|
||||||
|
m_pSeries->dataProxy()->resetArray(nullptr);
|
||||||
|
|
||||||
|
QMap< double, QMap< int, QVector< QVector<QVector3D> > > >::const_iterator ite = m_data.lowerBound(time);
|
||||||
|
if (ite == m_data.end())
|
||||||
|
{
|
||||||
|
ite--;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap< int, QVector< QVector<QVector3D> > > mapData = ite.value();
|
||||||
|
for (QMap< int, QVector< QVector<QVector3D> > >::Iterator it = mapData.begin(); it != mapData.end(); it++)
|
||||||
|
{
|
||||||
|
int nIndex = it.key();
|
||||||
|
QVector< QVector<QVector3D> > listRowData = it.value();
|
||||||
|
|
||||||
|
QSurfaceDataArray* data = new QSurfaceDataArray;
|
||||||
|
|
||||||
|
for (int nI = 0; nI < listRowData.size(); nI++)
|
||||||
|
{
|
||||||
|
QSurfaceDataRow* dataRow = new QSurfaceDataRow;
|
||||||
|
|
||||||
|
QVector<QVector3D> listColData = listRowData[nI];
|
||||||
|
for (int nJ = 0; nJ < listColData.size(); nJ++)
|
||||||
|
{
|
||||||
|
QVector3D v3d = listColData[nJ];
|
||||||
|
*dataRow << v3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data << dataRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pSeries->dataProxy()->resetArray(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Surface.setShadowQuality(QAbstract3DGraph::ShadowQuality::ShadowQualityNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::updateTitle(const QString & title)
|
||||||
|
{
|
||||||
|
if (nullptr != dockWidget_)
|
||||||
|
{
|
||||||
|
dockWidget_->setWindowTitle(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::updateTitleAxis(const QString & xTitle, const QString & yTitle, const QString & zTitle)
|
||||||
|
{
|
||||||
|
m_p3DXAxis->setTitle(xTitle);
|
||||||
|
m_p3DXAxis->setTitleVisible(true);
|
||||||
|
m_p3DYAxis->setTitle(yTitle);
|
||||||
|
m_p3DYAxis->setTitleVisible(true);
|
||||||
|
m_p3DZAxis->setTitle(zTitle);
|
||||||
|
m_p3DZAxis->setTitleVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::updateMinMaxX(float min, float max, int count)
|
||||||
|
{
|
||||||
|
if (max > min)
|
||||||
|
{
|
||||||
|
m_iMinX = min;
|
||||||
|
m_iMaxX = max;
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
m_p3DXAxis->setSegmentCount(count);
|
||||||
|
}
|
||||||
|
m_p3DXAxis->setRange(min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::updateMinMaxY(float min, float max, int count)
|
||||||
|
{
|
||||||
|
if (max > min)
|
||||||
|
{
|
||||||
|
m_iMinY = min;
|
||||||
|
m_iMaxY = max;
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
m_p3DYAxis->setSegmentCount(count);
|
||||||
|
}
|
||||||
|
m_p3DYAxis->setRange(min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::updateMinMaxZ(float min, float max, int count)
|
||||||
|
{
|
||||||
|
if (max > min)
|
||||||
|
{
|
||||||
|
m_iMinZ = min;
|
||||||
|
m_iMaxZ = max;
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
m_p3DZAxis->setSegmentCount(count);
|
||||||
|
}
|
||||||
|
m_p3DZAxis->setRange(min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfacePanel::updateParseFile(const QString & strFile, int nT, FileEntrySurface::SurfaceProperties listCurve)
|
||||||
|
{
|
||||||
|
if (strFile.isEmpty())
|
||||||
|
{
|
||||||
|
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请检查数据文件路径!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(strFile);
|
||||||
|
if (file.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
for (int nI = 0; nI < listCurve.size(); nI++)
|
||||||
|
{
|
||||||
|
FileEntrySurface::SurfaceProperty surface = listCurve.at(nI);
|
||||||
|
|
||||||
|
QLinearGradient gr;
|
||||||
|
gr.setColorAt(0.0, surface.color);
|
||||||
|
gr.setColorAt(0.5, Qt::yellow);
|
||||||
|
gr.setColorAt(0.8, Qt::red);
|
||||||
|
gr.setColorAt(1.0, Qt::darkRed);
|
||||||
|
|
||||||
|
m_pSeries->setBaseGradient(gr);
|
||||||
|
m_pSeries->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
|
||||||
|
//m_pSeries->setSingleHighlightColor(Qt::green);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bResetAxisX = false;
|
||||||
|
if (m_iMaxX == m_iMinX)
|
||||||
|
{
|
||||||
|
bResetAxisX = true;
|
||||||
|
}
|
||||||
|
bool bResetAxisY = false;
|
||||||
|
if (m_iMaxZ == m_iMinZ)
|
||||||
|
{
|
||||||
|
bResetAxisY = true;
|
||||||
|
}
|
||||||
|
bool bResetAxisZ = false;
|
||||||
|
if (m_iMaxY == m_iMinY)
|
||||||
|
{
|
||||||
|
bResetAxisZ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!file.atEnd())
|
||||||
|
{
|
||||||
|
QString strLine = file.readLine().simplified();
|
||||||
|
if (!strLine.isEmpty())
|
||||||
|
{
|
||||||
|
QStringList listLine = strLine.split(" ");
|
||||||
|
double t = listLine.at(nT).toDouble();
|
||||||
|
|
||||||
|
QMap< int, QVector< QVector<QVector3D> > > mapData;
|
||||||
|
for (int nI = 0; nI < listCurve.size(); nI++)
|
||||||
|
{
|
||||||
|
FileEntrySurface::SurfaceProperty surface = listCurve.at(nI);
|
||||||
|
int nStart = surface.start;
|
||||||
|
int nStop = surface.stop;
|
||||||
|
if (nStart == 0)
|
||||||
|
{
|
||||||
|
nStart = 1;
|
||||||
|
}
|
||||||
|
if (nStop == 0)
|
||||||
|
{
|
||||||
|
nStop = listLine.size();
|
||||||
|
}
|
||||||
|
QString strX = surface.x;
|
||||||
|
QString strY = surface.y;
|
||||||
|
QString strZ = surface.z;
|
||||||
|
|
||||||
|
double xInput = 0;
|
||||||
|
double yInput = 0;
|
||||||
|
double zInput = 0.0;
|
||||||
|
QVector< QVector<QVector3D> > listRowData;
|
||||||
|
int nRow = 0;
|
||||||
|
int nCol = 0;
|
||||||
|
for (int nJ = nStart; nJ < nStop; nJ += 3)
|
||||||
|
{
|
||||||
|
int x = listLine.at(nJ).toDouble();
|
||||||
|
int y = listLine.at(nJ + 1).toDouble();
|
||||||
|
double z = listLine.at(nJ + 2).toDouble();
|
||||||
|
|
||||||
|
if (strX == "x")
|
||||||
|
{
|
||||||
|
xInput = x;
|
||||||
|
}
|
||||||
|
else if (strX == "y")
|
||||||
|
{
|
||||||
|
xInput = y;
|
||||||
|
}
|
||||||
|
else if (strX == "z")
|
||||||
|
{
|
||||||
|
xInput = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strY == "x")
|
||||||
|
{
|
||||||
|
yInput = x;
|
||||||
|
}
|
||||||
|
else if (strY == "y")
|
||||||
|
{
|
||||||
|
yInput = y;
|
||||||
|
}
|
||||||
|
else if (strY == "z")
|
||||||
|
{
|
||||||
|
yInput = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strZ == "x")
|
||||||
|
{
|
||||||
|
zInput = x;
|
||||||
|
}
|
||||||
|
else if (strZ == "y")
|
||||||
|
{
|
||||||
|
zInput = y;
|
||||||
|
}
|
||||||
|
else if (strZ == "z")
|
||||||
|
{
|
||||||
|
zInput = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector3D v3d = QVector3D(xInput, yInput, zInput);
|
||||||
|
if (nRow == x)
|
||||||
|
{
|
||||||
|
int nIndex = listRowData.size() - 1;
|
||||||
|
QVector<QVector3D> listColData = listRowData[nIndex];
|
||||||
|
listColData.push_back(v3d);
|
||||||
|
listRowData.replace(nIndex, listColData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QVector<QVector3D> listColData;
|
||||||
|
listColData.push_back(v3d);
|
||||||
|
listRowData.push_back(listColData);
|
||||||
|
}
|
||||||
|
|
||||||
|
nRow = x;
|
||||||
|
nCol = y;
|
||||||
|
}
|
||||||
|
mapData.insert(nI, listRowData);
|
||||||
|
}
|
||||||
|
m_data.insert(t, mapData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_iMaxX == m_iMinX)
|
||||||
|
{
|
||||||
|
m_p3DXAxis->setAutoAdjustRange(true);
|
||||||
|
}
|
||||||
|
if (m_iMaxZ == m_iMinZ)
|
||||||
|
{
|
||||||
|
m_p3DZAxis->setAutoAdjustRange(true);
|
||||||
|
}
|
||||||
|
if (m_iMaxY == m_iMinY)
|
||||||
|
{
|
||||||
|
m_p3DYAxis->setAutoAdjustRange(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Surface.setHorizontalAspectRatio(1.0);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
91
src/ui/Panel/SurfacePanel.h
Normal file
91
src/ui/Panel/SurfacePanel.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DataPanel.h"
|
||||||
|
#include "workspace/FileEntry.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <Q3DSurface>
|
||||||
|
#include <QValue3DAxis>
|
||||||
|
|
||||||
|
using namespace QtDataVisualization;
|
||||||
|
|
||||||
|
class SurfacePanel : public DataPanel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
* @param index Panel index
|
||||||
|
* @param filePath Associated file path
|
||||||
|
* @param parent Parent widget
|
||||||
|
*/
|
||||||
|
explicit SurfacePanel(int index, const QString& filePath, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor with chart data
|
||||||
|
* @param index Panel index
|
||||||
|
* @param chartData Chart data containing curve information
|
||||||
|
* @param parent Parent widget
|
||||||
|
*/
|
||||||
|
explicit SurfacePanel(int index, std::shared_ptr<FileEntrySurface> fileEntry, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
|
virtual ~SurfacePanel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get file type
|
||||||
|
* @return File type (always Curve for this class)
|
||||||
|
*/
|
||||||
|
FileEntryType GetFileType() const override { return FileEntryType::Surface; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Refresh panel content
|
||||||
|
*/
|
||||||
|
void RefreshPanel() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief Initialize UI for curve-specific layout
|
||||||
|
*/
|
||||||
|
virtual void InitUI();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get type display name
|
||||||
|
* @return Display name for curve type
|
||||||
|
*/
|
||||||
|
QString GetTypeDisplayName() const override;
|
||||||
|
|
||||||
|
void OnDataPanelUpdated(FileEntrySurface* fileEntry);
|
||||||
|
|
||||||
|
virtual void OnTimeChanged(double time);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateTitle(const QString& title);
|
||||||
|
void updateTitleAxis(const QString& xTitle, const QString& yTitle, const QString& zTitle);
|
||||||
|
void updateMinMaxX(float min, float max, int count);
|
||||||
|
void updateMinMaxY(float min, float max, int count);
|
||||||
|
void updateMinMaxZ(float min, float max, int count);
|
||||||
|
void updateParseFile(const QString& strFile, int nT, FileEntrySurface::SurfaceProperties listCurve);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q3DSurface m_Surface;
|
||||||
|
|
||||||
|
QSurface3DSeries* m_pSeries;
|
||||||
|
|
||||||
|
QValue3DAxis* m_p3DXAxis;
|
||||||
|
QValue3DAxis* m_p3DYAxis;
|
||||||
|
QValue3DAxis* m_p3DZAxis;
|
||||||
|
|
||||||
|
float m_iMinX = 0;
|
||||||
|
float m_iMaxX = 10;
|
||||||
|
float m_iMinY = 0;
|
||||||
|
float m_iMaxY = 10;
|
||||||
|
float m_iMinZ = 0;
|
||||||
|
float m_iMaxZ = 10;
|
||||||
|
|
||||||
|
QMap< double, QMap< int, QVector< QVector<QVector3D> > > > m_data;
|
||||||
|
};
|
||||||
|
|
||||||
@ -375,7 +375,7 @@ void AddSurfaceFileDlg::accept()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set description
|
// Set description
|
||||||
fileEntry->SetDescription(GetDescription());
|
//fileEntry->SetDescription(GetDescription());
|
||||||
|
|
||||||
// Add to workspace
|
// Add to workspace
|
||||||
WorkSpace* workspace = WorkSpaceManager::Get().GetCurrent();
|
WorkSpace* workspace = WorkSpaceManager::Get().GetCurrent();
|
||||||
|
|||||||
@ -180,12 +180,115 @@ FileEntrySurface* FileEntrySurface::AsSurface() {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileEntrySurface::SetDescription(const QString& description) {
|
bool FileEntrySurface::SaveFiles(tinyxml2::XMLElement * scene, tinyxml2::XMLDocument * doc)
|
||||||
description_ = description;
|
{
|
||||||
|
if (!scene || !doc) {
|
||||||
|
LOG_ERROR("Invalid XML parameters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 <chart> 元素
|
||||||
|
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
|
||||||
|
scene->InsertEndChild(chartElement);
|
||||||
|
|
||||||
|
// 设置chart属性
|
||||||
|
chartElement->SetAttribute("name", name_.toUtf8().constData());
|
||||||
|
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
|
||||||
|
|
||||||
|
chartElement->SetAttribute("xCount", chartProperties_.xCount);
|
||||||
|
chartElement->SetAttribute("yCount", chartProperties_.yCount);
|
||||||
|
chartElement->SetAttribute("zCount", chartProperties_.zCount);
|
||||||
|
chartElement->SetAttribute("xTitle", chartProperties_.xTitle.toUtf8().constData());
|
||||||
|
chartElement->SetAttribute("yTitle", chartProperties_.yTitle.toUtf8().constData());
|
||||||
|
chartElement->SetAttribute("zTitle", chartProperties_.zTitle.toUtf8().constData());
|
||||||
|
chartElement->SetAttribute("xMin", chartProperties_.xMin);
|
||||||
|
chartElement->SetAttribute("xMax", chartProperties_.xMax);
|
||||||
|
chartElement->SetAttribute("yMin", chartProperties_.yMin);
|
||||||
|
chartElement->SetAttribute("yMax", chartProperties_.yMax);
|
||||||
|
chartElement->SetAttribute("zMin", chartProperties_.zMin);
|
||||||
|
chartElement->SetAttribute("zMax", chartProperties_.zMax);
|
||||||
|
chartElement->SetAttribute("t", chartProperties_.timeParam);
|
||||||
|
|
||||||
|
// 为每个CurveProperty创建<curve>元素
|
||||||
|
for (const auto& curve : surfaceProperties_) {
|
||||||
|
tinyxml2::XMLElement* curveElement = doc->NewElement("curve");
|
||||||
|
chartElement->InsertEndChild(curveElement);
|
||||||
|
|
||||||
|
curveElement->SetAttribute("name", curve.name.toUtf8().constData());
|
||||||
|
curveElement->SetAttribute("color", QColorToString(curve.color).toUtf8().constData());
|
||||||
|
curveElement->SetAttribute("start", curve.start);
|
||||||
|
curveElement->SetAttribute("stop", curve.stop);
|
||||||
|
curveElement->SetAttribute("x", curve.x.toUtf8().constData());
|
||||||
|
curveElement->SetAttribute("y", curve.y.toUtf8().constData());
|
||||||
|
curveElement->SetAttribute("z", curve.z.toUtf8().constData());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& FileEntrySurface::GetDescription() const {
|
bool FileEntrySurface::ParseFiles(const tinyxml2::XMLElement * element)
|
||||||
return description_;
|
{
|
||||||
|
if (!element) {
|
||||||
|
LOG_ERROR("Invalid XML element");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析chart属性
|
||||||
|
const char* nameAttr = element->Attribute("name");
|
||||||
|
const char* pathAttr = element->Attribute("path");
|
||||||
|
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
|
||||||
|
if (pathAttr) {
|
||||||
|
QString fullPath = QString::fromUtf8(pathAttr);
|
||||||
|
QFileInfo fileInfo(fullPath);
|
||||||
|
fileName_ = fileInfo.fileName();
|
||||||
|
path_ = fileInfo.absolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
chartProperties_.xCount = element->IntAttribute("xCount", 0);
|
||||||
|
chartProperties_.yCount = element->IntAttribute("yCount", 0);
|
||||||
|
chartProperties_.zCount = element->IntAttribute("zCount", 0);
|
||||||
|
|
||||||
|
const char* xTitleAttr = element->Attribute("xTitle");
|
||||||
|
const char* yTitleAttr = element->Attribute("yTitle");
|
||||||
|
const char* zTitleAttr = element->Attribute("zTitle");
|
||||||
|
if (xTitleAttr) chartProperties_.xTitle = QString::fromUtf8(xTitleAttr);
|
||||||
|
if (yTitleAttr) chartProperties_.yTitle = QString::fromUtf8(yTitleAttr);
|
||||||
|
if (zTitleAttr) chartProperties_.zTitle = QString::fromUtf8(zTitleAttr);
|
||||||
|
|
||||||
|
chartProperties_.xMin = element->DoubleAttribute("xMin", 0.0);
|
||||||
|
chartProperties_.xMax = element->DoubleAttribute("xMax", 0.0);
|
||||||
|
chartProperties_.yMin = element->DoubleAttribute("yMin", 0.0);
|
||||||
|
chartProperties_.yMax = element->DoubleAttribute("yMax", 0.0);
|
||||||
|
chartProperties_.zMin = element->DoubleAttribute("zMin", 0.0);
|
||||||
|
chartProperties_.zMax = element->DoubleAttribute("zMax", 0.0);
|
||||||
|
chartProperties_.timeParam = element->DoubleAttribute("t", 0.0);
|
||||||
|
|
||||||
|
surfaceProperties_.clear();
|
||||||
|
for (const tinyxml2::XMLElement* curveElement = element->FirstChildElement("curve");
|
||||||
|
curveElement != nullptr;
|
||||||
|
curveElement = curveElement->NextSiblingElement("curve")) {
|
||||||
|
|
||||||
|
SurfaceProperty curve;
|
||||||
|
|
||||||
|
const char* curveNameAttr = curveElement->Attribute("name");
|
||||||
|
const char* colorAttr = curveElement->Attribute("color");
|
||||||
|
if (curveNameAttr) curve.name = QString::fromUtf8(curveNameAttr);
|
||||||
|
if (colorAttr) curve.color = StringToQColor(QString::fromUtf8(colorAttr));
|
||||||
|
|
||||||
|
curve.start = curveElement->IntAttribute("start", 0);
|
||||||
|
curve.stop = curveElement->IntAttribute("stop", 0);
|
||||||
|
|
||||||
|
const char* xAttr = curveElement->Attribute("x");
|
||||||
|
const char* yAttr = curveElement->Attribute("y");
|
||||||
|
const char* zAttr = curveElement->Attribute("z");
|
||||||
|
if (xAttr) curve.x = QString::fromUtf8(xAttr);
|
||||||
|
if (yAttr) curve.y = QString::fromUtf8(yAttr);
|
||||||
|
if (zAttr) curve.z = QString::fromUtf8(zAttr);
|
||||||
|
|
||||||
|
surfaceProperties_.append(curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileEntryTable method implementations
|
// FileEntryTable method implementations
|
||||||
@ -290,6 +393,7 @@ bool FileEntryTable::ParseFiles(const tinyxml2::XMLElement * element)
|
|||||||
|
|
||||||
chartProperties_.timeParam = element->DoubleAttribute("t", 0.0);
|
chartProperties_.timeParam = element->DoubleAttribute("t", 0.0);
|
||||||
|
|
||||||
|
tableProperties_.clear();
|
||||||
for (const tinyxml2::XMLElement* curveElement = element->FirstChildElement("curve");
|
for (const tinyxml2::XMLElement* curveElement = element->FirstChildElement("curve");
|
||||||
curveElement != nullptr;
|
curveElement != nullptr;
|
||||||
curveElement = curveElement->NextSiblingElement("curve")) {
|
curveElement = curveElement->NextSiblingElement("curve")) {
|
||||||
|
|||||||
@ -208,14 +208,13 @@ public:
|
|||||||
// Type conversion
|
// Type conversion
|
||||||
FileEntrySurface* AsSurface() override;
|
FileEntrySurface* AsSurface() override;
|
||||||
|
|
||||||
// Description management
|
// XML处理方法
|
||||||
void SetDescription(const QString& description);
|
bool SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) override;
|
||||||
const QString& GetDescription() const;
|
bool ParseFiles(const tinyxml2::XMLElement* element) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ChartProperties chartProperties_;
|
ChartProperties chartProperties_;
|
||||||
SurfaceProperties surfaceProperties_;
|
SurfaceProperties surfaceProperties_;
|
||||||
QString description_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileEntryTable : public FileEntry {
|
class FileEntryTable : public FileEntry {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user