VTK_Learning_交互部件_測量類Widget的應用

1.與測量類相關的主要Widget

與測量類相關的主要Widget如下:

  • vtkDistanceWidget:用於在二維平面上測量兩點之間的距離。
  • vtkAngleWidget:用於在平面的角度測量。
  • vtkBiDimensionalWidget:用於測量二維平面上任意兩個正交方向的軸長。

 2.創建用於測量距離的Widget應用實例

先複習一下創建Widget的一般步驟:
1.實例化Widget;
2.指定渲染窗口交互器。Widget可以通過它來監聽用戶事件。
3.必要時使用觀察者/命令模式創建回調函數。與widget交互時,它會調用一些通用的VTK事件(94個事件列表),如StartInteractionEvent、InteractionEvent、EndInteractionEvent。用戶通過監聽這些事件並作出響應,從而可以更新數據、可視化參數或者應用程序的用戶圖形界面。
4.創建合適幾何表達實體。用SetRepresentation()函數把他與Widget關聯起來,或者使用Widget默認的幾何表達實體。
5.最後,必須激活Widget,使其在渲染場景中顯示。默認情況下,按鍵<I>用於激活Widget,使其在場景中可見。
實例代碼如下:
 

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
 
#include <vtkCommand.h>
#include <vtkSmartPointer.h>
#include <vtkJPEGReader.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
 
#include <vtkDistanceWidget.h>
#include <vtkDistanceRepresentation.h>
#include <vtkAngleWidget.h>
#include <vtkProperty2D.h>
#include <vtkLeaderActor2D.h>
#include <vtkAngleRepresentation2D.h>
#include <vtkBiDimensionalWidget.h>
#include <vtkBiDimensionalRepresentation2D.h>
 
 
class vtkBiDimensionalCallback: public vtkCommand
{
public:
	static	vtkBiDimensionalCallback*  New()
	{
		return new vtkBiDimensionalCallback;
	}
 
	virtual void Execute(vtkObject* caller, unsigned long, void*)
	{
		vtkBiDimensionalWidget* biDimensionalWidget =
			reinterpret_cast<vtkBiDimensionalWidget*> (caller);
		vtkBiDimensionalRepresentation2D* representation =
			static_cast<vtkBiDimensionalRepresentation2D*> (biDimensionalWidget->GetRepresentation());
		double p1[3];
		representation->GetPoint1DisplayPosition(p1);
		double p2[3];
		representation->GetPoint1DisplayPosition(p2);
		double p3[3];
		representation->GetPoint1DisplayPosition(p3);
		double p4[3];
		representation->GetPoint1DisplayPosition(p4);
		//顯示其中一個點的屏幕座標(px)
		std::cout << "P1: " << p1[0] << " " << p1[1] << " " << p1[2] << std::endl;
	}
	vtkBiDimensionalCallback() { }
};
int main()
{
	int WidgetType;
	std::cout << "Please select the Measurement Distance WidgetType: " << std::endl;
	std::cin >> WidgetType;
 
	vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
	reader->SetFileName("vtk.jpg");
	reader->Update();
 
	vtkSmartPointer<vtkImageActor> imgActor = vtkSmartPointer<vtkImageActor>::New();
	imgActor->SetInputData(reader->GetOutput());
 
	vtkSmartPointer<vtkRenderer> render = vtkSmartPointer<vtkRenderer>::New();
	render->AddActor(imgActor);
	render->SetBackground(0, 0, 0);
	render->ResetCamera();
 
	vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
	rw->AddRenderer(render);
	rw->SetWindowName("MeasurementDistanceApp");
	rw->SetSize(320, 320);
	rw->Render();
 
	vtkSmartPointer<vtkRenderWindowInteractor> rwi =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	rwi->SetRenderWindow(rw);
 
	vtkSmartPointer<vtkInteractorStyleImage> style = 
		vtkSmartPointer<vtkInteractorStyleImage>::New();
	rwi->SetInteractorStyle(style);
/****************************************************************/
	//vtkDistanceWidget
	if (WidgetType == 0)
	{
		//實例化Widget
		vtkSmartPointer<vtkDistanceWidget> distanceWidget =
			vtkSmartPointer<vtkDistanceWidget>::New();
		//指定渲染窗口交互器,來監聽用戶事件
		distanceWidget->SetInteractor(rwi);
		//必要時使用觀察者/命令模式創建回調函數(此處沒用)
		//創建幾何表達實體。用SetRepresentation()把事件與Widget關聯起來
		//或者使用Widget默認的幾何表達實體
		distanceWidget->CreateDefaultRepresentation();
		static_cast<vtkDistanceRepresentation*> (distanceWidget->GetRepresentation())
			->SetLabelFormat("%-#6.3g px");
		//激活Widget
		distanceWidget->On();
		
		rw->Render();
		rwi->Initialize();
		rwi->Start();
	}
	//vtkAngleWidget
	if (WidgetType == 1)
	{
		vtkSmartPointer<vtkAngleWidget> angleWiget = vtkSmartPointer<vtkAngleWidget>::New();
		angleWiget->SetInteractor(rwi);
		//創建個性化的實體圖標
		vtkSmartPointer<vtkAngleRepresentation2D> angleRep =
			vtkSmartPointer<vtkAngleRepresentation2D>::New();
		angleRep->GetRay1()->GetProperty()->SetColor(0, 1, 0);
		angleRep->GetRay1()->GetProperty()->SetLineWidth(3);
		angleRep->GetRay2()->GetProperty()->SetColor(0, 1, 0);
		angleRep->GetRay1()->GetProperty()->SetLineWidth(3);
		angleRep->GetArc()->GetProperty()->SetColor(0, 1, 0);
		angleRep->GetArc()->GetProperty()->SetLineWidth(3);
		angleWiget->SetRepresentation(angleRep);
		angleWiget->On();
 
		rw->Render();
		rwi->Initialize();
		rwi->Start();
	}
	//vtkBiDimensionalWidget
	if (WidgetType == 2)
	{
		vtkSmartPointer<vtkBiDimensionalWidget> bidimensionalWidget =
			vtkSmartPointer<vtkBiDimensionalWidget>::New();
		bidimensionalWidget->SetInteractor(rwi);
		//採用默認的圖標
		bidimensionalWidget->CreateDefaultRepresentation();
		//添加“觀察者-命令模式(命令子類方案)”
		vtkSmartPointer<vtkBiDimensionalCallback> bidiCallback =
			vtkSmartPointer<vtkBiDimensionalCallback>::New();
		bidimensionalWidget->AddObserver(vtkCommand::InteractionEvent, bidiCallback);
		bidimensionalWidget->On();
 
		rw->Render();
		rwi->Initialize();
		rwi->Start();
	}
	return 0;
}

輸出結果如下所示:

上面的例子中,使用了vtkDistanceWidget類來做二維空間的距離測量。先是實例化一個vtkDistanceWidget對象實例,然後調用該類的SetInteractor()函數來設置渲染窗口交互器;接着調用CreatDefaultRepresentation()函數來創建默認的幾何表達實體,急用十字形表示兩個端點來,端點之間使用帶有刻度的直線連接。需要注意的是,在程序調用SetLabelFormat()函數來設置兩點之間所測距離的文本表示格式;最後調用On()函數來激活vtkDistanceWidget實例。

角度測量的vtkAngleWidget以及二維正交方向長度測量的vtkBiDimensionalWidget的使用方法與vtkDistanceWidget類似,他們的二維幾何表達形式所所對應的類爲vtkAngleRepresentation2D和vtkBiDimensionalRepresentation2D.
 

 3.額外補充的C++基礎

3.1 reinterpret_cast

reinterpret_cast是強制類型轉換符!他是用來處理無關類型轉換的,通常爲操作數的位模式提供較低層次的重新解釋!但是他僅僅是重新解釋了給出的對象的比特模型,並沒有進行二進制的轉換!
他是用在任意的指針之間的轉換,引用之間的轉換,指針和足夠大的int型之間的轉換,整數到指針的轉換。
 

int *pi;  
char *pc = reinterpret_cast<char*>(pi);  

3.2 static_cast

《C++primer 第四版》中說編譯器隱式執行的任何類型轉換都可以由static_cast顯式完成!
要注意的是,此轉換沒有運行時檢測安全!他不能轉換掉expression的const、volatile、或者__unaligned屬性。他也不是用來去掉static屬性的! 大家應該清楚static限定符吧,他會造成範圍性的影響,而const則不同,他只是限定變量或對象自身!
當使用static限定符限定一個變量的時候,就拿類中吧,他會隨類的第一個實例對象的出現而出現,並且可以被這個類的所有對象所使用!!
C++中的static_cast執行非多態的轉換,用於代替C中通常的轉換操作。
對於我們的static_cast轉換符,他不僅可以應用到指針和引用上,而且還可以應用到基礎數據結構和對象上!
 

double da = 1.1;  
void *pa = &da;  
double *dp = static_cast<double*>(pa);  
int ia = static_cast<int>(da);  
  
cout << *dp << endl;  
cout << ia << endl;  

OK,代碼編譯通過!
《C++primer》告訴我們,對於一個由較大的算術類型到一個較小的類型的賦值,編譯器通常會報錯,然後當我們顯示地提供強制類型轉換的時候,警告信息就關閉了!
要知道我們的static_cast的真正用處不是在指針的引用上,而是在基礎類型的轉換和對象的轉換上!
static_cast也支持指向基類的指針和指向子類的指針之間的轉換!
但是在這裏要注意的是,我們從基類轉換到子類是一個不安全的行爲!
 

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