VTK用滑鼠畫線+VTK座標轉換問題+例項
阿新 • • 發佈:2019-02-07
本人在用VTK實現在渲染視窗上用滑鼠畫線的探究過程。
要在視窗上用滑鼠畫線首先要做的就是重寫滑鼠互動事件,於是就在官方網站找到重寫滑鼠響應事件的demo,然後再更改官方的demo,實現自己需要的功能。我的想法是:
1.獲取滑鼠左鍵按下時的座標。
2.獲取滑鼠左鍵上彈時的座標。
3.用這兩個點連線一條線。
遇到的問題時,智慧獲取到相對於視窗的座標點,而不是世界相對世界座標的座標點。導致的結果就是畫線的位置並不是滑鼠左鍵按下和上彈的連線。
在VS下實現的程式碼如下(沒有用cmake管理,直接在vs下做的):
包含一些我在實現的過程中除錯的過程,已經註釋:
#include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkRenderer.h> #include <vtkSphereSource.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkSmartPointer.h> #include <vtkPointPicker.h> #include <vtkCamera.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkNamedColors.h> #include <vtkObjectFactory.h> #include<vtkLine.h> #include<vtkProperty.h> #include<vtkPolyLine.h> #include<vtkUnstructuredGrid.h> #include<vtkDataSetMapper.h> #include<vtkLineSource.h> #include<vtkRendererCollection.h> #include<vtkCellPicker.h> #include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2 VTK_MODULE_INIT(vtkInteractionStyle); // Define interaction style vtkSmartPointer<vtkRenderer> renderer; double point1[3]{ 0 }; double point2[3]{ 0 }; double WorldPoint[3]{ 0 }; double WorldPoint1[3]{ 0 }; int *clickPos; int *clickPos1; class customMouseInteractorStyle : public vtkInteractorStyleTrackballCamera { public: static customMouseInteractorStyle* New(); vtkTypeMacro(customMouseInteractorStyle, vtkInteractorStyleTrackballCamera); virtual void OnLeftButtonDown() { std::cout << "Pressed left mouse button." << std::endl; // Forward events // vtkInteractorStyleTrackballCamera::OnLeftButtonDown(); // int* clickPos = this->GetInteractor()->GetEventPosition(); clickPos = this->GetInteractor()->GetEventPosition(); point1[0] = clickPos[0]; point1[1] = clickPos[1]; renderer->SetDisplayPoint(point1[0], point1[1], 0); renderer->DisplayToWorld(); WorldPoint[0] = (renderer->GetWorldPoint())[0]; WorldPoint[1] = (renderer->GetWorldPoint())[1]; WorldPoint[2] = (renderer->GetWorldPoint())[2]; // double* worldPosition = picker->GetPickPosition(); // std::cout << worldPosition[0] << "\t" << worldPosition[1] << std::endl; // std::cout << WorldPoint[0]<< std::endl << WorldPoint[1]<< std::endl; } virtual void OnLeftButtonUp() { std::cout << "Pressed left mouse up." << std::endl; vtkIdType pts[2]{ 0,1 }; // Forward events // vtkInteractorStyleTrackballCamera::OnLeftButtonDown(); // int* clickPos = this->GetInteractor()->GetEventPosition(); clickPos1 = this->GetInteractor()->GetEventPosition(); point2[0] = clickPos1[0]; point2[1] = clickPos1[1]; // std::cout << clickPos[0] << std::endl << clickPos[1] << std::endl << std::endl ; std::cout << point1[0] << std::endl << point1[1] << std::endl; std::cout << clickPos1[0] << std::endl << clickPos1[1] << std::endl ; renderer->SetDisplayPoint(point2[0], point2[1], 0); renderer->DisplayToWorld(); WorldPoint1[0] = (renderer->GetWorldPoint())[0]; WorldPoint1[1] = (renderer->GetWorldPoint())[1]; WorldPoint1[2] = (renderer->GetWorldPoint())[2]; ////one way //renderer->SetDisplayPoint(point1); //renderer->SetDisplayPoint(point2); //renderer->DisplayToWorld(); //vtkSmartPointer<vtkPoints>points = vtkSmartPointer<vtkPoints>::New(); //points->InsertNextPoint(point1[0], point1[1], 0); //points->InsertNextPoint(clickPos1[0], clickPos1[1], 0); //vtkSmartPointer<vtkPolyLine>polyline = vtkSmartPointer<vtkPolyLine>::New(); //polyline->GetPointIds()->SetNumberOfIds(2); //polyline->GetPointIds()->SetId(0, 0); //polyline->GetPointIds()->SetId(1, 1); //vtkSmartPointer<vtkUnstructuredGrid>grid= vtkSmartPointer<vtkUnstructuredGrid>::New(); //grid->Allocate(1, 1); //grid->InsertNextCell(polyline->GetCellType(), polyline->GetPointIds()); //grid->SetPoints(points); //vtkSmartPointer<vtkDataSetMapper>mapper= vtkSmartPointer<vtkDataSetMapper>::New(); //mapper->SetInputData(grid); //vtkSmartPointer<vtkActor> actor1 = vtkSmartPointer<vtkActor>::New(); //actor1->SetMapper(mapper); //actor1->GetProperty()->SetColor(1.0, 0.0, 0.0); //設定顏色 // //renderer->AddActor(actor1); // //renderer->GetRenderWindow()->GetInteractor()->Initialize(); //renderer->GetRenderWindow()->GetInteractor()->Render(); // renderer->GetRenderWindow()->Start(); ////the second way // double* p = renderer->GetActors()->GetLastActor()->GetOrigin(); vtkSmartPointer<vtkLineSource> lineSource = vtkSmartPointer<vtkLineSource>::New(); lineSource->SetPoint1(WorldPoint); lineSource->SetPoint2(WorldPoint1); vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(lineSource->GetOutputPort()); vtkSmartPointer<vtkActor> actor1 = vtkSmartPointer<vtkActor>::New(); actor1->SetMapper(mapper); actor1->GetProperty()->SetColor(1.0, 0.0, 0.0); // actor1->SetOrigin(0, 0,0); this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(actor1); renderer->GetRenderWindow()->GetInteractor()->Initialize(); renderer->GetRenderWindow()->GetInteractor()->Render(); // vtkSmartPointer<vtkCellArray>lines = vtkSmartPointer<vtkCellArray>::New(); //// lines->InsertNextCell(2); // lines->InsertNextCell(2, pts); // vtkSmartPointer<vtkPolyData>polydata = vtkSmartPointer<vtkPolyData>::New(); // polydata->SetPoints(points); // polydata->SetPolys(lines); // vtkSmartPointer<vtkPolyDataMapper>linemapper = vtkSmartPointer<vtkPolyDataMapper>::New(); // linemapper->SetInputData(polydata); //測試劃線 // vtkSmartPointer<vtkProperty>linepro = vtkSmartPointer<vtkProperty>::New(); // // linepro->SetColor(0, 0, 0); // linepro->SetOpacity(1); //透明度 // vtkSmartPointer<vtkActor>lineact = vtkSmartPointer<vtkActor>::New(); // lineact->SetMapper(linemapper); // lineact->SetProperty(linepro); // // renderer->AddActor(lineact); // renderer->GetRenderWindow()->Start(); /*vtkSmartPointer<vtkRenderer>render = vtkSmartPointer<vtkRenderer>::New(); render->AddActor(lineact); vtkSmartPointer<vtkRenderWindow>renwin = vtkSmartPointer<vtkRenderWindow>::New(); renwin->AddRenderer(render); vtkSmartPointer<vtkRenderWindowInteractor>iren = vtkSmartPointer<vtkRenderWindowInteractor>::New(); iren->SetRenderWindow(renwin); iren->Initialize(); iren->Start();*/ // renderer->Render(); } virtual void OnMiddleButtonDown() { std::cout << "Pressed middle mouse button." << std::endl; // Forward events vtkInteractorStyleTrackballCamera::OnMiddleButtonDown(); } virtual void OnRightButtonDown() { std::cout << "Pressed right mouse button." << std::endl; // Forward events vtkInteractorStyleTrackballCamera::OnRightButtonDown(); } }; vtkStandardNewMacro(customMouseInteractorStyle); int main(int, char *[]) { vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New(); sphereSource->SetCenter(0.0, 0.0, 0.0); sphereSource->SetRadius(5.0); sphereSource->Update(); vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(sphereSource->GetOutputPort()); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); vtkSmartPointer<vtkNamedColors> colors = vtkSmartPointer<vtkNamedColors>::New(); renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->SetBackground(colors->GetColor3d("Slate_grey").GetData()); renderer->AddActor(actor); vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); renderWindowInteractor->SetRenderWindow(renderWindow); vtkSmartPointer<customMouseInteractorStyle> style = vtkSmartPointer<customMouseInteractorStyle>::New(); renderWindowInteractor->SetInteractorStyle(style); renderWindowInteractor->Initialize(); renderWindowInteractor->Start(); return EXIT_SUCCESS; }
結果如下:
關於座標系的理論就不說了,大家都有買書,書上都有示意圖,只是書上可能沒有這樣的例項。
參考:
這個bug搞了兩天,希望可以幫到遇到同樣問題的人,節約時間,少走一點彎路。