VTK Chart坐标轴

本文介绍使用VTK库创建2D图表的过程。通过设置背景颜色、窗口尺寸等参数,并利用vtkChartXY类添加散点图,展示了如何绘制包含余弦、正弦及其组合的数据点。文中还详细介绍了如何为不同数据集配置颜色、宽度和标记样式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vtk绘制出来到坐标轴着实挺清秀的:

#include "mainwindow.h"
#include "QApplication"

#include "vtkAutoInit.h"
#if  VTK_MAJOR_VERSION >=7
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
VTK_MODULE_INIT(vtkRenderingContextOpenGL2)
#endif

#include "vtkVersion.h"
#include "vtkSmartPointer.h"
#include "vtkChartXY.h"
#include "vtkContextScene.h"
#include "vtkContextView.h"
#include "vtkFloatArray.h"
#include "vtkPlotPoints.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkTable.h"


int main(int argc, char *argv[])
{
    // Set up a 2D scene, add an XY chart to it
     vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New();
     view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
     view->GetRenderWindow()->SetSize(400, 300);
     vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
     view->GetScene()->AddItem(chart);
     chart->SetShowLegend(true);

     // Create a table with some points in it...
     vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();

     vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
     arrX->SetName("X Axis");
     table->AddColumn(arrX);

     vtkSmartPointer<vtkFloatArray> arrC = vtkSmartPointer<vtkFloatArray>::New();
     arrC->SetName("Cosine");
     table->AddColumn(arrC);

     vtkSmartPointer<vtkFloatArray> arrS = vtkSmartPointer<vtkFloatArray>::New();
     arrS->SetName("Sine");
     table->AddColumn(arrS);

     vtkSmartPointer<vtkFloatArray> arrT = vtkSmartPointer<vtkFloatArray>::New();
     arrT->SetName("Sine - Cosine");
     table->AddColumn(arrT);

    // Test charting with a few more points...
    int numPoints = 40;
    float inc = 7.5 / (numPoints-1);
    table->SetNumberOfRows(numPoints);
    for (int i = 0; i < numPoints; ++i)
    {
       table->SetValue(i, 0, i * inc);
       table->SetValue(i, 1, cos(i * inc) + 0.0);
       table->SetValue(i, 2, sin(i * inc) + 0.0);
       table->SetValue(i, 3, sin(i * inc) - cos(i * inc));
    }
     // Add multiple scatter plots, setting the colors etc
     vtkPlot *points = chart->AddPlot(vtkChart::POINTS);
   #if VTK_MAJOR_VERSION <= 5
     points->SetInput(table, 0, 1);
   #else
     points->SetInputData(table, 0, 1);
   #endif
     points->SetColor(0, 0, 0, 255);
     points->SetWidth(1.0);
     vtkPlotPoints::SafeDownCast(points)->SetMarkerStyle(vtkPlotPoints::CROSS);
     points = chart->AddPlot(vtkChart::POINTS);
   #if VTK_MAJOR_VERSION <= 5
     points->SetInput(table, 0, 2);
   #else
     points->SetInputData(table, 0, 2);
   #endif
     points->SetColor(0, 0, 0, 255);
     points->SetWidth(1.0);
     vtkPlotPoints::SafeDownCast(points)->SetMarkerStyle(vtkPlotPoints::PLUS);
     points = chart->AddPlot(vtkChart::POINTS);
   #if VTK_MAJOR_VERSION <= 5
     points->SetInput(table, 0, 3);
   #else
     points->SetInputData(table, 0, 3);
   #endif
     points->SetColor(0, 0, 255, 255);
     points->SetWidth(1.0);
     vtkPlotPoints::SafeDownCast(points)->SetMarkerStyle(vtkPlotPoints::CIRCLE);
     // finally render the scene
     view->GetRenderWindow()->SetMultiSamples(0);
     view->GetInteractor()->Initialize();
     view->GetInteractor()->Start();
     return EXIT_SUCCESS;
}

sleep;gnome-screenshot截图:
这里写图片描述

