QT學習VTK序列: OrientedArrow

/*
 * ModuleName: 模塊名稱
 * Description:
 * 參考代碼:https://lorensen.github.io/VTKExamples/site/Cxx/GeometricObjects/orientedArrow/
 * Author: hsw
 * Date: 2020-03-15
 *
*/

// QT
#include <QMainWindow>
#include <QDebug>

// VTK
#include <vtkActor.h>
#include <vtkArrowSource.h>
#include <vtkMath.h>
#include <vtkMinimalStandardRandomSequence.h>
#include <vtkNamedColors.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkAutoInit.h>

// C++
#include <array>

namespace Ui {
class MainWindow;
}

VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType);

// #define USER_MATRIX

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
private:

};
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    vtkSmartPointer<vtkNamedColors> colors =
            vtkSmartPointer<vtkNamedColors>::New();

    // Set the background color.
    std::array<unsigned char , 4> bkg{{26, 51, 77, 255}};
    colors->SetColor("BkgColor", bkg.data());

    //Create an arrow.
    vtkSmartPointer<vtkArrowSource> arrowSource =
            vtkSmartPointer<vtkArrowSource>::New();

    // Generate a random start and end point
    double startPoint[3];
    double endPoint[3];
    vtkSmartPointer<vtkMinimalStandardRandomSequence> rng =
            vtkSmartPointer<vtkMinimalStandardRandomSequence>::New();
    rng->SetSeed(8775070); // For testing.
    for (auto i = 0; i < 3; ++i)
    {
        rng->Next();
        startPoint[i] = rng->GetRangeValue(-10, 10);
        rng->Next();
        endPoint[i] = rng->GetRangeValue(-10, 10);
    }

#if 1
    // Compute a basis
    double normalizedX[3];
    double normalizedY[3];
    double normalizedZ[3];

    // The X axis is a vector from start to end
    vtkMath::Subtract(endPoint, startPoint, normalizedX);
    double length = vtkMath::Norm(normalizedX);
    vtkMath::Normalize(normalizedX);

    // The Z axis is an arbitrary vector cross X
    double arbitrary[3];
    for (auto i = 0; i < 3; ++i)
    {
        rng->Next();
        arbitrary[i] = rng->GetRangeValue(-10, 10);
    }
    vtkMath::Cross(normalizedX, arbitrary, normalizedZ);
    vtkMath::Normalize(normalizedZ);

    // The Y axis is Z cross X
    vtkMath::Cross(normalizedZ, normalizedX, normalizedY);
    vtkSmartPointer<vtkMatrix4x4> matrix =
            vtkSmartPointer<vtkMatrix4x4>::New();

    // Create the direction cosine matrix
    matrix->Identity();
    for (auto i = 0; i < 3; i++)
    {
        matrix->SetElement(i, 0, normalizedX[i]);
        matrix->SetElement(i, 1, normalizedY[i]);
        matrix->SetElement(i, 2, normalizedZ[i]);
    }

    // Apply the transforms
    vtkSmartPointer<vtkTransform> transform =
            vtkSmartPointer<vtkTransform>::New();
    transform->Translate(startPoint);
    transform->Concatenate(matrix);
    transform->Scale(length, length, length);

    // Transform the polydata
    vtkSmartPointer<vtkTransformPolyDataFilter> transformPD =
            vtkSmartPointer<vtkTransformPolyDataFilter>::New();
    transformPD->SetTransform(transform);
    transformPD->SetInputConnection(arrowSource->GetOutputPort());

    //Create a mapper and actor for the arrow
    vtkSmartPointer<vtkPolyDataMapper> mapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    vtkSmartPointer<vtkActor> actor =
            vtkSmartPointer<vtkActor>::New();
#ifdef USER_MATRIX
    mapper->SetInputConnection(arrowSource->GetOutputPort());
    actor->SetUserMatrix(transform->GetMatrix());
#else
    mapper->SetInputConnection(transformPD->GetOutputPort());
#endif
#else
    //Create a mapper and actor for the arrow
    vtkSmartPointer<vtkPolyDataMapper> mapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(arrowSource->GetOutputPort());

    vtkSmartPointer<vtkActor> actor =
            vtkSmartPointer<vtkActor>::New();
#endif
    actor->SetMapper(mapper);
    actor->GetProperty()->SetColor(colors->GetColor3d("Cyan").GetData());

    // Create spheres for start and end point
    vtkSmartPointer<vtkSphereSource> sphereStartSource =
            vtkSmartPointer<vtkSphereSource>::New();
    sphereStartSource->SetCenter(startPoint);
    sphereStartSource->SetRadius(0.8);
    vtkSmartPointer<vtkPolyDataMapper> sphereStartMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    sphereStartMapper->SetInputConnection(sphereStartSource->GetOutputPort());
    vtkSmartPointer<vtkActor> sphereStart =
            vtkSmartPointer<vtkActor>::New();
    sphereStart->SetMapper(sphereStartMapper);
    sphereStart->GetProperty()->SetColor(colors->GetColor3d("Yellow").GetData());

    vtkSmartPointer<vtkSphereSource> sphereEndSource =
            vtkSmartPointer<vtkSphereSource>::New();
    sphereEndSource->SetCenter(endPoint);
    sphereEndSource->SetRadius(0.8);
    vtkSmartPointer<vtkPolyDataMapper> sphereEndMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    sphereEndMapper->SetInputConnection(sphereEndSource->GetOutputPort());
    vtkSmartPointer<vtkActor> sphereEnd =
            vtkSmartPointer<vtkActor>::New();
    sphereEnd->SetMapper(sphereEndMapper);
    sphereEnd->GetProperty()->SetColor(colors->GetColor3d("Magenta").GetData());

    //Create a renderer
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();

    //Add the actor to the scene
    renderer->AddActor(actor);
    renderer->AddActor(sphereStart);
    renderer->AddActor(sphereEnd);
    renderer->SetBackground(colors->GetColor3d("BkgColor").GetData());

    // vtkRenderWindow
    ui->qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
    ui->qvtkWidget->GetRenderWindow()->SetWindowName("Oriented Arrow");
}

MainWindow::~MainWindow()
{
    delete ui;
}

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