VTK+CTK+Qt5 配置与测试

VTK、CTK的编译安装

下载

  1. VTK源码地址:Gitlab或者Github
  2. CTK源码地址:Github
  3. CMake, 3.12.3
  4. git
  5. Qt 5.11.2
  6. Windows: Visual Studio 2017, Mac: clang + make

编译

编译VTK

$ mkdir Libs
$ cd Libs
$ git clone https://gitlab.kitware.com/vtk/vtk.git 
#注:Windows下使用最新版本,Mac下使用v8.0.1,不然总出现OpenGL错误,未解决

使用CMake-GUI配置,

  • Where is the source code选择Libs/VTK

  • Where to build the binaries选择Libs/VTK-build

  • CMAKE_INSTALL_PREFIX选择Libs/VTK-install

  • VTK_Group_QT勾选,

  • VTK_QT_VERSION选择5,

  • Qt5_DIR选择Qt5安装目录下的5.11.2/lib/cmake/Qt5目录,

  • Windows下可勾选Module_vtkGUISupportQtOpenGL,Mac下勾选运行时会报错,不知道为什么

  • VTK_DEBUG_LEAKS可勾选,程序运行完会提示是否有内存泄漏

  • 取消勾选BUILD_TEST

  • 多次configure没有错误及红色提示之后Generate
    编译工程, 安装

编译CTK

$ mkdir Libs
$ cd Libs
$ git clone https://github.com/commontk/CTK.git 

使用CMake-GUI配置,

  • Where is the source code选择Libs/CTK
  • Where to build the binaries选择Libs/CTK-build
  • CMAKE_INSTALL_PREFIX选择Libs/CTK-install
  • CTK_QT_VERSION选择5,
  • Qt5_DIR选择Qt5安装目录下的5.11.2/lib/cmake/Qt5目录,
  • 勾选CMAKE_BUILD_QTDESIGNER_PLUGINS
  • 取消勾选BUILD_TEST
  • 多次configure没有错误及红色提示之后Generate
    编译工程, 安装,注意,CTK安装需要在CTK-build目录安装一次,然后在CTK-build/CTK-build目录再安装一次

测试

VTK测试

CMakeLists.txt

cmake_minimum_required(VERSION 3.12)
project(VTKTest)

set(CMAKE_CXX_STANDARD 14)

IF(APPLE)
    SET(VTK_DIR "/Users/fitsir/Libs/VTK-install/lib/cmake/vtk-8.0")
    SET(CTK_DIR "/Users/fitsir/Libs/CTK-install/lib/ctk-0.1/CMake")
ENDIF()

FIND_PACKAGE(VTK REQUIRED)
IF (VTK_FOUND)
    MESSAGE(STATUS "VTK found.")
    INCLUDE(${VTK_USE_FILE})
ENDIF()
FIND_PACKAGE(CTK REQUIRED)
IF(CTK_FOUND)
    MESSAGE(STATUS "CTK found.")
    INCLUDE(${CTK_USE_FILE})
ENDIF()
FIND_PACKAGE(Qt5 COMPONENTS Widgets OpenGL REQUIRED)
IF(Qt5_FOUND)
    MESSAGE(STATUS "Qt5 found.")
ENDIF()


add_executable(VTKTest main.cpp)
target_link_libraries(VTKTest
    ${VTK_LIBRARIES})

main.cpp

#include <iostream>
//VTK includes
#include <vtkRenderWindow.h>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>

void vtk_without_qt();

int main() {
    std::cout << "Hello, World!" << std::endl;
    vtk_without_qt();
    return 0;
}

void vtk_without_qt(){
    auto cylinder = vtkSmartPointer<vtkCylinderSource>::New();
    cylinder->SetHeight(3.0);
    cylinder->SetRadius(1.0);
    cylinder->SetResolution(10);
    auto cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
    auto cylinderActor = vtkSmartPointer<vtkActor>::New();
    cylinderActor->SetMapper(cylinderMapper);
    auto renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(cylinderActor);
    renderer->SetBackground(0.1, 0.2, 0.4);
    auto renWin = vtkSmartPointer<vtkRenderWindow>::New();
    renWin->AddRenderer(renderer);
    renWin->SetSize(300, 300);
    auto iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    iren->SetRenderWindow(renWin);
    auto style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    iren->SetInteractorStyle(style);

    iren->Initialize();
    iren->Start();
}

运行效果

vtk_without_qt.png

VTK+Qt5 测试

CMakeLists.txt

CMakeLists.txt只需添加Qt5相关的库

target_link_libraries(VTKTest
    ${VTK_LIBRARIES}
    ${Qt5Widgets_LIBRARIES}
    ${Qt5OpenGL_LIBRARIES})

main.cpp

#include <iostream>
//VTK includes
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>

#include <QVTKOpenGLWidget.h>
#include <QApplication>
#include <QVBoxLayout>
#include <QSurfaceFormat>
int vtk_with_qt(int argc, char* argv[]);

int main(int argc, char* argv[]) {
    std::cout << "Hello, World!" << std::endl;
    QSurfaceFormat::setDefaultFormat(QVTKOpenGLWidget::defaultFormat());

    return vtk_with_qt(argc, argv);

}

int vtk_with_qt(int argc, char* argv[]){
    QApplication a(argc, argv);
    QWidget w;// = new QWidget(0);
    QVBoxLayout layout;// = new QVBoxLayout(0);
    QVTKOpenGLWidget v;// = new QVTKOpenGLWidget();
    v.setFixedSize(300, 300);
    layout.addWidget(&v);
    w.setLayout(&layout);

    auto cylinder = vtkSmartPointer<vtkCylinderSource>::New();
    cylinder->SetHeight(3.0);
    cylinder->SetRadius(1.0);
    cylinder->SetResolution(10);
    auto cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
    auto cylinderActor = vtkSmartPointer<vtkActor>::New();
    cylinderActor->SetMapper(cylinderMapper);
    auto renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(cylinderActor);
    renderer->SetBackground(0.1, 0.2, 0.4);
    auto renWin = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renWin->AddRenderer(renderer);

    v.SetRenderWindow(renWin);
    w.show();

    return a.exec();
}

运行效果

vtk_with_qt.png

VTK+CTK+Qt5测试

CMakeList.txt

#Qt5 需要添加CTK依赖的一些库
FIND_PACKAGE(Qt5 COMPONENTS Widgets OpenGL Xml Network REQUIRED)
target_link_libraries(VTKTest
    ${VTK_LIBRARIES}
    ${Qt5Widgets_LIBRARIES}
    ${Qt5OpenGL_LIBRARIES}
    ${CTK_LIBRARIES})

main.cpp

#include <iostream>
//VTK includes
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>

#include <QVTKOpenGLWidget.h>
#include <QApplication>
#include <QVBoxLayout>
#include <QSurfaceFormat>
#include <ctkVTKRenderView.h>
#include <ctkSliderWidget.h>
int vtk_with_ctk_qt(int argc, char* argv[]);

int main(int argc, char* argv[]) {
    std::cout << "Hello, World!" << std::endl;
    QSurfaceFormat::setDefaultFormat(QVTKOpenGLWidget::defaultFormat());

    return vtk_with_ctk_qt(argc, argv);

}


int vtk_with_ctk_qt(int argc, char* argv[]){
    QApplication a(argc, argv);
    QWidget w;// = new QWidget(0);
    QVBoxLayout layout;// = new QVBoxLayout(0);
    ctkVTKRenderView v;// = new QVTKOpenGLWidget();

    v.setFixedSize(300, 300);
    layout.addWidget(&v);
    ctkSliderWidget s;
    s.setRange(0, 100);
    layout.addWidget(&s);
    w.setLayout(&layout);

    auto cylinder = vtkSmartPointer<vtkCylinderSource>::New();
    cylinder->SetHeight(3.0);
    cylinder->SetRadius(1.0);
    cylinder->SetResolution(10);
    auto cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
    auto cylinderActor = vtkSmartPointer<vtkActor>::New();
    cylinderActor->SetMapper(cylinderMapper);
    auto renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(cylinderActor);
    renderer->SetBackground(0.1, 0.2, 0.4);
    auto renWin = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renWin->AddRenderer(renderer);

    v.renderWindow()->AddRenderer(renderer);
    w.show();

    return a.exec();
}

运行效果

vtk_with_ctk_qt.png

VTK 机械臂控制

main.cpp

//VTK includes
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkLODActor.h>
#include <vtkAssembly.h>
#include <vtkSTLReader.h>
#include <vtkProperty.h>
#include <vtkCamera.h>
#include <vtkPlaneSource.h>
#include <vtkTransform.h>
#include <vtkAxesActor.h>
#include <vtkCaptionActor2D.h>
#include <QVTKOpenGLWidget.h>

#include <QApplication>
#include <QVBoxLayout>
#include <QSurfaceFormat>
#include <QString>
#include <QFile>
#include <QDebug>
#include <QLineEdit>
#include <ctkSliderWidget.h>

int vtk_arm_control(int argc, char* argv[]);
vtkSmartPointer<vtkLODActor> setupActor(QString toolPath);
void setGround();
void setAxes();
void setAssembly();
void valueChanged1(double value);
void valueChanged2(double value);
void setCamera();

#define FILE1 "/A1.STL"
#define FILE2 "/A2.STL"
#define FILE3 "/A3.STL"
vtkSmartPointer<vtkRenderer> renderer;
vtkSmartPointer<vtkAssembly> assembly[3];
vtkSmartPointer<vtkGenericOpenGLRenderWindow> renWin;

int main(int argc, char* argv[]) {
    qDebug() << "Hello, World!";
    QSurfaceFormat::setDefaultFormat(QVTKOpenGLWidget::defaultFormat());
    renderer = vtkSmartPointer<vtkRenderer>::New();
    renWin = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    return vtk_arm_control(argc, argv);
}

int vtk_arm_control(int argc, char* argv[]){
    QApplication a(argc, argv);
    QWidget window;
    window.setMinimumSize(400, 400);
    QVBoxLayout layout;

    QVTKOpenGLWidget view;
    ctkSliderWidget slider1, slider2;
    slider1.setMinimum(-180);
    slider1.setMaximum(180);
    slider2.setMinimum(-180);
    slider2.setMaximum(180);

    layout.addWidget(&view);
    layout.addWidget(&slider1);
    layout.addWidget(&slider2);
    QObject::connect(&slider1, &ctkSliderWidget::valueChanged, &valueChanged1);
    QObject::connect(&slider2, &ctkSliderWidget::valueChanged, &valueChanged2);
    window.setLayout(&layout);

    QString path = "/Users/fitsir/P/VTKTest/stl";

    QList<QString> filenames;
    filenames << path + FILE1          //1
              << path + FILE2
              << path + FILE3;
    vtkSmartPointer<vtkLODActor> actor[3];
    for(int i = 0; i < filenames.size(); i++) {
        actor[i] = setupActor(filenames[i].toLatin1());
    }

    assembly[1] = vtkSmartPointer<vtkAssembly>::New();
    assembly[0] = vtkSmartPointer<vtkAssembly>::New();
    assembly[2] = vtkSmartPointer<vtkAssembly>::New();

    assembly[2]->AddPart(actor[2]);
    assembly[2]->SetOrigin(350, 0, 705);

    assembly[1]->AddPart(actor[1]);
    assembly[1]->AddPart(assembly[2]);
    assembly[1]->SetOrigin(0, 0, 0);

    assembly[0]->AddPart(actor[0]);
    assembly[0]->AddPart(assembly[1]);
    assembly[0]->SetOrigin(0, 0, 0);// # This is the point about which all rotations take place


    renderer->AddActor(assembly[0]);
    renWin->AddRenderer(renderer);

    setAxes();
    setGround();
    renderer->SetBackground(.2, .2, .2);
    setCamera();
    renderer->ResetCameraClippingRange();


    view.SetRenderWindow(renWin);
    window.show();

    return a.exec();
}

