274 lines
8.3 KiB
C++
274 lines
8.3 KiB
C++
//
|
|
// Created by wuxiaxin on 24-7-9.
|
|
//
|
|
|
|
// You may need to build the project (run Qt uic code generator) to get "ui_wavemodel.h" resolved
|
|
|
|
#include "wavemodel.h"
|
|
#include "ui_wavemodel.h"
|
|
#include "MainWindow/MainWindow.h"
|
|
#include "Settings/BusAPI.h"
|
|
#include "Settings/GraphOption.h"
|
|
#include "Common/DebugLogger.h"
|
|
#include <QSettings>
|
|
#include <vtkSmartPointer.h>
|
|
#include <vtkRenderer.h>
|
|
#include <vtkGenericOpenGLRenderWindow.h>
|
|
#include <vtkPolyDataMapper.h>
|
|
#include <vtkActor.h>
|
|
#include <vtkStructuredGrid.h>
|
|
#include <vtkPoints.h>
|
|
#include <vtkFloatArray.h>
|
|
#include <vtkPointData.h>
|
|
#include <QVBoxLayout>
|
|
#include <cmath>
|
|
#include <cstdlib>
|
|
#include <vector>
|
|
#include <qDebug>
|
|
#include <vtkSTLWriter.h>
|
|
#include <QMessageBox>
|
|
#include <QFileInfo>
|
|
#include <QFileDialog>
|
|
|
|
namespace wave {
|
|
|
|
wavemodel::wavemodel(GUI::MainWindow* _mainwindow)
|
|
: QDialog(_mainwindow),
|
|
_mainwindow(_mainwindow),
|
|
ui(new Ui::wavemodel)
|
|
{
|
|
ui->setupUi(this);
|
|
connect(ui->ShowWave_pushButton, &QPushButton::clicked, this, &wavemodel::on_push_wave_models_slot);
|
|
connect(ui->SaveModel_pushButton, &QPushButton::clicked, this, &wavemodel::on_push_save_models_slot);
|
|
this->setWindowTitle(u8"动态水面生成");
|
|
initVTKView();
|
|
|
|
// Display default grid
|
|
vtkSmartPointer<vtkStructuredGrid> grid = createDefaultGrid();
|
|
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
|
|
mapper->SetInputData(grid);
|
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
actor->SetMapper(mapper);
|
|
|
|
_render->AddActor(actor);
|
|
_render->ResetCamera();
|
|
_renderWindow->Render();
|
|
}
|
|
|
|
wavemodel::~wavemodel()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void wavemodel::initVTKView() {
|
|
// 添加控件
|
|
_qvtkWidget = new QVTKOpenGLNativeWidget(this);
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(ui->modelViewContent);
|
|
mainLayout->addWidget(_qvtkWidget);
|
|
|
|
// 初始化渲染器
|
|
_renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
|
|
_qvtkWidget->setRenderWindow(_renderWindow);
|
|
|
|
_render = vtkSmartPointer<vtkOpenGLRenderer>::New();
|
|
_render->SetGradientBackground(true);
|
|
|
|
// 设置渲染背景色
|
|
Setting::GraphOption *option = Setting::BusAPI::instance()->getGraphOption();
|
|
QColor topcolor = option->getBackgroundTopColor();
|
|
QColor bottomcolor = option->getBackgroundBottomColor();
|
|
_render->SetBackground2(topcolor.redF(), topcolor.greenF(), topcolor.blueF());
|
|
_render->SetBackground(bottomcolor.redF(), bottomcolor.greenF(), bottomcolor.blueF());
|
|
|
|
// 开启硬件加速特性
|
|
_render->UseDepthPeelingOn();
|
|
_render->SetUseFXAA(true);
|
|
_interactor = _renderWindow->GetInteractor();
|
|
_renderWindow->AddRenderer(_render);
|
|
}
|
|
|
|
vtkSmartPointer<vtkStructuredGrid> wavemodel::createDefaultGrid()
|
|
{
|
|
vtkSmartPointer<vtkStructuredGrid> structuredGrid = vtkSmartPointer<vtkStructuredGrid>::New();
|
|
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
|
|
vtkSmartPointer<vtkFloatArray> heights = vtkSmartPointer<vtkFloatArray>::New();
|
|
heights->SetName("Height");
|
|
|
|
int gridSize = 10; // Default grid size
|
|
double spacing = 1.0; // Grid spacing
|
|
|
|
for (int i = 0; i < gridSize; ++i) {
|
|
for (int j = 0; j < gridSize; ++j) {
|
|
double x = i * spacing;
|
|
double y = j * spacing;
|
|
double z = sin(i) * cos(j); // Sample height value
|
|
points->InsertNextPoint(x, y, z);
|
|
heights->InsertNextValue(z);
|
|
}
|
|
}
|
|
|
|
structuredGrid->SetDimensions(gridSize, gridSize, 1);
|
|
structuredGrid->SetPoints(points);
|
|
structuredGrid->GetPointData()->SetScalars(heights);
|
|
|
|
return structuredGrid;
|
|
}
|
|
|
|
void wavemodel::on_push_wave_models_slot() {
|
|
|
|
//清除所有模型
|
|
_render->RemoveAllViewProps();
|
|
|
|
|
|
|
|
double v =ui->doubleSpinBox_v->value();
|
|
double t =ui->doubleSpinBox_t->value();
|
|
double Ymin =ui->doubleSpinBox_YMin->value();
|
|
double Ymax =ui->doubleSpinBox_YMax->value();
|
|
double Xmin =ui->doubleSpinBox_XMin->value();
|
|
double Xmax =ui->doubleSpinBox_XMax->value();
|
|
double rand =ui->doubleSpinBox_r->value();
|
|
int grid=ui->spinBox_g->value(); // 采样点数
|
|
|
|
// 计算采样间隔
|
|
double xdelta=(Xmax-Xmin)/(grid-1);
|
|
double ydelta=(Ymax-Ymin)/(grid-1);
|
|
|
|
|
|
_structuredGrid= vtkSmartPointer<vtkStructuredGrid>::New();
|
|
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
|
|
vtkSmartPointer<vtkFloatArray> heights = vtkSmartPointer<vtkFloatArray>::New();
|
|
heights->SetName("Height");
|
|
|
|
|
|
const double g = 9.8; // 重力加速度常数
|
|
const int m = 5; // theta 的段数
|
|
const int n = 5; // omg 的段数
|
|
const double T = 12.5; // 平均波浪周期
|
|
// const int grid_size = 101; // x 和 y 的大小为 101 (1500/15 + 1)
|
|
|
|
|
|
// 其他参数
|
|
double omg_0 = 2 * M_PI / T;
|
|
double min_omg = 0.3;
|
|
double max_omg = 0.8;
|
|
double d_omg = (max_omg - min_omg) / n;
|
|
double d_theta = M_PI / m;
|
|
double z = 0.0;
|
|
|
|
for (int xi = 0; xi < grid; ++xi) {
|
|
for(int yi = 0; yi < grid; ++yi) {
|
|
points->InsertNextPoint(xdelta * xi, ydelta * yi, 0.0);
|
|
heights->InsertNextValue(0);
|
|
}
|
|
}
|
|
double temp,omg_i,k_i,theta_j,eps,S_omg,p,q,fi_u;
|
|
// 计算波浪高度
|
|
for (int i = 1; i <= n; ++i) {
|
|
omg_i = (rand + i - 1) * d_omg + min_omg;
|
|
k_i = omg_i * omg_i / g;
|
|
for (int j = 1; j <= m; ++j) {
|
|
theta_j = -M_PI / 2 + d_theta * j;
|
|
eps = M_PI / 2 * (rand);
|
|
S_omg = 6.65e-4 * g * g * std::exp(-0.35 * g /std::pow( (v * omg_i), 4)) / std::pow(omg_i, 5);
|
|
p = 0.5 + 0.82 * std::exp(-0.5 * std::pow(omg_i / omg_0, 4));
|
|
q = 0.32 * std::exp(-0.5 * std::pow(omg_i / omg_0, 4));
|
|
fi_u = 1 / M_PI * (1 + p * std::cos(2 * theta_j) + q * std::cos(4 * theta_j));
|
|
|
|
for(int pid=0;pid<points->GetNumberOfPoints();pid++){
|
|
double* ppoint=points->GetPoint(pid);
|
|
temp = k_i * 15*ppoint[0] * std::cos(theta_j) + k_i * 15*ppoint[1] * std::sin(theta_j) - omg_i * t + eps;
|
|
ppoint[2] = std::cos(temp) * std::sqrt(2 * S_omg * fi_u * d_omg * d_theta) + ppoint[2];
|
|
points->SetPoint(pid,ppoint[0],ppoint[1],ppoint[2]);
|
|
heights->SetValue(pid,ppoint[2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
double range[2];
|
|
heights->GetRange(range);
|
|
double minvalue = range[0];
|
|
double maxvalue = range[1];
|
|
|
|
qDebug()<<"Minimum value: " << minvalue;
|
|
qDebug()<<"Maximum value: " << maxvalue;
|
|
|
|
_structuredGrid->SetDimensions(grid, grid, 1);
|
|
_structuredGrid->SetPoints(points);
|
|
_structuredGrid->GetPointData()->SetScalars(heights);
|
|
|
|
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
|
|
mapper->SetInputData(_structuredGrid);
|
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
actor->SetMapper(mapper);
|
|
|
|
_render->AddActor(actor);
|
|
_render->ResetCamera();
|
|
|
|
//更新渲染窗口
|
|
_renderWindow->Render();
|
|
_qvtkWidget->update();
|
|
|
|
}
|
|
|
|
|
|
void wavemodel::SaveWaveModel(QString filepath){
|
|
if(nullptr==_structuredGrid){
|
|
qDebug()<<"inpolyData ,nullptr : ";
|
|
}else{
|
|
qDebug()<<"inpolyData , cell Count : "+QString::number(_structuredGrid->GetNumberOfCells());
|
|
}
|
|
// stl 支持 polygondata 格式 vtkdataset
|
|
vtkSmartPointer<vtkGeometryFilter> polygonMeshFilter = vtkSmartPointer<vtkGeometryFilter>::New();
|
|
polygonMeshFilter->AddInputData(_structuredGrid);
|
|
polygonMeshFilter->Update();
|
|
if(nullptr==polygonMeshFilter->GetOutput()){
|
|
qDebug()<<" polygonMeshFilter write std error !!!! "+filepath;
|
|
}else{
|
|
|
|
}
|
|
|
|
|
|
vtkSmartPointer<vtkSTLWriter> writer = vtkSmartPointer<vtkSTLWriter>::New();
|
|
writer->SetInputData(polygonMeshFilter->GetOutput());
|
|
writer->SetFileTypeToBinary();
|
|
writer->SetFileName(filepath.toLocal8Bit().constData());
|
|
writer->Write();
|
|
|
|
QFile outfile(filepath);
|
|
if(outfile.exists()){
|
|
_curModelPath=filepath;
|
|
}
|
|
else{
|
|
QMessageBox::warning(nullptr, QObject::tr("Warning"), QObject::tr("wave model save Error !"));
|
|
}
|
|
}
|
|
// 导入网格
|
|
void wavemodel::importMeshModelToMainWindows( ) {
|
|
QString stdPath=_curModelPath;
|
|
QFileInfo info(stdPath);
|
|
QString name = info.fileName();
|
|
QString path = info.filePath();
|
|
QString suffix = "STL(*.stl)"; // 这里应该与 MeshDataExchangePlugin::install() 中的一致
|
|
//info.suffix().toLower();
|
|
emit _mainwindow->importMeshSIGN(stdPath,suffix,-1);
|
|
}
|
|
void wavemodel::on_push_save_models_slot() {
|
|
|
|
QString filepath = QFileDialog::getSaveFileName(this, tr("Save wave model "), "", "STL(*.stl)");
|
|
if (filepath.isEmpty())
|
|
{
|
|
return ;
|
|
|
|
}else{
|
|
this->SaveWaveModel(filepath);
|
|
this->importMeshModelToMainWindows();
|
|
};
|
|
}
|
|
|
|
} // namespace wave
|