スポンサーリンク

VTKでクリックした位置を注視点にする

#include <iostream>

//VTK_MODULE_INITに必要
#include <vtkAutoInit.h>


#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>

//円筒とその表示に必要
#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"psapi.lib")
#pragma comment(lib,"dbghelp.lib")
#pragma comment(lib,"ws2_32.lib")


//必須
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>
#include <vtkPropPicker.h>

#include <vtkAppendPolyData.h>
#include <vtkLineSource.h>
#include <vtkProperty.h>


// 注視点を表示するためのアクタを作成
vtkSmartPointer<vtkActor> Create3DPlusActor(
    double length = 1.0,
    double width = 2.0
);

// マウスイベントをカスタマイズするためのクラス
class MouseInteractorStyle2 : public vtkInteractorStyleTrackballCamera
{
public:

    // 注視点を表示するためのアクタ
    vtkSmartPointer<vtkActor> focal_mark; 

    static MouseInteractorStyle2* New();
    vtkTypeMacro(MouseInteractorStyle2, vtkInteractorStyleTrackballCamera);

    virtual void OnLeftButtonDown()
    {
        int ctrl = this->Interactor->GetControlKey();
        if (ctrl) {

            int* clickPos = this->GetInteractor()->GetEventPosition();

            // ピック下オブジェクトを取得
            auto picker = vtkSmartPointer<vtkPropPicker>::New();
            picker->Pick(clickPos[0], clickPos[1], 0, this->GetDefaultRenderer());

            // オブジェクトがクリックされていたら位置とアドレスを出力
            if (picker->GetActor() != nullptr) {

                double* pos = picker->GetPickPosition();

                auto camera = this->GetDefaultRenderer()->GetActiveCamera();
                camera->SetFocalPoint(pos); // カメラの焦点をクリック位置に設定
                focal_mark->SetPosition(pos); // クリック位置に移動

            }
        }


        // Forward events
        vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
    }

private:

};
vtkStandardNewMacro(MouseInteractorStyle2);



int main(int /*argc*/, char** /*argv*/)
{

    //////////////////////////////////////
    // Create a vtkCylinderSource
    vtkSmartPointer<vtkCylinderSource> cylinderSource = vtkSmartPointer<vtkCylinderSource>::New();
    cylinderSource->SetCenter(0.0, 0.0, 0.0);
    cylinderSource->SetRadius(5.0);
    cylinderSource->SetHeight(7.0);
    cylinderSource->SetResolution(100);

    //////////////////////////////////////
    // Create a mapper and actor
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(cylinderSource->GetOutputPort());
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    //////////////////////////////////////
    auto renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(actor);
    renderer->ResetCamera();




    //////////////////////////////////////
    auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();

    //////////////////////////////////////
    auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    renderWindow->SetInteractor(interactor);
    renderWindow->Render();

    //////////////////////////////////////
    // マウスイベントを設定.
    auto style = vtkSmartPointer<MouseInteractorStyle2>::New();
    style->SetDefaultRenderer(renderer);
    interactor->SetInteractorStyle(style);
    //////////////////////////////////////
    vtkCamera* cam = renderer->GetActiveCamera();
    double focal[3];
    cam->GetFocalPoint(focal);
    auto axes = Create3DPlusActor(1, 1);
    axes->SetPosition(focal);
    renderer->AddActor(axes); // 軸をレンダラーに追加
    style->focal_mark = axes;
    //////////////////////////////////////

    interactor->Start(); //イベントループへ入る

    return 0;
}



// 線分の長さ、太さ、色を指定できる
vtkSmartPointer<vtkActor> Create3DPlusActor(
    double length,
    double width
) {
    double center[3]= { 0.0, 0.0, 0.0 };
    double color[3] = { 1.0, 1.0, 1.0 };

    // 各軸の線分を作成
    auto appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();

    // x軸の線
    auto xLine = vtkSmartPointer<vtkLineSource>::New();
    xLine->SetPoint1(center[0] - length / 2.0, center[1], center[2]);
    xLine->SetPoint2(center[0] + length / 2.0, center[1], center[2]);
    xLine->Update();
    appendFilter->AddInputData(xLine->GetOutput());



    // y軸の線
    auto yLine = vtkSmartPointer<vtkLineSource>::New();
    yLine->SetPoint1(center[0], center[1] - length / 2.0, center[2]);
    yLine->SetPoint2(center[0], center[1] + length / 2.0, center[2]);
    yLine->Update();
    appendFilter->AddInputData(yLine->GetOutput());

    // z軸の線
    auto zLine = vtkSmartPointer<vtkLineSource>::New();
    zLine->SetPoint1(center[0], center[1], center[2] - length / 2.0);
    zLine->SetPoint2(center[0], center[1], center[2] + length / 2.0);
    zLine->Update();
    appendFilter->AddInputData(zLine->GetOutput());

    appendFilter->Update();

    // マッパーとアクター
    auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(appendFilter->GetOutputPort());

    auto actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);
    actor->GetProperty()->SetLineWidth(width);
    actor->GetProperty()->SetColor(color);

    return actor;
}

昔書いた内容かどうか思い出せない。コードを書いた記憶はあるが記事が見つからなかった。

やったことはあるかもしれないが、きっと当時よりはよいコードになっている。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: