QT學習VTK序列: Cell3D

#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++;
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章