├── .gitignore ├── README.md └── RadarPPI ├── .gitignore ├── RadarPPI.vcxproj ├── RadarPPI.vcxproj.filters ├── RadarPPI.vcxproj.user ├── Resource.qrc ├── Resource ├── background.png ├── dot.png └── scan.png ├── VGRadarPPIViewer.cpp ├── VGRadarPPIViewer.h ├── VGRadarPPIViewer.ui ├── icon.ico ├── icon.rc ├── main.cpp ├── qcustomplot.cpp ├── qcustomplot.h ├── vgradarppi.cpp ├── vgradarppi.h └── 资源 ├── 示例.png ├── 示例2.png ├── 示例3.png ├── 背景图源文件-雷达抽象绿色光圈.zip └── 雷达PPI显示效果3.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RadarPPI 2 | 使用Qt+QCustomPlot实现的动态雷达PPI显示(P显)... 3 | 4 | ## 动态预览效果 5 | ![image](https://github.com/gnibuoz/RadarPPI/blob/main/RadarPPI/%E8%B5%84%E6%BA%90/%E9%9B%B7%E8%BE%BEPPI%E6%98%BE%E7%A4%BA%E6%95%88%E6%9E%9C3.gif) 6 | 7 | ## 预览效果-1 8 | ![image](https://github.com/gnibuoz/RadarPPI/blob/main/RadarPPI/%E8%B5%84%E6%BA%90/%E7%A4%BA%E4%BE%8B.png) 9 | 10 | ## 预览效果-2 11 | ![image](https://github.com/gnibuoz/RadarPPI/blob/main/RadarPPI/%E8%B5%84%E6%BA%90/%E7%A4%BA%E4%BE%8B3.png) 12 | -------------------------------------------------------------------------------- /RadarPPI/.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /RadarPPI/RadarPPI.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | {A6B22D0B-FFE0-4EFE-9723-A77239DB2785} 43 | QtVS_v302 44 | 8.1 45 | $(MSBuildProjectDirectory)\QtMsBuild 46 | 47 | 48 | 49 | Application 50 | v140 51 | MultiByte 52 | 53 | 54 | Application 55 | v140 56 | MultiByte 57 | 58 | 59 | Application 60 | v140 61 | MultiByte 62 | 63 | 64 | Application 65 | v140 66 | MultiByte 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | $(SolutionDir).temp\$(ProjectName)\Link\$(PlatformTarget)\$(Configuration)\ 89 | $(SolutionDir).temp\$(ProjectName)\Compile\$(PlatformTarget)\$(Configuration)\ 90 | $(ProjectName)d 91 | 92 | 93 | $(SolutionDir).temp\$(ProjectName)\Link\$(PlatformTarget)\$(Configuration)\ 94 | $(SolutionDir).temp\$(ProjectName)\Compile\$(PlatformTarget)\$(Configuration)\ 95 | 96 | 97 | $(SolutionDir).temp\$(ProjectName)\Link\$(PlatformTarget)\$(Configuration)\ 98 | $(SolutionDir).temp\$(ProjectName)\Compile\$(PlatformTarget)\$(Configuration)\ 99 | $(ProjectName)d 100 | 101 | 102 | $(SolutionDir).temp\$(ProjectName)\Link\$(PlatformTarget)\$(Configuration)\ 103 | $(SolutionDir).temp\$(ProjectName)\Compile\$(PlatformTarget)\$(Configuration)\ 104 | 105 | 106 | 107 | 108 | 109 | Qt5.12.10(VS2017-x64) 110 | core;gui;widgets;sql 111 | 112 | 113 | msvc2017 114 | core;gui;widgets 115 | 116 | 117 | Qt5.12.10(VS2017-x64) 118 | core;gui;widgets;sql;webenginewidgets;axcontainer 119 | 120 | 121 | msvc2017 122 | core;gui;widgets 123 | 124 | 125 | 126 | 127 | 128 | 129 | true 130 | Disabled 131 | ProgramDatabase 132 | MultiThreadedDebugDLL 133 | true 134 | $(SolutionDir)include;$(SolutionDir)include\$(ProjectName);$(SolutionDir)3rdParty\OSG\include;D:\OSG\osg3.6.5\include;D:\QT\5.12.10\msvc2015_64\include\QtSql;.\;%(AdditionalIncludeDirectories) 135 | 136 | 137 | Console 138 | $(TargetPath) 139 | true 140 | D:\QT\5.12.10\msvc2015_64\lib\cmake\Qt5Sql;D:\OSG\osg3.6.5\lib;$(SolutionDir)lib\$(PlatformTarget)\$(Configuration);$(SolutionDir)lib\$(PlatformTarget);$(SolutionDir)3rdParty\OSG\lib\$(PlatformTarget)\$(Configuration);%(AdditionalLibraryDirectories) 141 | 142 | 143 | echo D | xcopy "$(TargetPath)" "$(SolutionDir)bin_$(PlatformTarget)_$(Configuration)\" /y 144 | 145 | 146 | 147 | 148 | true 149 | Disabled 150 | ProgramDatabase 151 | MultiThreadedDebugDLL 152 | true 153 | $(SolutionDir)include;$(SolutionDir)include\$(ProjectName);$(SolutionDir)3rdParty\OSG\include;.\;%(AdditionalIncludeDirectories) 154 | 155 | 156 | Windows 157 | $(TargetPath) 158 | true 159 | $(SolutionDir)lib\$(PlatformTarget)\$(Configuration);$(SolutionDir)lib\$(PlatformTarget);$(SolutionDir)3rdParty\OSG\lib\$(PlatformTarget)\$(Configuration);%(AdditionalLibraryDirectories) 160 | 161 | 162 | echo D | xcopy "$(TargetPath)" "$(SolutionDir)bin_$(PlatformTarget)_$(Configuration)\" /y 163 | 164 | 165 | 166 | 167 | true 168 | ProgramDatabase 169 | MultiThreadedDLL 170 | true 171 | D:\github\src\VGScenarioEditorV2.0\include;$(VG_DEV_LIBS)\OSG\include;$(SolutionDir)include;$(SolutionDir)include\$(ProjectName);$(VG_DEV_LIBS)\grpc\include;$(VG_DEV_LIBS)\OSG\include;$(VG_DEV_LIBS)\GDAL\include;$(VG_DEV_LIBS)\boost\include;$(VG_DEV_LIBS)\python3\include\python3.9;$(SolutionDir)include/util;$(SolutionDir)include/common;$(SolutionDir)include/sim;$(SolutionDir)include/database;$(SolutionDir)include/ai;$(SolutionDir)include/scriptinterface;$(SolutionDir)include;$(SolutionDir)WarfareRPC;.\;%(AdditionalIncludeDirectories) 172 | UNICODE;_UNICODE;WIN32;%(PreprocessorDefinitions) 173 | Disabled 174 | 175 | 176 | 177 | 178 | Console 179 | $(TargetPath) 180 | Debug 181 | D:\github\src\VGScenarioEditorV2.0\lib\x64;$(VG_DEV_LIBS)\OSG\lib\$(PlatformTarget)\$(Configuration);$(SolutionDir)lib\$(PlatformTarget)\$(Configuration);$(SolutionDir)lib\$(PlatformTarget);$(VG_DEV_LIBS)\python3\lib;$(VG_DEV_LIBS)\boost\lib;$(VG_DEV_LIBS)\GDAL\lib\$(PlatformTarget)\;$(VG_DEV_LIBS)\grpc\lib\$(PlatformTarget)\;%(AdditionalLibraryDirectories) 182 | %(AdditionalDependencies) 183 | 184 | 185 | echo D | xcopy "$(TargetPath)" "$(SolutionDir)bin_$(PlatformTarget)_$(Configuration)\" /y 186 | 187 | 188 | 189 | 190 | true 191 | 192 | 193 | MultiThreadedDLL 194 | true 195 | $(SolutionDir)include;$(SolutionDir)include\$(ProjectName);$(SolutionDir)3rdParty\OSG\include;.\;%(AdditionalIncludeDirectories) 196 | 197 | 198 | Windows 199 | $(TargetPath) 200 | false 201 | $(SolutionDir)lib\$(PlatformTarget)\$(Configuration);$(SolutionDir)lib\$(PlatformTarget);$(SolutionDir)3rdParty\OSG\lib\$(PlatformTarget)\$(Configuration);%(AdditionalLibraryDirectories) 202 | 203 | 204 | echo D | xcopy "$(TargetPath)" "$(SolutionDir)bin_$(PlatformTarget)_$(Configuration)\" /y 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /RadarPPI/RadarPPI.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} 14 | qrc;* 15 | false 16 | 17 | 18 | {99349809-55BA-4b9d-BF79-8FDBB0286EB3} 19 | ui 20 | 21 | 22 | {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} 23 | qrc;* 24 | false 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | Source Files 42 | 43 | 44 | 45 | 46 | Resource Files 47 | 48 | 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | -------------------------------------------------------------------------------- /RadarPPI/RadarPPI.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)bin_$(PlatformTarget)_$(Configuration)\$(TargetFileName) 5 | $(SolutionDir)bin_$(PlatformTarget)_$(Configuration) 6 | WindowsLocalDebugger 7 | 8 | 9 | $(SolutionDir)bin_$(PlatformTarget)_$(Configuration)\$(TargetFileName) 10 | $(SolutionDir)bin_$(PlatformTarget)_$(Configuration) 11 | WindowsLocalDebugger 12 | PATH=%PATH%;D:/OSG/osg3.6.5/bin_x64_Debug;$(QtDllPath) $(LocalDebuggerEnvironment) 13 | 14 | 15 | $(SolutionDir)bin_$(PlatformTarget)_$(Configuration)\$(TargetFileName) 16 | $(SolutionDir)bin_$(PlatformTarget)_$(Configuration) 17 | WindowsLocalDebugger 18 | 19 | 20 | $(SolutionDir)bin_$(PlatformTarget)_$(Configuration)\$(TargetFileName) 21 | $(SolutionDir)bin_$(PlatformTarget)_$(Configuration) 22 | WindowsLocalDebugger 23 | PATH=$(VG_DEV_LIBS)bin_x64_Release%3b%PATH% $(LocalDebuggerEnvironment) 24 | 25 | 26 | 2022-11-21T04:17:32.5770636Z 27 | 28 | 29 | 2022-11-21T02:18:11.9319895Z 30 | 31 | -------------------------------------------------------------------------------- /RadarPPI/Resource.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | Resource/background.png 4 | Resource/dot.png 5 | Resource/scan.png 6 | 7 | 8 | -------------------------------------------------------------------------------- /RadarPPI/Resource/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/Resource/background.png -------------------------------------------------------------------------------- /RadarPPI/Resource/dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/Resource/dot.png -------------------------------------------------------------------------------- /RadarPPI/Resource/scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/Resource/scan.png -------------------------------------------------------------------------------- /RadarPPI/VGRadarPPIViewer.cpp: -------------------------------------------------------------------------------- 1 | #include "VGRadarPPIViewer.h" 2 | #include "ui_VGRadarPPIViewer.h" 3 | 4 | #include "QTime" 5 | #include "QTimer" 6 | #include "QFileDialog" 7 | 8 | #include "QFile" 9 | #include "QTextStream" 10 | 11 | namespace RadarPPI { 12 | 13 | FrameDataVector loadPPIData(const QString& path) 14 | { 15 | FrameDataVector frames; 16 | 17 | QFile file(path); 18 | if (!file.open(QIODevice::ReadOnly | QFile::Text)) return frames; 19 | 20 | QTextStream s(&file); 21 | while (!s.atEnd()) 22 | { 23 | auto values = s.readLine().simplified().trimmed().split(" ", QString::SkipEmptyParts); 24 | if (values.empty()) continue; 25 | 26 | Targets targets; 27 | auto n = values.size() / 2; 28 | for (auto i = 0; i < n; ++i) 29 | { 30 | auto r = values[i * 2].toDouble(); 31 | auto t = values[i * 2 + 1].toDouble() * 3.1415926 / 180.0; 32 | 33 | if (r >= 0.0) 34 | { 35 | targets.push_back(Target{ r * cos(t), r * sin(t) }); 36 | } 37 | } 38 | 39 | frames.push_back(targets); 40 | } 41 | 42 | file.close(); 43 | return frames; 44 | } 45 | }; 46 | 47 | 48 | VGRadarPPIViewer::VGRadarPPIViewer(QWidget *parent) 49 | : QWidget(parent) 50 | { 51 | ui = new Ui::VGRadarPPIViewer(); 52 | ui->setupUi(this); 53 | 54 | ui->widget->setColor(QColor("#00ffb2")); 55 | 56 | qsrand(QTime::currentTime().msecsSinceStartOfDay()); 57 | auto timer = new QTimer(this); 58 | connect(timer, &QTimer::timeout, [&, this]() { 59 | if (_data.empty()) 60 | { 61 | static int counter = 0; 62 | 63 | //if (counter++ % 2 == 0) 64 | //{ 65 | // static int idx = 0; 66 | static QVector clrs{ QColor("#ff6666") ,QColor("#2aff36"), QColor("#ddff21"),QColor("#ffa621"),QColor("#0061ff"),QColor("#00ffb2") }; 67 | // ui->widget->setColor(clrs[idx++ % clrs.size()]); // ²âÊÔÑÕÉ«±ä»¯ 68 | //} 69 | 70 | const auto range = ui->doubleSpinBoxRange->value() * 1000.0; 71 | 72 | QVector x, y; 73 | for (int i = 0; i < qrand() % 30; i += 1) 74 | { 75 | x.push_back(((qrand() % 2000 - 1000) / 1000.0) * range * 0.7); 76 | y.push_back(((qrand() % 2000 - 1000) / 1000.0) * range * 0.7); 77 | } 78 | ui->widget->addData(x, y); 79 | } 80 | else 81 | { 82 | _idx++; 83 | _idx %= _data.size(); 84 | 85 | auto dd = _data[_idx]; 86 | 87 | QVector x, y; 88 | for (auto& d : dd) 89 | { 90 | x.push_back(d.x()); 91 | y.push_back(d.y()); 92 | } 93 | ui->widget->addData(x, y); 94 | } 95 | }); 96 | timer->start(1000); 97 | 98 | connect(ui->pushButton, &QPushButton::clicked, [=]() { 99 | auto path = QFileDialog::getOpenFileName(this, "PPI Data", " "); 100 | 101 | if (path.isEmpty()) return; 102 | 103 | _data = RadarPPI::loadPPIData(path); 104 | _idx = 0u; 105 | 106 | if (!_data.empty()) 107 | { 108 | ui->widget->setData({}, {}); 109 | } 110 | }); 111 | 112 | auto handler = [=]() { 113 | ui->widget->setRange(ui->doubleSpinBoxRange->value() * 1000.0); 114 | ui->widget->setSpeed(360.0 / ui->doubleSpinBoxT->value()); 115 | }; 116 | 117 | connect(ui->doubleSpinBoxRange, QOverload::of(&QDoubleSpinBox::valueChanged), handler); 118 | connect(ui->doubleSpinBoxT, QOverload::of(&QDoubleSpinBox::valueChanged), handler); 119 | 120 | connect(ui->doubleSpinBoxTheta, QOverload::of(&QDoubleSpinBox::valueChanged), [=]() { 121 | ui->widget->stop(); 122 | ui->widget->setData({}, {}); 123 | ui->widget->setTheta(-ui->doubleSpinBoxTheta->value() + 90.0); 124 | ui->widget->start(); 125 | }); 126 | 127 | QTimer::singleShot(1000, handler); 128 | } 129 | 130 | VGRadarPPIViewer::~VGRadarPPIViewer() 131 | { 132 | delete ui; 133 | } -------------------------------------------------------------------------------- /RadarPPI/VGRadarPPIViewer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | namespace Ui { class VGRadarPPIViewer; }; 5 | 6 | #include "QPointF" 7 | #include "QVector" 8 | 9 | using Target = QPointF; // 目标点 10 | using Targets = QVector; // 目标列表 11 | using FrameDataVector = QVector; // 所有时刻数据 12 | 13 | class VGRadarPPIViewer : public QWidget 14 | { 15 | Q_OBJECT 16 | public: 17 | VGRadarPPIViewer(QWidget *parent = Q_NULLPTR); 18 | ~VGRadarPPIViewer(); 19 | 20 | private: 21 | Ui::VGRadarPPIViewer *ui; 22 | 23 | FrameDataVector _data; 24 | unsigned _idx{ 0u }; 25 | }; -------------------------------------------------------------------------------- /RadarPPI/VGRadarPPIViewer.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | VGRadarPPIViewer 4 | 5 | 6 | 7 | 0 8 | 0 9 | 562 10 | 528 11 | 12 | 13 | 14 | VGRadarPPIViewer 15 | 16 | 17 | 18 | 2 19 | 20 | 21 | 2 22 | 23 | 24 | 2 25 | 26 | 27 | 2 28 | 29 | 30 | 2 31 | 32 | 33 | 34 | 35 | 36 | 37 | 加载数据 38 | 39 | 40 | 41 | 42 | 43 | 44 | 范围 45 | 46 | 47 | 48 | 49 | 50 | 51 | 公里 52 | 53 | 54 | 0 55 | 56 | 57 | 1.000000000000000 58 | 59 | 60 | 99999999.000000000000000 61 | 62 | 63 | 100.000000000000000 64 | 65 | 66 | 67 | 68 | 69 | 70 | 扫描周期 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 0.010000000000000 81 | 82 | 83 | 999999.000000000000000 84 | 85 | 86 | 60.000000000000000 87 | 88 | 89 | 90 | 91 | 92 | 93 | 初始方位 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 0.000000000000000 104 | 105 | 106 | 360.000000000000000 107 | 108 | 109 | 0.000000000000000 110 | 111 | 112 | 113 | 114 | 115 | 116 | Qt::Horizontal 117 | 118 | 119 | 120 | 40 121 | 20 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | VGRadarPPI 137 | QWidget 138 |
vgradarppi.h
139 | 1 140 |
141 |
142 | 143 | 144 |
145 | -------------------------------------------------------------------------------- /RadarPPI/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/icon.ico -------------------------------------------------------------------------------- /RadarPPI/icon.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "icon.ico" 2 | 3 | -------------------------------------------------------------------------------- /RadarPPI/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "VGRadarPPIViewer.h" 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QApplication a(argc, argv); 7 | 8 | VGRadarPPIViewer p; 9 | p.setWindowTitle(QString::fromLocal8Bit("雷达PPI显示效果")); 10 | p.show(); 11 | 12 | return a.exec(); 13 | } -------------------------------------------------------------------------------- /RadarPPI/vgradarppi.cpp: -------------------------------------------------------------------------------- 1 | #include "vgradarppi.h" 2 | #include "QPainter" 3 | #include "QEvent" 4 | 5 | struct VGRadarPPIPrivate 6 | { 7 | VGRadarPPIPrivate() 8 | { 9 | dot = QPixmap(":/Resource/dot.png").scaledToWidth(12, Qt::SmoothTransformation); 10 | } 11 | 12 | inline QPixmap convertToColor(const QPixmap& background, const QColor& color) 13 | { 14 | auto b = background.toImage(); 15 | auto ba = b.alphaChannel(); 16 | b.fill(color); 17 | b.setAlphaChannel(ba); 18 | return QPixmap::fromImage(b); 19 | } 20 | 21 | inline void setColor(const QColor& color) 22 | { 23 | background = convertToColor(background, color); 24 | scan = convertToColor(scan, color); 25 | dot = convertToColor(dot, color); 26 | } 27 | 28 | QCPGraph* graph{ nullptr }; 29 | qreal speed{ 6.0 }; // 扫描角速度,默认120°/s 30 | qreal range_m{ 10000.0 }; // 范围 31 | 32 | QPixmap background{ ":/Resource/background.png" }; 33 | QPixmap scan{ ":/Resource/scan.png" }; 34 | QPixmap dot; 35 | 36 | qreal angle{ 90.0 }; 37 | QElapsedTimer timer; 38 | 39 | qint32 timerID{ -1 }; 40 | }; 41 | 42 | VGRadarPPI::VGRadarPPI(QWidget *parent) 43 | : QCustomPlot(parent) 44 | , _(new VGRadarPPIPrivate) 45 | { 46 | resize(600, 600); 47 | 48 | setBackground(_->background); //设置背景为透明色 49 | 50 | setBackgroundScaledMode(Qt::IgnoreAspectRatio); 51 | 52 | setBackground(QColor(0, 0, 0, 255)); //设置默认背景为黑色 53 | 54 | _->graph = addGraph(); 55 | _->graph->setLineStyle(QCPGraph::lsNone); 56 | 57 | QCPScatterStyle style(QCPScatterStyle::ssPixmap, 1.0); 58 | style.setPixmap(QPixmap(":/Resource/dot.png").scaledToWidth(8, Qt::SmoothTransformation)); 59 | _->graph->setScatterStyle(style); 60 | 61 | xAxis2->setVisible(false); // 顶部坐标轴 62 | xAxis->setVisible(false); // 底部坐标轴 63 | yAxis->setVisible(false); // 左边坐标轴 64 | yAxis2->setVisible(false); // 右边坐标轴 65 | 66 | setRange(10e3); // 10km 67 | 68 | start(); 69 | } 70 | 71 | VGRadarPPI::~VGRadarPPI() 72 | { 73 | delete _; 74 | _ = Q_NULLPTR; 75 | } 76 | 77 | void VGRadarPPI::setData(const DataVector& x, const DataVector& y) 78 | { 79 | Q_ASSERT(x.size() == y.size()); 80 | 81 | DataVector xx, yy; 82 | for (auto i = 0; i < x.size(); ++i) 83 | { 84 | auto r = sqrt(x[i] * x[i] + y[i] * y[i]); 85 | if (r > _->range_m * 0.8) 86 | continue; 87 | 88 | xx.push_back(x[i]); 89 | yy.push_back(y[i]); 90 | } 91 | 92 | _->graph->setData(xx, yy); 93 | replot(QCustomPlot::rpQueuedReplot); 94 | } 95 | 96 | void VGRadarPPI::addData(const DataVector& x, const DataVector& y) 97 | { 98 | Q_ASSERT(x.size() == y.size()); 99 | 100 | DataVector xx, yy; 101 | for (auto i = 0; i < x.size(); ++i) 102 | { 103 | auto r = sqrt(x[i] * x[i] + y[i] * y[i]); 104 | if (r > _->range_m * 0.8) 105 | continue; 106 | 107 | xx.push_back(x[i]); 108 | yy.push_back(y[i]); 109 | } 110 | _->graph->addData(xx, yy); 111 | replot(QCustomPlot::rpQueuedReplot); 112 | } 113 | 114 | void VGRadarPPI::setRange(qreal range_m) 115 | { 116 | _->range_m = range_m; 117 | xAxis->setRange(-range_m, range_m); 118 | yAxis->setRange(-range_m, range_m); 119 | replot(QCustomPlot::rpQueuedReplot); 120 | } 121 | 122 | void VGRadarPPI::setTheta(qreal theta) 123 | { 124 | _->angle = theta; 125 | } 126 | 127 | void VGRadarPPI::setSpeed(qreal speed_deg_s) 128 | { 129 | _->speed = speed_deg_s; 130 | } 131 | 132 | void VGRadarPPI::start() 133 | { 134 | if (_->timerID == -1) 135 | { 136 | _->timerID = startTimer(20); 137 | _->timer.restart(); 138 | } 139 | } 140 | 141 | void VGRadarPPI::pause() 142 | { 143 | if (_->timerID == -1)return; 144 | 145 | killTimer(_->timerID); 146 | _->timerID = -1; 147 | } 148 | 149 | void VGRadarPPI::stop() 150 | { 151 | if (_->timerID == -1)return; 152 | 153 | killTimer(_->timerID); 154 | _->timerID = -1; 155 | 156 | _->angle = -90.0; 157 | } 158 | 159 | void VGRadarPPI::setColor(const QColor& color) 160 | { 161 | _->setColor(color); 162 | 163 | setBackground(_->background); //设置背景为透明色 164 | 165 | QCPScatterStyle style(QCPScatterStyle::ssPixmap, 1.0); 166 | style.setPixmap(_->dot); 167 | _->graph->setScatterStyle(style); 168 | 169 | repaint(); 170 | replot(); 171 | } 172 | 173 | qreal VGRadarPPI::getRange() const 174 | { 175 | return _->range_m; 176 | } 177 | 178 | qreal VGRadarPPI::getSpeed() const 179 | { 180 | return _->speed; 181 | } 182 | 183 | void VGRadarPPI::paintEvent(QPaintEvent *event) 184 | { 185 | QCustomPlot::paintEvent(event); 186 | 187 | QPainter p(this); 188 | p.translate(width() / 2, height() / 2); 189 | p.rotate(_->angle); 190 | p.drawPixmap(-width() / 2, -height() / 2, width(), height(), _->scan); 191 | 192 | _->angle -= _->speed * _->timer.elapsed() / 1000.0; 193 | 194 | _->timer.restart(); 195 | } 196 | 197 | void VGRadarPPI::timerEvent(QTimerEvent *event) 198 | { 199 | repaint(); 200 | } -------------------------------------------------------------------------------- /RadarPPI/vgradarppi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "QCustomPlot.h" 4 | 5 | struct VGRadarPPIPrivate; 6 | 7 | /** 8 | * 雷达PPI显示 9 | */ 10 | class VGRadarPPI : public QCustomPlot 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | using DataVector = QVector; 16 | 17 | VGRadarPPI(QWidget *parent = Q_NULLPTR); 18 | 19 | ~VGRadarPPI(); 20 | 21 | /** 22 | * 替换更新数据,直角坐标 23 | */ 24 | void setData(const DataVector& x, const DataVector& y); 25 | 26 | /** 27 | * 追加更新数据,直角坐标 28 | */ 29 | void addData(const DataVector& x, const DataVector& y); 30 | 31 | /** 32 | * 设置颜色 33 | */ 34 | void setColor(const QColor& color); 35 | 36 | /** 37 | * 查询P显范围(m) 38 | */ 39 | qreal getRange() const; 40 | 41 | /** 42 | * 查询P显扫描角速度(°/s) 43 | */ 44 | qreal getSpeed() const; 45 | 46 | public Q_SLOTS: 47 | /** 48 | * 设置P显范围(m) 49 | */ 50 | void setRange(qreal range_m); 51 | 52 | /** 53 | * 设置P显当前扫描角度 54 | */ 55 | void setTheta(qreal theta); 56 | 57 | /** 58 | * 设置扫描角速度(°/s) 59 | */ 60 | void setSpeed(qreal speed_deg_s); 61 | 62 | /** 63 | * 开始扫描 64 | */ 65 | void start(); 66 | 67 | /** 68 | * 暂停扫描 69 | */ 70 | void pause(); 71 | 72 | /** 73 | * 停止扫描 74 | */ 75 | void stop(); 76 | 77 | protected: 78 | void paintEvent(QPaintEvent *event) override; 79 | 80 | void timerEvent(QTimerEvent *event) override; 81 | 82 | private: 83 | VGRadarPPIPrivate *_{ Q_NULLPTR }; 84 | }; -------------------------------------------------------------------------------- /RadarPPI/资源/示例.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/资源/示例.png -------------------------------------------------------------------------------- /RadarPPI/资源/示例2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/资源/示例2.png -------------------------------------------------------------------------------- /RadarPPI/资源/示例3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/资源/示例3.png -------------------------------------------------------------------------------- /RadarPPI/资源/背景图源文件-雷达抽象绿色光圈.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/资源/背景图源文件-雷达抽象绿色光圈.zip -------------------------------------------------------------------------------- /RadarPPI/资源/雷达PPI显示效果3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnibuoz/RadarPPI/ccc5ce4c888aff7d6d705bf8a9abb55a8b8b597f/RadarPPI/资源/雷达PPI显示效果3.gif --------------------------------------------------------------------------------