#ifndef MAINWINDOW_H
#define MAINWINDOW_H
/*
* ModuleName: 模塊名稱
* Description:
* 參考代碼:https://lorensen.github.io/VTKExamples/site/Cxx/GeometricObjects/Cell3DDemonstration/
* Author: hsw
* Date: 2020-03-15
*
*/
// QT
#include <QMainWindow>
#include <QDebug>
// VTK
#include <vtkActor.h>
#include <vtkActor2D.h>
#include <vtkCamera.h>
#include <vtkCellArray.h>
#include <vtkDataSetMapper.h>
#include <vtkHexagonalPrism.h>
#include <vtkHexahedron.h>
#include <vtkNamedColors.h>
#include <vtkPentagonalPrism.h>
#include <vtkPoints.h>
#include <vtkPolyhedron.h>
#include <vtkProperty.h>
#include <vtkPyramid.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkTetra.h>
#include <vtkTextMapper.h>
#include <vtkTextProperty.h>
#include <vtkUnstructuredGrid.h>
#include <vtkVoxel.h>
#include <vtkWedge.h>
#include <vtkAutoInit.h>
// C++
#include <array>
#include <cstdlib>
#include <string>
#include <vector>
namespace Ui {
class MainWindow;
}
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType);
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
vtkSmartPointer<vtkUnstructuredGrid> MakeHexagonalPrism();
vtkSmartPointer<vtkUnstructuredGrid> MakeHexahedron();
vtkSmartPointer<vtkUnstructuredGrid> MakePentagonalPrism();
vtkSmartPointer<vtkUnstructuredGrid> MakePolyhedron();
vtkSmartPointer<vtkUnstructuredGrid> MakePyramid();
vtkSmartPointer<vtkUnstructuredGrid> MakeTetrahedron();
vtkSmartPointer<vtkUnstructuredGrid> MakeVoxel();
vtkSmartPointer<vtkUnstructuredGrid> MakeWedge();
private:
void MakeGridWindowRender(const int gridRow, const int gridCol);
private:
Ui::MainWindow *ui;
private:
// 文本內容
std::vector<std::string> titles;
// 文本
std::vector<vtkSmartPointer<vtkTextMapper> > textMappers;
std::vector<vtkSmartPointer<vtkActor2D> > textActors;
std::vector<vtkSmartPointer<vtkUnstructuredGrid> > uGrids;
std::vector<vtkSmartPointer<vtkDataSetMapper> > mappers;
std::vector<vtkSmartPointer<vtkActor> > actors;
std::vector<vtkSmartPointer<vtkRenderer> > renderers;
vtkSmartPointer<vtkRenderWindow> renderWindow;
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor;
int totalRendererCnt;
private:
vtkSmartPointer<vtkNamedColors> namedColors;
vtkColor3d backgroundColor;
vtkColor3d actorFaceColor;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// vtkNamedColor
namedColors = vtkSmartPointer<vtkNamedColors>::New();
std::array<unsigned char, 4> bkg{{51, 77, 102, 255}};
namedColors->SetColor("bkg", bkg.data());
backgroundColor = namedColors->GetColor3d("bkg");
actorFaceColor = namedColors->GetColor3d("Seashell");
// vtkUnstructuredGrid
uGrids.push_back(MakeHexagonalPrism());
titles.push_back("Hexagonal Prism");
uGrids.push_back(MakeHexahedron());
titles.push_back("Hexahedron");
uGrids.push_back(MakePentagonalPrism());
titles.push_back("Pentagonal Prism");
uGrids.push_back(MakePolyhedron());
titles.push_back("Polyhedron");
uGrids.push_back(MakePyramid());
titles.push_back("Pyramid");
uGrids.push_back(MakeTetrahedron());
titles.push_back("Tetrahedron");
uGrids.push_back(MakeVoxel());
titles.push_back("Voxel");
uGrids.push_back(MakeWedge());
titles.push_back("Wedge");
// vtkRenderWindow 和 vtkRenderWindowInteractor
totalRendererCnt = titles.size();
// 柵格化的界面
MakeGridWindowRender(3, 3);
}
MainWindow::~MainWindow()
{
delete ui;
}
vtkSmartPointer<vtkUnstructuredGrid> MainWindow::MakeHexagonalPrism()
{
// 3D: hexagonal prism(六棱柱): a wedge with an hexagonal base.
// Be careful, the base face ordering is different from wedge.
int numberOfVertices = 12;
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(0.0, 0.0, 1.0);
points->InsertNextPoint(1.0, 0.0, 1.0);
points->InsertNextPoint(1.5, 0.5, 1.0);
points->InsertNextPoint(1.0, 1.0, 1.0);
points->InsertNextPoint(0.0, 1.0, 1.0);
points->InsertNextPoint(-0.5, 0.5, 1.0);
points->InsertNextPoint(0.0, 0.0, 0.0);
points->InsertNextPoint(1.0, 0.0, 0.0);
points->InsertNextPoint(1.5, 0.5, 0.0);
points->InsertNextPoint(1.0, 1.0, 0.0);
points->InsertNextPoint(0.0, 1.0, 0.0);
points->InsertNextPoint(-0.5, 0.5, 0.0);
vtkSmartPointer<vtkHexagonalPrism> hexagonalPrism = vtkSmartPointer<vtkHexagonalPrism>::New();
for (int i = 0; i < numberOfVertices; ++i)
{
hexagonalPrism->GetPointIds()->SetId(i, i);
}
vtkSmartPointer<vtkUnstructuredGrid> ug = vtkSmartPointer<vtkUnstructuredGrid>::New();
ug->InsertNextCell(hexagonalPrism->GetCellType(),
hexagonalPrism->GetPointIds());
ug->SetPoints(points);
return ug;
}
vtkSmartPointer<vtkUnstructuredGrid> MainWindow::MakeHexahedron()
{
// A regular hexagon (cube, 立方體) with all faces square and three squares around
// each vertex is created below.
// Setup the coordinates of eight points
// (the two faces must be in counter clockwise
// order as viewed from the outside).
// As an exercise you can modify the coordinates of the points to create
// seven topologically distinct convex hexahedras.
int numberOfVertices = 8;
// Create the points
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(0.0, 0.0, 0.0);
points->InsertNextPoint(1.0, 0.0, 0.0);
points->InsertNextPoint(1.0, 1.0, 0.0);
points->InsertNextPoint(0.0, 1.0, 0.0);
points->InsertNextPoint(0.0, 0.0, 1.0);
points->InsertNextPoint(1.0, 0.0, 1.0);
points->InsertNextPoint(1.0, 1.0, 1.0);
points->InsertNextPoint(0.0, 1.0, 1.0);
// Create a hexahedron from the points
vtkSmartPointer<vtkHexahedron> hex = vtkSmartPointer<vtkHexahedron>::New();
for (int i = 0; i < numberOfVertices; ++i)
{
hex->GetPointIds()->SetId(i, i);
}
// Add the points and hexahedron to an unstructured grid
vtkSmartPointer<vtkUnstructuredGrid> uGrid =
vtkSmartPointer<vtkUnstructuredGrid>::New();
uGrid->SetPoints(points);
uGrid->InsertNextCell(hex->GetCellType(), hex->GetPointIds());
return uGrid;
}
vtkSmartPointer<vtkUnstructuredGrid> MainWindow::MakePentagonalPrism()
{
// 五棱柱
int numberOfVertices = 10;
// Create the points
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(11, 10, 10);
points->InsertNextPoint(13, 10, 10);
points->InsertNextPoint(14, 12, 10);
points->InsertNextPoint(12, 14, 10);
points->InsertNextPoint(10, 12, 10);
points->InsertNextPoint(11, 10, 14);
points->InsertNextPoint(13, 10, 14);
points->InsertNextPoint(14, 12, 14);
points->InsertNextPoint(12, 14, 14);
points->InsertNextPoint(10, 12, 14);
// Pentagonal Prism
vtkSmartPointer<vtkPentagonalPrism> pentagonalPrism = vtkSmartPointer<vtkPentagonalPrism>::New();
for (int i = 0; i < numberOfVertices; ++i)
{
pentagonalPrism->GetPointIds()->SetId(i, i);
}
// Add the points and hexahedron to an unstructured grid
vtkSmartPointer<vtkUnstructuredGrid> uGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
uGrid->SetPoints(points);
uGrid->InsertNextCell(pentagonalPrism->GetCellType(),
pentagonalPrism->GetPointIds());
return uGrid;
}
vtkSmartPointer<vtkUnstructuredGrid> MainWindow::MakePolyhedron()
{
// Make a regular dodecahedron. It consists of twelve regular pentagonal(五邊形)
// faces with three faces meeting at each vertex.
int numberOfVertices = 20;
int numberOfFaces = 12;
int numberOfFaceVertices = 5;
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint( 1.21412, 0, 1.58931);
points->InsertNextPoint( 0.375185, 1.1547, 1.58931);
points->InsertNextPoint(-0.982247, 0.713644, 1.58931);
points->InsertNextPoint(-0.982247, -0.713644, 1.58931);
points->InsertNextPoint( 0.375185, -1.1547, 1.58931);
points->InsertNextPoint( 1.96449, 0, 0.375185);
points->InsertNextPoint( 0.607062, 1.86835, 0.375185);
points->InsertNextPoint(-1.58931, 1.1547, 0.375185);
points->InsertNextPoint(-1.58931, -1.1547, 0.375185);
points->InsertNextPoint( 0.607062, -1.86835, 0.375185);
points->InsertNextPoint( 1.58931, 1.1547, -0.375185);
points->InsertNextPoint(-0.607062, 1.86835, -0.375185);
points->InsertNextPoint(-1.96449, 0, -0.375185);
points->InsertNextPoint(-0.607062, -1.86835, -0.375185);
points->InsertNextPoint( 1.58931, -1.1547, -0.375185);
points->InsertNextPoint( 0.982247, 0.713644, -1.58931);
points->InsertNextPoint(-0.375185, 1.1547, -1.58931);
points->InsertNextPoint(-1.21412, 0, -1.58931);
points->InsertNextPoint(-0.375185, -1.1547, -1.58931);
points->InsertNextPoint( 0.982247, -0.713644, -1.58931);
vtkIdType dodechedronPointsIds[20] =
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
vtkIdType dodechedronFace[12][5] = {
{0, 1, 2, 3, 4},
{0, 5, 10, 6, 1},
{1, 6, 11, 7, 2},
{2, 7, 12, 8, 3},
{3, 8, 13, 9, 4},
{4, 9, 14, 5, 0},
{15, 10, 5, 14, 19},
{16, 11, 6, 10, 15},
{17, 12, 7, 11, 16},
{18, 13, 8, 12, 17},
{19, 14, 9, 13, 18},
{19, 18, 17, 16, 15}
};
vtkSmartPointer<vtkCellArray> dodechedronFaces = vtkSmartPointer<vtkCellArray>::New();
for (int i = 0; i < numberOfFaces; i++)
{
dodechedronFaces->InsertNextCell(numberOfFaceVertices, dodechedronFace[i]);
}
vtkSmartPointer<vtkUnstructuredGrid> uGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
uGrid->InsertNextCell(VTK_POLYHEDRON,
numberOfVertices, dodechedronPointsIds,
numberOfFaces, dodechedronFaces->GetPointer());
uGrid->SetPoints(points);
return uGrid;
}
vtkSmartPointer<vtkUnstructuredGrid> MainWindow::MakePyramid()
{
// Make a regular square pyramid(方形棱錐).
int numberOfVertices = 5;
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
float p0[3] = {1.0, 1.0, 0.0};
float p1[3] = {-1.0, 1.0, 0.0};
float p2[3] = {-1.0, -1.0, 0.0};
float p3[3] = {1.0, -1.0, 0.0};
float p4[3] = {0.0, 0.0, 1.0};
points->InsertNextPoint(p0);
points->InsertNextPoint(p1);
points->InsertNextPoint(p2);
points->InsertNextPoint(p3);
points->InsertNextPoint(p4);
vtkSmartPointer<vtkPyramid> pyramid = vtkSmartPointer<vtkPyramid>::New();
for (int i = 0; i < numberOfVertices; ++i)
{
pyramid->GetPointIds()->SetId(i, i);
}
vtkSmartPointer<vtkUnstructuredGrid> ug = vtkSmartPointer<vtkUnstructuredGrid>::New();
ug->SetPoints(points);
ug->InsertNextCell(pyramid->GetCellType(),pyramid->GetPointIds());
return ug;
}
vtkSmartPointer<vtkUnstructuredGrid> MainWindow::MakeTetrahedron()
{
// Make a tetrahedron(四面體).
int numberOfVertices = 4;
vtkSmartPointer< vtkPoints > points = vtkSmartPointer< vtkPoints > :: New();
points->InsertNextPoint(0, 0, 0);
points->InsertNextPoint(1, 0, 0);
points->InsertNextPoint(1, 1, 0);
points->InsertNextPoint(0, 1, 1);
vtkSmartPointer<vtkTetra> tetra = vtkSmartPointer<vtkTetra>::New();
for (int i = 0; i < numberOfVertices; ++i)
{
tetra->GetPointIds()->SetId(i, i);
}
vtkSmartPointer<vtkCellArray> cellArray = vtkSmartPointer<vtkCellArray>::New();
cellArray->InsertNextCell(tetra);
vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
unstructuredGrid->SetPoints(points);
unstructuredGrid->SetCells(VTK_TETRA, cellArray);
return unstructuredGrid;
}
vtkSmartPointer<vtkUnstructuredGrid> MainWindow::MakeVoxel()
{
// A voxel is a representation of a regular grid in 3-D space.
int numberOfVertices = 8;
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(0, 0, 0);
points->InsertNextPoint(1, 0, 0);
points->InsertNextPoint(0, 1, 0);
points->InsertNextPoint(1, 1, 0);
points->InsertNextPoint(0, 0, 1);
points->InsertNextPoint(1, 0, 1);
points->InsertNextPoint(0, 1, 1);
points->InsertNextPoint(1, 1, 1);
vtkSmartPointer<vtkVoxel> voxel = vtkSmartPointer<vtkVoxel>::New();
for (int i = 0; i < numberOfVertices; ++i)
{
voxel->GetPointIds()->SetId(i, i);
}
vtkSmartPointer<vtkUnstructuredGrid> ug = vtkSmartPointer<vtkUnstructuredGrid>::New();
ug->SetPoints(points);
ug->InsertNextCell(voxel->GetCellType(),voxel->GetPointIds());
return ug;
}
vtkSmartPointer<vtkUnstructuredGrid> MainWindow::MakeWedge()
{
// A wedge consists of two triangular ends and three rectangular faces.
int numberOfVertices = 6;
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(0, 1, 0);
points->InsertNextPoint(0, 0, 0);
points->InsertNextPoint(0, .5, .5);
points->InsertNextPoint(1, 1, 0);
points->InsertNextPoint(1, 0.0, 0.0);
points->InsertNextPoint(1, .5, .5);
vtkSmartPointer<vtkWedge> wedge = vtkSmartPointer<vtkWedge>::New();
for (int i = 0; i < numberOfVertices; ++i)
{
wedge->GetPointIds()->SetId(i, i);
}
vtkSmartPointer<vtkUnstructuredGrid> ug = vtkSmartPointer<vtkUnstructuredGrid>::New();
ug->SetPoints(points);
ug->InsertNextCell(wedge->GetCellType(),wedge->GetPointIds());
return ug;
}
void MainWindow::MakeGridWindowRender(const int gridRow, const int gridCol)
{
renderers.clear();
double gridRowStep = 1.0 / gridRow;
double gridColStep = 1.0 / gridCol;
vtkSmartPointer<vtkTextProperty> textProperty = vtkSmartPointer<vtkTextProperty>::New();
textProperty->SetFontSize(16);
textProperty->SetJustificationToCentered();
int iterRow, iterCol;
int winIndex = 0;
for(iterRow = 0; iterRow < gridRow; ++iterRow)
{
for(iterCol = 0; iterCol < gridCol; ++iterCol)
{
double viewport[4] = {gridColStep * iterCol ,
(gridRow - iterRow - 1) * gridRowStep,
gridColStep * (iterCol + 1) ,
(gridRow - iterRow ) * gridRowStep};
renderers.push_back(vtkSmartPointer<vtkRenderer>::New());
textMappers.push_back(vtkSmartPointer<vtkTextMapper>::New());
textActors.push_back(vtkSmartPointer<vtkActor2D>::New());
mappers.push_back(vtkSmartPointer<vtkDataSetMapper>::New());
actors.push_back(vtkSmartPointer<vtkActor>::New());
if(winIndex >= totalRendererCnt)
{// 柵格窗口中未使用的部分
renderers[winIndex]->SetViewport(viewport);
renderers[winIndex]->ResetCameraClippingRange();
renderers[winIndex]->SetBackground(backgroundColor.GetData());
ui->qvtkWidget->GetRenderWindow()->AddRenderer((*(renderers.rbegin())));
}
else
{// 柵格窗口中使用的部分
mappers[winIndex]->SetInputData(uGrids[winIndex]);
actors[winIndex]->SetMapper(mappers[winIndex]);
actors[winIndex]->GetProperty()->SetColor(actorFaceColor.GetData());
renderers[winIndex]->AddViewProp(actors[winIndex]);
textMappers[winIndex]->SetInput(titles[winIndex].c_str());
textMappers[winIndex]->SetTextProperty(textProperty);
textActors[winIndex]->SetMapper(textMappers[winIndex]);
textActors[winIndex]->SetPosition(120, 16);
renderers[winIndex]->AddViewProp(textActors[winIndex]);
renderers[winIndex]->SetViewport(viewport);
renderers[winIndex]->ResetCameraClippingRange();
renderers[winIndex]->SetBackground(backgroundColor.GetData());
renderers[winIndex]->ResetCamera();
renderers[winIndex]->GetActiveCamera()->Azimuth(30);
renderers[winIndex]->GetActiveCamera()->Elevation(-30);
renderers[winIndex]->GetActiveCamera()->Zoom(0.85);
renderers[winIndex]->ResetCameraClippingRange();
ui->qvtkWidget->GetRenderWindow()->AddRenderer((*(renderers.rbegin())));
}
winIndex++;
}
}
}