<think>好的,我现在需要帮助用户解决在Qt 5.14.2中实现三轴飞行轨迹动态显示的问题。用户的需求包括坐标系、刻度、CSV数据导入、缩放、鼠标交互显示坐标与时间、动态播放和完整代码。我得一步步分析这些需求,并思考如何实现。 首先,用户提到要使用Qt 5.14.2,所以需要确保所用的库和模块在该版本中可用。Qt的版本兼容性很重要,比如Qt Charts模块在5.14中应该是可用的,但需要确认用户是否正确安装了该模块,并在项目配置中启用了它。 接下来是CSV数据导入。Qt中处理CSV文件通常使用QFile和QTextStream来逐行读取数据。用户的数据可能包含时间戳和三个轴的坐标,每行可能有四个数据点:时间、x、y、z。需要解析这些数据并存储到适当的数据结构中,比如QVector或QList。需要注意的是CSV的格式是否正确,是否有标题行,分隔符是否为逗号等。 然后是坐标系和刻度的显示。Qt Charts中的QChart、QValueAxis和QScatterSeries或QSplineSeries可能适用。三轴需要三个坐标轴,但Qt Charts默认是二维的,所以可能需要分别处理三个二维图表,或者使用3D图表模块。不过,Qt Data Visualization模块可能需要额外的安装,并且可能在5.14版本中可用性有限。用户的需求是三轴显示,可能需要使用三个不同的二维图表,分别显示XY、XZ、YZ平面,或者使用一个三维视图。但考虑到用户可能需要一个三维坐标系,而Qt Charts本身不支持3D,可能需要采用其他方法,比如使用QOpenGLWidget进行自定义绘制,或者使用第三方库如VTK。但用户可能希望用Qt自带的组件,所以可能需要用三个2D图表来模拟三轴显示,或者将三个轴组合在一个图表中,比如使用不同的颜色和轴标签。 缩放功能可以通过QChartView的setRubberBand(QChartView::RectangleRubberBand)来实现矩形缩放,同时支持鼠标滚轮缩放。需要处理鼠标事件来调整视图的缩放比例。 鼠标交互显示坐标和时间,这需要重写QChartView的鼠标移动事件,获取鼠标位置对应的图表坐标,然后显示在状态栏或自定义的标签上。同时,当鼠标悬停在数据点上时,可能需要显示具体的数据值和时间,这可以通过QToolTip或自定义的提示框实现。 动态播放和回放需要控制数据点的显示进度。可以使用定时器QTimer来逐步添加数据点到series中,形成动画效果。回放功能可能需要重置数据,并重新开始定时器。 关于代码结构,可能需要创建一个主窗口,包含菜单栏(导入CSV)、图表视图、控制按钮(播放、暂停、重置)。数据处理部分需要将CSV内容读取并存储到数据结构中,然后在定时器的槽函数中逐步将数据添加到series中。 注释方面,需要详细说明每个部分的功能,特别是数据解析、图表配置、事件处理和动画逻辑。确保代码的可读性和可维护性。 可能的挑战包括三维坐标的显示,因为Qt Charts是二维的。可能需要使用三个不同的图表分别显示不同平面,或者采用伪3D效果。此外,动态播放时数据更新的性能也需要考虑,避免界面卡顿。 最后,需要提供完整的可编译代码,包括.pro文件的配置,确保用户正确链接Qt Charts模块,例如在.pro中添加QT += charts。同时,处理不同平台下的兼容性问题,比如文件路径和分隔符。 总结下来,步骤大致如下: 1. 创建主窗口,布局图表视图和控制组件。 2. 实现CSV数据导入功能,解析数据到结构体或列表。 3. 配置三个坐标轴,设置图表属性。 4. 实现缩放和鼠标交互显示坐标。 5. 使用定时器控制动态播放和回放。 6. 编写详细的注释和测试代码。</think>以下是基于Qt 5.14.2实现三轴飞行轨迹动态显示应用的完整解决方案(使用C++和Qt Charts模块): ```cpp // mainwindow.h #include <QMainWindow> #include <QtCharts> struct FlightData { qreal time; qreal x; qreal y; qreal z; }; QT_CHARTS_USE_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void loadCSV(); void updatePlot(); void showPointTooltip(const QPointF &pos, bool state); private: void setupChart(); void setupAxes(); void setupUI(); QChart *chart; QScatterSeries *series; QList<FlightData> flightData; QTimer *animationTimer; int currentIndex = 0; QChartView *chartView; QStatusBar *statusBar; }; ``` ```cpp // mainwindow.cpp #include "mainwindow.h" #include <QFileDialog> #include <QTextStream> #include <QValueAxis> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setupChart(); setupUI(); setupAxes(); animationTimer = new QTimer(this); connect(animationTimer, &QTimer::timeout, this, &MainWindow::updatePlot); } void MainWindow::setupChart() { chart = new QChart(); series = new QScatterSeries(); series->setMarkerSize(8.0); chart->addSeries(series); chart->setAnimationOptions(QChart::AllAnimations); } void MainWindow::setupAxes() { // 创建三维坐标轴(使用三个二维轴组合) QValueAxis *axisX = new QValueAxis(); QValueAxis *axisY = new QValueAxis(); QValueAxis *axisZ = new QValueAxis(); axisX->setTitleText("X Axis"); axisY->setTitleText("Y Axis"); axisZ->setTitleText("Z Axis"); chart->addAxis(axisX, Qt::AlignBottom); chart->addAxis(axisY, Qt::AlignLeft); // Z轴使用右侧轴显示高度信息 chart->addAxis(axisZ, Qt::AlignRight); series->attachAxis(axisX); series->attachAxis(axisY); } void MainWindow::setupUI() { chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); chartView->setRubberBand(QChartView::RectangleRubberBand); // 矩形缩放 setCentralWidget(chartView); // 创建菜单栏 QMenu *fileMenu = menuBar()->addMenu("File"); QAction *openAction = fileMenu->addAction("Open CSV"); connect(openAction, &QAction::triggered, this, &MainWindow::loadCSV); // 鼠标移动事件处理 connect(series, &QScatterSeries::hovered, this, &MainWindow::showPointTooltip); } void MainWindow::loadCSV() { QString fileName = QFileDialog::getOpenFileName(this, "Open CSV", "", "CSV Files (*.csv)"); if (fileName.isEmpty()) return; QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) return; flightData.clear(); QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); QStringList fields = line.split(','); if (fields.size() == 4) { FlightData data; data.time = fields[0].toDouble(); data.x = fields[1].toDouble(); data.y = fields[2].toDouble(); data.z = fields[3].toDouble(); flightData.append(data); } } file.close(); // 自动设置坐标范围 QValueAxis *axisX = qobject_cast<QValueAxis*>(chart->axisX()); QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axisY()); QValueAxis *axisZ = qobject_cast<QValueAxis*>(chart->axisZ()); auto minmax = [](const QList<FlightData>& data, auto accessor) { auto pair = std::minmax_element(data.begin(), data.end(), [accessor](const FlightData& a, const FlightData& b) { return accessor(a) < accessor(b); }); return qMakePair(accessor(*pair.first), accessor(*pair.second)); }; axisX->setRange(minmax(flightData, [](auto d){ return d.x; })); axisY->setRange(minmax(flightData, [](auto d){ return d.y; })); axisZ->setRange(minmax(flightData, [](auto d){ return d.z; })); animationTimer->start(50); // 20 FPS } void MainWindow::updatePlot() { if (currentIndex < flightData.size()) { const auto &data = flightData[currentIndex]; series->append(data.x, data.y); currentIndex++; } else { animationTimer->stop(); } } void MainWindow::showPointTooltip(const QPointF &pos, bool state) { if (state) { // 查找最近的数据点 auto it = std::min_element(flightData.begin(), flightData.end(), [pos](const FlightData& a, const FlightData& b) { return qHypot(a.x - pos.x(), a.y - pos.y()) < qHypot(b.x - pos.x(), b.y - pos.y()); }); int index = std::distance(flightData.begin(), it); QString tooltip = QString("Time: %1s\nX: %2\nY: %3\nZ: %4") .arg(flightData[index].time) .arg(flightData[index].x) .arg(flightData[index].y) .arg(flightData[index].z); QToolTip::showText(QCursor::pos(), tooltip); } else { QToolTip::hideText(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值