VTK(Visualization Toolkit)是一个开源的、跨平台的三维可视化开发库,用于处理和可视化三维数据。它提供了一系列算法和工具,用于创建、操作和渲染复杂的三维图形,并支持多种数据表示方式,包括点、线、面、体等。VTK提供了一套高效的算法,用于可视化医学图像、流体动力学模拟、地理信息系统等领域的数据。
1、VTK源码下载
源码下载地址:https://vtk.org/download/
将VTK-9.3.1.tar.gz ,VTKData-9.3.1.tar.gz,VTKLargeData-9.3.1.tar.gz解压到同一目录,并创建build和SDK文件夹。
2、CMake设置
打开CMake-gui进行设置:
开启支持Qt编译;电脑上会自动找到对应的Qt路径(Qt已经在电脑环境变量添加过路径)。
点击“config”按钮,没有错误提示后点击“Generate”按钮,最后点击“open project”按钮打开VS工程。
3、VS编译
点击Open project 按钮打开VS项目工程,然后先选择 ALL_BUILD进行生成,随后选择INSTALL进行sdk整理。
编译后的VTK sdk如下所示:
4、示例demo
编译完成后我们来验证一下VTK编译的是否正确可用。此处可以参考VTK提供的示例代码。我们用了Qt+VTK来进行验证。https://examples.vtk.org/site/。
4.1 演示效果
演示效果如下图:
4.2 源码
#include <QtCore/QCoreApplication>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkActor.h>
#include <vtkDataSetMapper.h>
#include <vtkDoubleArray.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkPointData.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <QApplication>
#include <QDockWidget>
#include <QGridLayout>
#include <QLabel>
#include <QMainWindow>
#include <QPointer>
#include <QPushButton>
#include <QVBoxLayout>
#include <cmath>
#include <cstdlib>
#include <random>
namespace {
/**
* Deform the sphere source using a random amplitude and modes and render it in
* the window
*
* @param sphere the original sphere source
* @param mapper the mapper for the scene
* @param window the window to render to
* @param randEng the random number generator engine
*/
void Randomize(vtkSphereSource* sphere, vtkMapper* mapper,
vtkGenericOpenGLRenderWindow* window, std::mt19937& randEng);
} // namespace
int main(int argc, char* argv[])
{
QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());
QApplication app(argc, argv);
// Main window.
QMainWindow mainWindow;
mainWindow.resize(1200, 900);
// Control area.
QDockWidget controlDock;
mainWindow.addDockWidget(Qt::LeftDockWidgetArea, &controlDock);
QLabel controlDockTitle("Control Dock");
controlDockTitle.setMargin(20);
controlDock.setTitleBarWidget(&controlDockTitle);
QPointer<QVBoxLayout> dockLayout = new QVBoxLayout();
QWidget layoutContainer;
layoutContainer.setLayout(dockLayout);
controlDock.setWidget(&layoutContainer);
QPushButton randomizeButton;
randomizeButton.setText("Randomize");
dockLayout->addWidget(&randomizeButton);
// Render area.
QPointer<QVTKOpenGLNativeWidget> vtkRenderWidget =
new QVTKOpenGLNativeWidget();
mainWindow.setCentralWidget(vtkRenderWidget);
// VTK part.
vtkNew<vtkGenericOpenGLRenderWindow> window;
vtkRenderWidget->setRenderWindow(window.Get());
vtkNew<vtkSphereSource> sphere;
sphere->SetRadius(1.0);
sphere->SetThetaResolution(100);
sphere->SetPhiResolution(100);
vtkNew<vtkDataSetMapper> mapper;
mapper->SetInputConnection(sphere->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetEdgeVisibility(true);
actor->GetProperty()->SetRepresentationToSurface();
vtkNew<vtkRenderer> renderer;
renderer->AddActor(actor);
window->AddRenderer(renderer);
// Setup initial status.
std::mt19937 randEng(0);
::Randomize(sphere, mapper, window, randEng);
// connect the buttons
QObject::connect(&randomizeButton, &QPushButton::released,
[&]() { ::Randomize(sphere, mapper, window, randEng); });
mainWindow.show();
return app.exec();
}
namespace {
void Randomize(vtkSphereSource* sphere, vtkMapper* mapper,
vtkGenericOpenGLRenderWindow* window, std::mt19937& randEng)
{
// Generate randomness.
double randAmp = 0.2 + ((randEng() % 1000) / 1000.0) * 0.2;
double randThetaFreq = 1.0 + (randEng() % 9);
double randPhiFreq = 1.0 + (randEng() % 9);
// Extract and prepare data.
sphere->Update();
vtkSmartPointer<vtkPolyData> newSphere;
newSphere.TakeReference(sphere->GetOutput()->NewInstance());
newSphere->DeepCopy(sphere->GetOutput());
vtkNew<vtkDoubleArray> height;
height->SetName("Height");
height->SetNumberOfComponents(1);
height->SetNumberOfTuples(newSphere->GetNumberOfPoints());
newSphere->GetPointData()->AddArray(height);
// Deform the sphere.
for (int iP = 0; iP < newSphere->GetNumberOfPoints(); iP++)
{
double pt[3] = { 0.0 };
newSphere->GetPoint(iP, pt);
double theta = std::atan2(pt[1], pt[0]);
double phi =
std::atan2(pt[2], std::sqrt(std::pow(pt[0], 2) + std::pow(pt[1], 2)));
double thisAmp =
randAmp * std::cos(randThetaFreq * theta) * std::sin(randPhiFreq * phi);
height->SetValue(iP, thisAmp);
pt[0] += thisAmp * std::cos(theta) * std::cos(phi);
pt[1] += thisAmp * std::sin(theta) * std::cos(phi);
pt[2] += thisAmp * std::sin(phi);
newSphere->GetPoints()->SetPoint(iP, pt);
}
newSphere->GetPointData()->SetScalars(height);
// Reconfigure the pipeline to take the new deformed sphere.
mapper->SetInputDataObject(newSphere);
mapper->SetScalarModeToUsePointData();
mapper->ColorByArrayComponent("Height", 0);
window->Render();
}
} // namespace
4.3 项目属性设定
vtkGUISupportQt-9.3d.lib
vtkRenderingCore-9.3d.lib
vtkRenderingOpenGL2-9.3d.lib
vtkCommonCore-9.3d.lib
vtkCommonDataModel-9.3d.lib
vtkCommonExecutionModel-9.3d.lib
vtkFiltersCore-9.3d.lib
vtkFiltersSources-9.3d.lib
vtksys-9.3d.lib