vtkSmartPointer<vtkLODActor> setupActor(QString toolPath) {
    qDebug() << "setupActor";
    QFile file(toolPath);
    if(!file.exists()) {
        qDebug() << QString("STL file %1 is missing").arg(toolPath);
        return nullptr;
    }

    vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
    vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    reader->SetFileName(toolPath.toLatin1());
    reader->Update();
    mapper->SetInputConnection(reader->GetOutputPort());
    actor->SetMapper(mapper);
    double r = vtkMath::Random(.4, 1.0);
    double g = vtkMath::Random(.4, 1.0);
    double b = vtkMath::Random(.4, 1.0);
    actor->GetProperty()->SetDiffuseColor(r, g, b);
    actor->GetProperty()->SetDiffuse(.8);
    actor->GetProperty()->SetSpecular(.5);
    actor->GetProperty()->SetSpecularColor(1.0, 1.0, 1.0);
    actor->GetProperty()->SetSpecularPower(30.0);

    return actor;

}


void setCamera() {
    qDebug() << "setCamera";
    if(renderer == nullptr) {
        qDebug() << "Renderer is nullptr";
        return;
    }

    vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();

    camera->SetFocalPoint(600, 0, 1300);
    camera->SetPosition(700, 2200, 1500);
    camera->Zoom(0.4);
    camera->SetViewUp(0, 0, 1);
    renderer->SetActiveCamera(camera);
}

void setGround() {
    qDebug() << "setGround";
    vtkSmartPointer<vtkActor> ground = vtkSmartPointer<vtkActor>::New();
    vtkSmartPointer<vtkPlaneSource> ground_plane = vtkSmartPointer<vtkPlaneSource>::New();

    ground_plane->SetXResolution(50);
    ground_plane->SetYResolution(50);
    ground_plane->SetCenter(0, 0, 0);
    ground_plane->SetNormal(0, 0, 1);

    vtkSmartPointer<vtkPolyDataMapper> ground_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    ground_mapper->SetInputConnection(ground_plane->GetOutputPort());
    ground->SetMapper(ground_mapper);
    ground->GetProperty()->SetRepresentationToWireframe();
    vtkSmartPointer<vtkTransform> ground_transform = vtkSmartPointer<vtkTransform>::New();
    ground_transform->Scale(4000, 4000, 1);
    ground->SetUserTransform(ground_transform);

    renderer->AddActor(ground);

}

void setAxes() {
    qDebug() << "setAxes";
    if(renderer == nullptr) {
        qDebug() << "Renderer is nullptr";
        return;
    }

    vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
    axes->SetTotalLength(1000, 1000, 1200); //  # Set the total length of the axes in 3 dimensions
    axes->SetShaftType(1);
    axes->SetCylinderRadius(0.02);
    axes->GetXAxisCaptionActor2D()->SetWidth(0.04);
    axes->GetYAxisCaptionActor2D()->SetWidth(0.04);
    axes->GetZAxisCaptionActor2D()->SetWidth(0.04);

    renderer->AddActor(axes);
}

void valueChanged1(double value) {
    assembly[1]->SetOrientation(0, 0, -value);
    renWin->Render();
}

void valueChanged2(double value) {
    assembly[2]->SetOrientation(0, -value, 0);
    renWin->Render();
}

运行效果

arm_control_1.png
arm_control_2.png

源码

coding

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容