vtkBoxWidget.cxx 源代码学习

看源代码能学到很多东西。。。。。


/*=========================================================================
Program:   Visualization Toolkit
Module:    vtkBoxWidget.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notice for more information.
=========================================================================*/
#include "vtkBoxWidget.h"

#include "vtkActor.h"
#include "vtkAssemblyNode.h"
#include "vtkAssemblyPath.h"
#include "vtkCallbackCommand.h"
#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkCellPicker.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPickingManager.h"
#include "vtkPlanes.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkSphereSource.h"
#include "vtkTransform.h"

vtkStandardNewMacro(vtkBoxWidget);

vtkBoxWidget::vtkBoxWidget()
{
	this->State = vtkBoxWidget::Start;
	this->EventCallbackCommand->SetCallback(vtkBoxWidget::ProcessEvents);

	// Enable/disable the translation, rotation, and scaling of the widget
	this->TranslationEnabled = 1;
	this->RotationEnabled = 1;
	this->ScalingEnabled = 1;

	//Build the representation of the widget
	int i;

	// Control orientation of normals
	this->InsideOut = 0;
	this->OutlineFaceWires = 0;
	this->OutlineCursorWires = 1;

	// Construct the poly data representing the hex
	this->HexPolyData = vtkPolyData::New();
	this->HexMapper = vtkPolyDataMapper::New();
	this->HexMapper->SetInputData(HexPolyData);
	this->HexActor = vtkActor::New();
	this->HexActor->SetMapper(this->HexMapper);

	// Construct initial points
	this->Points = vtkPoints::New(VTK_DOUBLE);
	this->Points->SetNumberOfPoints(15);//8 corners; 6 faces; 1 center
	this->HexPolyData->SetPoints(this->Points);

	// Construct connectivity for the faces. These are used to perform
	// the picking.
	vtkIdType pts[4];
	vtkCellArray *cells = vtkCellArray::New();
	cells->Allocate(cells->EstimateSize(6,4));
	pts[0] = 3; pts[1] = 0; pts[2] = 4; pts[3] = 7;
	cells->InsertNextCell(4,pts);
	pts[0] = 1; pts[1] = 2; pts[2] = 6; pts[3] = 5;
	cells->InsertNextCell(4,pts);
	pts[0] = 0; pts[1] = 1; pts[2] = 5; pts[3] = 4;
	cells->InsertNextCell(4,pts);
	pts[0] = 2; pts[1] = 3; pts[2] = 7; pts[3] = 6;
	cells->InsertNextCell(4,pts);
	pts[0] = 0; pts[1] = 3; pts[2] = 2; pts[3] = 1;
	cells->InsertNextCell(4,pts);
	pts[0] = 4; pts[1] = 5; pts[2] = 6; pts[3] = 7;
	cells->InsertNextCell(4,pts);
	this->HexPolyData->SetPolys(cells);
	cells->Delete();
	this->HexPolyData->BuildCells();

	// The face of the hexahedra 
	cells = vtkCellArray::New();
	cells->Allocate(cells->EstimateSize(1,4));
	cells->InsertNextCell(4,pts); //temporary, replaced later  六面体的顶面
	this->HexFacePolyData = vtkPolyData::New();
	this->HexFacePolyData->SetPoints(this->Points);
	this->HexFacePolyData->SetPolys(cells);
	this->HexFaceMapper = vtkPolyDataMapper::New();
	this->HexFaceMapper->SetInputData(HexFacePolyData);
	this->HexFace = vtkActor::New();
	this->HexFace->SetMapper(this->HexFaceMapper);
	cells->Delete();

	// Create the outline for the hex
	this->OutlinePolyData = vtkPolyData::New();
	this->OutlinePolyData->SetPoints(this->Points);
	this->OutlineMapper = vtkPolyDataMapper::New();
	this->OutlineMapper->SetInputData(this->OutlinePolyData);
	this->HexOutline = vtkActor::New();
	this->HexOutline->SetMapper(this->OutlineMapper);
	cells = vtkCellArray::New();
	cells->Allocate(cells->EstimateSize(15,2));
	this->OutlinePolyData->SetLines(cells);
	cells->Delete();

	// Set up the initial properties
	this->CreateDefaultProperties();

	// Create the outline
	this->GenerateOutline();

	// Create the handles
	this->Handle = new vtkActor* [7];
	this->HandleMapper = new vtkPolyDataMapper* [7];
	this->HandleGeometry = new vtkSphereSource* [7];
	for (i=0; i<7; i++)
	{
		this->HandleGeometry[i] = vtkSphereSource::New();
		this->HandleGeometry[i]->SetThetaResolution(16);
		this->HandleGeometry[i]->SetPhiResolution(8);
		this->HandleMapper[i] = vtkPolyDataMapper::New();
		this->HandleMapper[i]->SetInputConnection(
			this->HandleGeometry[i]->GetOutputPort());
		this->Handle[i] = vtkActor::New();
		this->Handle[i]->SetMapper(this->HandleMapper[i]);
	}

	// Define the point coordinates
	double bounds[6];
	bounds[0] = -0.5;
	bounds[1] = 0.5;
	bounds[2] = -0.5;
	bounds[3] = 0.5;
	bounds[4] = -0.5;
	bounds[5] = 0.5;
	// Points 8-14 are down by PositionHandles();
	this->PlaceWidget(bounds);

	//Manage the picking stuff
	this->HandlePicker = vtkCellPicker::New();
	this->HandlePicker->SetTolerance(0.001);
	for (i=0; i<7; i++)
	{
		this->HandlePicker->AddPickList(this->Handle[i]);
	}
	this->HandlePicker->PickFromListOn();

	this->HexPicker = vtkCellPicker::New();
	this->HexPicker->SetTolerance(0.001);
	this->HexPicker->AddPickList(HexActor);
	this->HexPicker->PickFromListOn();

	this->CurrentHandle = NULL;

	this->Transform = vtkTransform::New();
}

vtkBoxWidget::~vtkBoxWidget()
{
	this->HexActor->Delete();
	this->HexMapper->Delete();
	this->HexPolyData->Delete();
	this->Points->Delete();

	this->HexFace->Delete();
	this->HexFaceMapper->Delete();
	this->HexFacePolyData->Delete();

	this->HexOutline->Delete();
	this->OutlineMapper->Delete();
	this->OutlinePolyData->Delete();

	for (int i=0; i<7; i++)
	{
		this->HandleGeometry[i]->Delete();
		this->HandleMapper[i]->Delete();
		this->Handle[i]->Delete();
	}
	delete [] this->Handle;
	delete [] this->HandleMapper;
	delete [] this->HandleGeometry;

	this->HandlePicker->Delete();
	this->HexPicker->Delete();

	this->Transform->Delete();

	this->HandleProperty->Delete();
	this->SelectedHandleProperty->Delete();
	this->FaceProperty->Delete();
	this->SelectedFaceProperty->Delete();
	this->OutlineProperty->Delete();
	this->SelectedOutlineProperty->Delete();
}

void vtkBoxWidget::SetEnabled(int enabling)
{
	if ( ! this->Interactor )
	{
		vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
		return;
	}

	if ( enabling ) //------------------------------------------------------------
	{
		vtkDebugMacro(<<"Enabling widget");

		if ( this->Enabled ) //already enabled, just return
		{
			return;
		}

		if ( ! this->CurrentRenderer )
		{
			this->SetCurrentRenderer(this->Interactor->FindPokedRenderer(
				this->Interactor->GetLastEventPosition()[0],
				this->Interactor->GetLastEventPosition()[1]));
			if (this->CurrentRenderer == NULL)
			{
				return;
			}
		}

		this->Enabled = 1;

		// listen to the following events
		vtkRenderWindowInteractor *i = this->Interactor;
		i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand,
			this->Priority);
		i->AddObserver(vtkCommand::LeftButtonPressEvent,
			this->EventCallbackCommand, this->Priority);
		i->AddObserver(vtkCommand::LeftButtonReleaseEvent,
			this->EventCallbackCommand, this->Priority);
		i->AddObserver(vtkCommand::MiddleButtonPressEvent,
			this->EventCallbackCommand, this->Priority);
		i->AddObserver(vtkCommand::MiddleButtonReleaseEvent,
			this->EventCallbackCommand, this->Priority);
		i->AddObserver(vtkCommand::RightButtonPressEvent,
			this->EventCallbackCommand, this->Priority);
		i->AddObserver(vtkCommand::RightButtonReleaseEvent,
			this->EventCallbackCommand, this->Priority);

		// Add the various actors
		// Add the outline
		this->CurrentRenderer->AddActor(this->HexActor);
		this->CurrentRenderer->AddActor(this->HexOutline);
		this->HexActor->SetProperty(this->OutlineProperty);
		this->HexOutline->SetProperty(this->OutlineProperty);

		// Add the hex face
		this->CurrentRenderer->AddActor(this->HexFace);
		this->HexFace->SetProperty(this->FaceProperty);

		// turn on the handles
		for (int j=0; j<7; j++)
		{
			this->CurrentRenderer->AddActor(this->Handle[j]);
			this->Handle[j]->SetProperty(this->HandleProperty);
		}

		this->InvokeEvent(vtkCommand::EnableEvent,NULL);
	}

	else //disabling-------------------------------------------------------------
	{
		vtkDebugMacro(<<"Disabling widget");

		if ( ! this->Enabled ) //already disabled, just return
		{
			return;
		}

		this->Enabled = 0;

		// don't listen for events any more
		this->Interactor->RemoveObserver(this->EventCallbackCommand);

		// turn off the outline
		this->CurrentRenderer->RemoveActor(this->HexActor);
		this->CurrentRenderer->RemoveActor(this->HexOutline);

		// turn off the hex face
		this->CurrentRenderer->RemoveActor(this->HexFace);

		// turn off the handles
		for (int i=0; i<7; i++)
		{
			this->CurrentRenderer->RemoveActor(this->Handle[i]);
		}

		this->CurrentHandle = NULL;
		this->InvokeEvent(vtkCommand::DisableEvent,NULL);
		this->SetCurrentRenderer(NULL);
	}

	this->Interactor->Render();
}
// Handles the events 对应初始化过程中监听的事件
void vtkBoxWidget::ProcessEvents(vtkObject* vtkNotUsed(object),
	unsigned long event,
	void* clientdata,
	void* vtkNotUsed(calldata))
{
	vtkBoxWidget* self = reinterpret_cast<vtkBoxWidget *>( clientdata );

	//okay, let's do the right thing
	switch(event)
	{
	case vtkCommand::LeftButtonPressEvent:
		self->OnLeftButtonDown();
		break;
	case vtkCommand::LeftButtonReleaseEvent:
		self->OnLeftButtonUp();
		break;
	case vtkCommand::MiddleButtonPressEvent:
		self->OnMiddleButtonDown();
		break;
	case vtkCommand::MiddleButtonReleaseEvent:
		self->OnMiddleButtonUp();
		break;
	case vtkCommand::RightButtonPressEvent:
		self->OnRightButtonDown();
		break;
	case vtkCommand::RightButtonReleaseEvent:
		self->OnRightButtonUp();
		break;
	case vtkCommand::MouseMoveEvent:
		self->OnMouseMove();
		break;
	}
}

void vtkBoxWidget::PrintSelf(ostream& os, vtkIndent indent)
{
	this->Superclass::PrintSelf(os,indent);

	double *bounds=this->InitialBounds;
	os << indent << "Initial Bounds: "
		<< "(" << bounds[0] << "," << bounds[1] << ") "
		<< "(" << bounds[2] << "," << bounds[3] << ") "
		<< "(" << bounds[4] << "," << bounds[5] << ")\n";

	if ( this->HandleProperty )
	{
		os << indent << "Handle Property: " << this->HandleProperty << "\n";
	}
	else
	{
		os << indent << "Handle Property: (none)\n";
	}
	if ( this->SelectedHandleProperty )
	{
		os << indent << "Selected Handle Property: "
			<< this->SelectedHandleProperty << "\n";
	}
	else
	{
		os << indent << "SelectedHandle Property: (none)\n";
	}

	if ( this->FaceProperty )
	{
		os << indent << "Face Property: " << this->FaceProperty << "\n";
	}
	else
	{
		os << indent << "Face Property: (none)\n";
	}
	if ( this->SelectedFaceProperty )
	{
		os << indent << "Selected Face Property: "
			<< this->SelectedFaceProperty << "\n";
	}
	else
	{
		os << indent << "Selected Face Property: (none)\n";
	}

	if ( this->OutlineProperty )
	{
		os << indent << "Outline Property: " << this->OutlineProperty << "\n";
	}
	else
	{
		os << indent << "Outline Property: (none)\n";
	}
	if ( this->SelectedOutlineProperty )
	{
		os << indent << "Selected Outline Property: "
			<< this->SelectedOutlineProperty << "\n";
	}
	else
	{
		os << indent << "Selected Outline Property: (none)\n";
	}

	os << indent << "Outline Face Wires: " << (this->OutlineFaceWires ? "On\n" : "Off\n");
	os << indent << "Outline Cursor Wires: " << (this->OutlineCursorWires ? "On\n" : "Off\n");
	os << indent << "Inside Out: " << (this->InsideOut ? "On\n" : "Off\n");
	os << indent << "Translation Enabled: " << (this->TranslationEnabled ? "On\n" : "Off\n");
	os << indent << "Scaling Enabled: " << (this->ScalingEnabled ? "On\n" : "Off\n");
	os << indent << "Rotation Enabled: " << (this->RotationEnabled ? "On\n" : "Off\n");

}

#define VTK_AVERAGE(a,b,c) \
	c[0] = (a[0] + b[0])/2.0; \
	c[1] = (a[1] + b[1])/2.0; \
	c[2] = (a[2] + b[2])/2.0;

/************************************************************************/
/* 更新六个点的中心/句柄,其他相关数据的更新【个人感觉这个代码非常棒,组织、结构】 */
/************************************************************************/
void vtkBoxWidget::PositionHandles()
{
	// 六面体的8个顶点的坐标
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);
	double *p0 = pts;
	double *p1 = pts + 3*1;
	double *p2 = pts + 3*2;
	double *p3 = pts + 3*3;
	//double *p4 = pts + 3*4;
	double *p5 = pts + 3*5;
	double *p6 = pts + 3*6;
	double *p7 = pts + 3*7;
	double x[3];
	// 每个面的中心, 下标: 8 - 14
	VTK_AVERAGE(p0,p7,x);
	this->Points->SetPoint(8, x);
	VTK_AVERAGE(p1,p6,x);
	this->Points->SetPoint(9, x);
	VTK_AVERAGE(p0,p5,x);
	this->Points->SetPoint(10, x);
	VTK_AVERAGE(p2,p7,x);
	this->Points->SetPoint(11, x);
	VTK_AVERAGE(p1,p3,x);
	this->Points->SetPoint(12, x);
	VTK_AVERAGE(p5,p7,x);
	this->Points->SetPoint(13, x);
	VTK_AVERAGE(p0,p6,x);
	this->Points->SetPoint(14, x);

	int i;
	for (i = 0; i < 7; ++i)
	{
		this->HandleGeometry[i]->SetCenter(this->Points->GetPoint(8+i));
	}
	// 更新数据
	this->Points->GetData()->Modified();
	this->HexFacePolyData->Modified();
	this->HexPolyData->Modified();
	this->GenerateOutline();
}
#undef VTK_AVERAGE

// 句柄可见
void vtkBoxWidget::HandlesOn()
{
	for (int i=0; i<7; i++)
	{
		this->Handle[i]->VisibilityOn();
	}
}
// 句柄不可见
void vtkBoxWidget::HandlesOff()
{
	for (int i=0; i<7; i++)
	{
		this->Handle[i]->VisibilityOff();
	}
}
// 句柄半径设置
void vtkBoxWidget::SizeHandles()
{
	double radius = this->vtk3DWidget::SizeHandles(1.5);
	for(int i=0; i<7; i++)
	{
		this->HandleGeometry[i]->SetRadius(radius);
	}
}
// 句柄高亮
int vtkBoxWidget::HighlightHandle(vtkProp *prop)
{
	// first unhighlight anything picked
	this->HighlightOutline(0);
	if ( this->CurrentHandle )
	{
		this->CurrentHandle->SetProperty(this->HandleProperty);
	}

	this->CurrentHandle = static_cast<vtkActor *>(prop);

	if ( this->CurrentHandle )
	{
		this->CurrentHandle->SetProperty(this->SelectedHandleProperty);
		for (int i=0; i<6; i++) //find attached face
		{
			if ( this->CurrentHandle == this->Handle[i] )
			{
				return i;
			}
		}
	}

	if ( this->CurrentHandle == this->Handle[6] )
	{
		this->HighlightOutline(1);
	}

	return -1;
}
// 高亮某个面
void vtkBoxWidget::HighlightFace(int cellId)
{
	if ( cellId >= 0 )
	{
		vtkIdType npts;
		vtkIdType *pts;
		vtkCellArray *cells = this->HexFacePolyData->GetPolys();
		this->HexPolyData->GetCellPoints(cellId, npts, pts);
		this->HexFacePolyData->Modified();
		cells->ReplaceCell(0, npts, pts);
		this->CurrentHexFace = cellId;
		this->HexFace->SetProperty(this->SelectedFaceProperty);
		if ( !this->CurrentHandle )
		{
			this->CurrentHandle = this->HexFace;
		}
	}
	else
	{
		this->HexFace->SetProperty(this->FaceProperty);
		this->CurrentHexFace = -1;
	}
}
// 高亮轮廓线和面
void vtkBoxWidget::HighlightOutline(int highlight)
{
	if ( highlight )
	{
		this->HexActor->SetProperty(this->SelectedOutlineProperty);
		this->HexOutline->SetProperty(this->SelectedOutlineProperty);
	}
	else
	{
		this->HexActor->SetProperty(this->OutlineProperty);
		this->HexOutline->SetProperty(this->OutlineProperty);
	}
}

void vtkBoxWidget::OnLeftButtonDown()
{
	int X = this->Interactor->GetEventPosition()[0];
	int Y = this->Interactor->GetEventPosition()[1];

	// Try to pick handles first; if no handles picked, then pick the bounding box.
	if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
	{
		this->State = vtkBoxWidget::Outside;
		return;
	}

	vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker); // Proceed to a pick, whether through the PickingManager if the picking is managed or directly using the picker, and return the assembly path.

	if ( path != NULL )
	{
		// 高亮句柄和面
		this->State = vtkBoxWidget::Moving;
		this->HighlightFace(
			this->HighlightHandle(path->GetFirstNode()->GetViewProp()));
		this->HandlePicker->GetPickPosition(this->LastPickPosition);
		this->ValidPick = 1;
	}
	else
	{
		path = this->GetAssemblyPath(X, Y, 0., this->HexPicker);

		if ( path != NULL )
		{
			this->State = vtkBoxWidget::Moving;
			this->HexPicker->GetPickPosition(this->LastPickPosition);
			this->ValidPick = 1;

			if ( !this->Interactor->GetShiftKey() )
			{	// 没有按 shift 键时,高亮面
				this->HighlightHandle(NULL);
				this->HighlightFace(this->HexPicker->GetCellId());
			}
			else
			{	// 有按 shift 键时,高亮轮廓线;
				this->CurrentHandle = this->Handle[6];
				this->HighlightOutline(1);
			}
		}
		else
		{
			this->HighlightFace(this->HighlightHandle(NULL));
			this->State = vtkBoxWidget::Outside;
			return;
		}
	}

	this->EventCallbackCommand->SetAbortFlag(1);
	this->StartInteraction();
	this->InvokeEvent(vtkCommand::StartInteractionEvent, NULL);
	this->Interactor->Render();
}

void vtkBoxWidget::OnLeftButtonUp()
{
	if ( this->State == vtkBoxWidget::Outside ||
		this->State == vtkBoxWidget::Start )
	{
		return;
	}

	this->State = vtkBoxWidget::Start;
	this->HighlightFace(this->HighlightHandle(NULL)); // 句柄、面的属性恢复原状
	this->SizeHandles();	// 重置句柄大小

	this->EventCallbackCommand->SetAbortFlag(1);  // Set/Get the abort flag. If this is set to true no further commands are executed. 
	this->EndInteraction();
	this->InvokeEvent(vtkCommand::EndInteractionEvent, NULL);
	this->Interactor->Render(); // 渲染场景. 通过渲染唤起相关的 vtkRenderWindow 对象

}

void vtkBoxWidget::OnMiddleButtonDown()
{
	int X = this->Interactor->GetEventPosition()[0];
	int Y = this->Interactor->GetEventPosition()[1];

	// Try to pick handles first; if no handles picked, then pick the bounding box.
	if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
	{
		this->State = vtkBoxWidget::Outside;
		return;
	}

	vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);

	if ( path != NULL )
	{
		// 长按鼠标滚轮: 高亮轮廓线
		this->State = vtkBoxWidget::Moving;
		this->CurrentHandle = this->Handle[6];
		this->HighlightOutline(1);
		this->HandlePicker->GetPickPosition(this->LastPickPosition);
		this->ValidPick = 1;
	}
	else
	{
		path = this->GetAssemblyPath(X, Y, 0., this->HexPicker);

		if ( path != NULL )
		{
			this->State = vtkBoxWidget::Moving;
			this->CurrentHandle = this->Handle[6];
			this->HighlightOutline(1);
			this->HexPicker->GetPickPosition(this->LastPickPosition);
			this->ValidPick = 1;
		}
		else
		{
			this->HighlightFace(this->HighlightHandle(NULL));
			this->State = vtkBoxWidget::Outside;
			return;
		}
	}

	this->EventCallbackCommand->SetAbortFlag(1);
	this->StartInteraction();
	this->InvokeEvent(vtkCommand::StartInteractionEvent, NULL);
	this->Interactor->Render();
}

void vtkBoxWidget::OnMiddleButtonUp()
{
	if ( this->State == vtkBoxWidget::Outside ||
		this->State == vtkBoxWidget::Start )
	{
		return;
	}

	this->State = vtkBoxWidget::Start;
	this->HighlightFace(this->HighlightHandle(NULL));
	this->SizeHandles();

	this->EventCallbackCommand->SetAbortFlag(1);
	this->EndInteraction();
	this->InvokeEvent(vtkCommand::EndInteractionEvent, NULL);
	this->Interactor->Render();

}

void vtkBoxWidget::OnRightButtonDown()
{
	int X = this->Interactor->GetEventPosition()[0];
	int Y = this->Interactor->GetEventPosition()[1];

	// Okay, we can process this. Try to pick handles first;
	// if no handles picked, then pick the bounding box.
	if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
	{
		this->State = vtkBoxWidget::Outside;
		return;
	}

	vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);

	if ( path != NULL )
	{
		this->State = vtkBoxWidget::Scaling;
		this->HighlightOutline(1);
		this->HandlePicker->GetPickPosition(this->LastPickPosition);
		this->ValidPick = 1;
	}
	else
	{
		path = this->GetAssemblyPath(X, Y, 0., this->HexPicker);

		if ( path != NULL )
		{
			this->State = vtkBoxWidget::Scaling;
			this->HighlightOutline(1);
			this->HexPicker->GetPickPosition(this->LastPickPosition);
			this->ValidPick = 1;
		}
		else
		{
			this->State = vtkBoxWidget::Outside;
			return;
		}
	}

	this->EventCallbackCommand->SetAbortFlag(1);
	this->StartInteraction();
	this->InvokeEvent(vtkCommand::StartInteractionEvent, NULL);
	this->Interactor->Render();
}

void vtkBoxWidget::OnRightButtonUp()
{
	if ( this->State == vtkBoxWidget::Outside )
	{
		return;
	}

	this->State = vtkBoxWidget::Start;
	this->HighlightOutline(0);
	this->SizeHandles();

	this->EventCallbackCommand->SetAbortFlag(1);
	this->EndInteraction();
	this->InvokeEvent(vtkCommand::EndInteractionEvent, NULL);
	this->Interactor->Render();
}

void vtkBoxWidget::OnMouseMove()
{
	// See whether we're active
	if ( this->State == vtkBoxWidget::Outside ||
		this->State == vtkBoxWidget::Start )
	{
		return;
	}

	int X = this->Interactor->GetEventPosition()[0];
	int Y = this->Interactor->GetEventPosition()[1];

	// Do different things depending on state
	// Calculations everybody does
	double focalPoint[4], pickPoint[4], prevPickPoint[4];
	double z, vpn[3];

	vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
	if ( !camera )
	{
		return;
	}

	// Compute the two points defining the motion vector
	this->ComputeWorldToDisplay(this->LastPickPosition[0], this->LastPickPosition[1],
		this->LastPickPosition[2], focalPoint);
	z = focalPoint[2];
	this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]),
		double(this->Interactor->GetLastEventPosition()[1]),
		z, prevPickPoint);
	this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);

	// Process the motion
	if ( this->State == vtkBoxWidget::Moving )
	{
		// Okay to process
		if ( this->CurrentHandle )
		{
			if ( this->RotationEnabled && this->CurrentHandle == this->HexFace )
			{
				// 鼠标指向某一面:旋转
				camera->GetViewPlaneNormal(vpn);
				this->Rotate(X, Y, prevPickPoint, pickPoint, vpn);
			}
			else if ( this->TranslationEnabled && this->CurrentHandle == this->Handle[6] )
			{
				// 鼠标指向中心句柄: 平移
				this->Translate(prevPickPoint, pickPoint);
			}
			else if ( this->TranslationEnabled && this->ScalingEnabled )
			{
				// 鼠标指向某一面的句柄: 缩放
				if ( this->CurrentHandle == this->Handle[0] )
				{
					this->MoveMinusXFace(prevPickPoint, pickPoint);
				}
				else if ( this->CurrentHandle == this->Handle[1] )
				{
					this->MovePlusXFace(prevPickPoint, pickPoint);
				}
				else if ( this->CurrentHandle == this->Handle[2] )
				{
					this->MoveMinusYFace(prevPickPoint, pickPoint);
				}
				else if ( this->CurrentHandle == this->Handle[3] )
				{
					this->MovePlusYFace(prevPickPoint, pickPoint);
				}
				else if ( this->CurrentHandle == this->Handle[4] )
				{
					this->MoveMinusZFace(prevPickPoint, pickPoint);
				}
				else if ( this->CurrentHandle == this->Handle[5] )
				{
					this->MovePlusZFace(prevPickPoint, pickPoint);
				}
			}
		}
	}
	else if ( this->ScalingEnabled && this->State == vtkBoxWidget::Scaling )
	{
		this->Scale(prevPickPoint, pickPoint, X, Y);
	}

	// Interact, if desired
	this->EventCallbackCommand->SetAbortFlag(1);
	this->InvokeEvent(vtkCommand::InteractionEvent, NULL);
	this->Interactor->Render();
}
/************************************************************************/
/* 移动某个面                                                           */
// 输入:
// double *p1	:鼠标移动之前的点的坐标
// double *p2	:鼠标移动之后的点的坐标
// double *dir	:方向向量
// double *x1	:面的四个点
// double *x2	:
// double *x3	:
// double *x4	:
// double *x5	:面的中心
/************************************************************************/
void vtkBoxWidget::MoveFace(double *p1, double *p2, double *dir,
	double *x1, double *x2, double *x3, double *x4,
	double *x5)
{
	int i;
	double v[3], v2[3];

	for (i=0; i<3; i++)
	{
		v[i] = p2[i] - p1[i]; // 鼠标移动的向量
		v2[i] = dir[i];
	}

	vtkMath::Normalize(v2); // 单元化
	double f = vtkMath::Dot(v,v2); // 求得V在V2方向上的投影长度
	// 5个点的平移
	for (i=0; i<3; i++)
	{
		v[i] = f*v2[i];

		x1[i] += v[i];
		x2[i] += v[i];
		x3[i] += v[i];
		x4[i] += v[i];
		x5[i] += v[i];
	}
	this->PositionHandles();
}
/************************************************************************/
/* 【这个函数太牛掰了】                                                 */
// 输入:
// 三个方向的单位向量
// 输出:
// double dir[3]	:移动的方向向量
/************************************************************************/
void vtkBoxWidget::GetDirection(const double Nx[3],const double Ny[3], const double Nz[3], double dir[3])
{
	double dotNy, dotNz;
	double y[3];

	if(vtkMath::Dot(Nx,Nx)!=0) // Nx 不为零向量的时候
	{
		dir[0] = Nx[0];
		dir[1] = Nx[1];
		dir[2] = Nx[2];
	}
	else
	{
		dotNy = vtkMath::Dot(Ny,Ny);
		dotNz = vtkMath::Dot(Nz,Nz);
		if(dotNy != 0 && dotNz != 0) // Ny Nz 不为零向量的时候
		{
			vtkMath::Cross(Ny,Nz,dir);
		}
		else if(dotNy != 0)
		{
			//dir must have been initialized to the
			//corresponding coordinate direction before calling
			//this method
			vtkMath::Cross(Ny,dir,y);
			vtkMath::Cross(y,Ny,dir);
		}
		else if(dotNz != 0)
		{
			//dir must have been initialized to the
			//corresponding coordinate direction before calling
			//this method
			vtkMath::Cross(Nz,dir,y);
			vtkMath::Cross(y,Nz,dir);
		}
	}
}
/************************************************************************/
/* 移动 XYZ 方向的正负面                                                */
/************************************************************************/
void vtkBoxWidget::MovePlusXFace(double *p1, double *p2)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);

	double *h1 = pts + 3*9;		// X正轴的面的中心点/句柄

	double *x1 = pts + 3*1;		// X正轴的面的四个点
	double *x2 = pts + 3*2;
	double *x3 = pts + 3*5;
	double *x4 = pts + 3*6;

	double dir[3] = { 1 , 0 , 0};
	this->ComputeNormals();
	this->GetDirection(this->N[1],this->N[3],this->N[5],dir);
	this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1);
}

void vtkBoxWidget::MoveMinusXFace(double *p1, double *p2)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);

	double *h1 = pts + 3*8;		// X负轴的面的中心点/句柄

	double *x1 = pts + 3*0;		// X负轴的面的四个点
	double *x2 = pts + 3*3;
	double *x3 = pts + 3*4;
	double *x4 = pts + 3*7;

	double dir[3]={-1,0,0};
	this->ComputeNormals();		// 计算各个方向的单位向量
	this->GetDirection(this->N[0],this->N[4],this->N[2],dir);

	this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1);
}

void vtkBoxWidget::MovePlusYFace(double *p1, double *p2)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);

	double *h1 = pts + 3*11;

	double *x1 = pts + 3*2;
	double *x2 = pts + 3*3;
	double *x3 = pts + 3*6;
	double *x4 = pts + 3*7;

	double dir[3]={0,1,0};
	this->ComputeNormals();
	this->GetDirection(this->N[3],this->N[5],this->N[1],dir);

	this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1);
}

void vtkBoxWidget::MoveMinusYFace(double *p1, double *p2)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);

	double *h1 = pts + 3*10;

	double *x1 = pts + 3*0;
	double *x2 = pts + 3*1;
	double *x3 = pts + 3*4;
	double *x4 = pts + 3*5;

	double dir[3] = {0, -1, 0};
	this->ComputeNormals();
	this->GetDirection(this->N[2],this->N[0],this->N[4],dir);

	this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1);
}

void vtkBoxWidget::MovePlusZFace(double *p1, double *p2)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);

	double *h1 = pts + 3*13;

	double *x1 = pts + 3*4;
	double *x2 = pts + 3*5;
	double *x3 = pts + 3*6;
	double *x4 = pts + 3*7;

	double dir[3]={0,0,1};
	this->ComputeNormals();
	this->GetDirection(this->N[5],this->N[1],this->N[3],dir);

	this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1);
}

void vtkBoxWidget::MoveMinusZFace(double *p1, double *p2)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);

	double *h1 = pts + 3*12;

	double *x1 = pts + 3*0;
	double *x2 = pts + 3*1;
	double *x3 = pts + 3*2;
	double *x4 = pts + 3*3;

	double dir[3]={0,0,-1};
	this->ComputeNormals();
	this->GetDirection(this->N[4],this->N[2],this->N[0],dir);

	this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1);
}
/************************************************************************/
/* 平移:	循环遍历所有的点集(角点、顶点),并平移每个点              */
// 输入:
// double *p1	:鼠标移动之前的点的坐标
// double *p2	:鼠标移动之后的点的坐标
/************************************************************************/
// Loop through all points and translate them
void vtkBoxWidget::Translate(double *p1, double *p2)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);
	double v[3];		// 移动向量

	v[0] = p2[0] - p1[0];
	v[1] = p2[1] - p1[1];
	v[2] = p2[2] - p1[2];

	// Move the corners
	for (int i=0; i<8; i++)
	{
		*pts++ += v[0];
		*pts++ += v[1];
		*pts++ += v[2];
	}
	this->PositionHandles();
}
/************************************************************************/
/* 缩放                                                                 */
// 输入:
// double *p1	:鼠标移动之前的点的坐标
// double *p2	:鼠标移动之后的点的坐标
/************************************************************************/
void vtkBoxWidget::Scale(double* vtkNotUsed(p1), double* vtkNotUsed(p2),
	int vtkNotUsed(X), int Y)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);
	double *center
		= static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(3*14);
	double sf;

	if ( Y > this->Interactor->GetLastEventPosition()[1] )
	{
		sf = 1.03;
	}
	else
	{
		sf = 0.97;
	}

	// Move the corners
	for (int i=0; i<8; i++, pts+=3)
	{
		pts[0] = sf * (pts[0] - center[0]) + center[0];
		pts[1] = sf * (pts[1] - center[1]) + center[1];
		pts[2] = sf * (pts[2] - center[2]) + center[2];
	}
	this->PositionHandles();
}
/************************************************************************/
/* 计算单位向量,存储在N向量中,为X正方向,X负方向,Y正方向,Y负方向,Z正方向,Z负方向   */
/************************************************************************/
void vtkBoxWidget::ComputeNormals()
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);
	double *p0 = pts;
	double *px = pts + 3*1;
	double *py = pts + 3*3;
	double *pz = pts + 3*4;
	int i;

	for (i=0; i<3; i++)
	{
		this->N[0][i] = p0[i] - px[i];
		this->N[2][i] = p0[i] - py[i];
		this->N[4][i] = p0[i] - pz[i];
	}
	vtkMath::Normalize(this->N[0]);
	vtkMath::Normalize(this->N[2]);
	vtkMath::Normalize(this->N[4]);
	for (i=0; i<3; i++)
	{
		this->N[1][i] = -this->N[0][i];
		this->N[3][i] = -this->N[2][i];
		this->N[5][i] = -this->N[4][i];
	}
}
/************************************************************************/
/* 6个平面获取                                                             */
/************************************************************************/
void vtkBoxWidget::GetPlanes(vtkPlanes *planes)
{
	if ( ! planes )
	{
		return;
	}

	this->ComputeNormals();

	vtkPoints *pts = vtkPoints::New(VTK_DOUBLE);
	pts->SetNumberOfPoints(6);

	vtkDoubleArray *normals = vtkDoubleArray::New();
	normals->SetNumberOfComponents(3);
	normals->SetNumberOfTuples(6);

	// Set the normals and coordinate values
	double factor = (this->InsideOut ? -1.0 : 1.0);
	for (int i=0; i<6; i++)
	{
		pts->SetPoint(i,this->Points->GetPoint(8+i));
		normals->SetTuple3(i, factor*this->N[i][0], factor*this->N[i][1],
			factor*this->N[i][2]);
	}

	planes->SetPoints(pts);
	planes->SetNormals(normals);

	pts->Delete();
	normals->Delete();
}
/************************************************************************/
/* 旋转                                                                 */
// 输入
// int X		:鼠标当前点的坐标:x
// int Y		:鼠标当前点的坐标: y
// double *p1	:鼠标移动之前的点的坐标
// double *p2	:鼠标移动之后的点的坐标
// double *vpn	:法向量
/************************************************************************/
void vtkBoxWidget::Rotate(int X, int Y, double *p1, double *p2, double *vpn)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);
	double *center =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(3*14);
	double v[3];		// vector of motion: 移动的向量
	double axis[3];		// axis of rotation: 
	double theta;		// rotation angle
	int i;

	v[0] = p2[0] - p1[0];
	v[1] = p2[1] - p1[1];
	v[2] = p2[2] - p1[2];

	// Create axis of rotation and angle of rotation
	vtkMath::Cross(vpn,v,axis);
	if ( vtkMath::Normalize(axis) == 0.0 )
	{
		return;
	}
	int *size = this->CurrentRenderer->GetSize();
	double l2 = (X-this->Interactor->GetLastEventPosition()[0])*(X-this->Interactor->GetLastEventPosition()[0]) 
		+ (Y-this->Interactor->GetLastEventPosition()[1])*(Y-this->Interactor->GetLastEventPosition()[1]);
	theta = 360.0 * sqrt(l2/(size[0]*size[0]+size[1]*size[1]));
	// vtkTransform	:describes linear transformations via a 4x4 matrix 
	//Manipulate the transform to reflect the rotation
	this->Transform->Identity();
	this->Transform->Translate(center[0],center[1],center[2]);
	this->Transform->RotateWXYZ(theta,axis);
	this->Transform->Translate(-center[0],-center[1],-center[2]);

	//Set the corners
	vtkPoints *newPts = vtkPoints::New(VTK_DOUBLE);
	this->Transform->TransformPoints(this->Points, newPts);

	for (i=0; i<8; i++, pts+=3)
	{// 变换8个点的坐标
		this->Points->SetPoint(i, newPts->GetPoint(i));
	}

	newPts->Delete();
	this->PositionHandles(); // 重新计算句柄的坐标,更新相关的数据
}
/************************************************************************/
/* 设置相关默认属性                                                     */
/************************************************************************/
// Properties used to control the appearance of selected objects and
// the manipulator in general.
void vtkBoxWidget::CreateDefaultProperties()
{
	// Handle properties
	this->HandleProperty = vtkProperty::New();
	this->HandleProperty->SetColor(1,1,1);
	// 被选中的句柄的属性
	this->SelectedHandleProperty = vtkProperty::New();
	this->SelectedHandleProperty->SetColor(1,0,0);

	// Face properties
	this->FaceProperty = vtkProperty::New();
	this->FaceProperty->SetColor(1,1,1);
	this->FaceProperty->SetOpacity(0.0); // 设置透明度
	// 被选中的面的属性
	this->SelectedFaceProperty = vtkProperty::New();
	this->SelectedFaceProperty->SetColor(1,1,0);
	this->SelectedFaceProperty->SetOpacity(0.25);

	// Outline properties
	this->OutlineProperty = vtkProperty::New();
	this->OutlineProperty->SetRepresentationToWireframe(); // 表示几何结构为线,不是点和面
	this->OutlineProperty->SetAmbient(1.0); // Set/Get the ambient lighting coefficient. 
	this->OutlineProperty->SetAmbientColor(1.0,1.0,1.0); // 环境光颜色
	this->OutlineProperty->SetLineWidth(2.0);

	// 被选中时轮廓对象的属性设置
	this->SelectedOutlineProperty = vtkProperty::New();
	this->SelectedOutlineProperty->SetRepresentationToWireframe();
	this->SelectedOutlineProperty->SetAmbient(1.0);
	this->SelectedOutlineProperty->SetAmbientColor(0.0,1.0,0.0);
	this->SelectedOutlineProperty->SetLineWidth(2.0);
}
/************************************************************************/
/* 初始化控件的位置                                                     */
// 初始化时 输入bds[6]为: double bounds[6];
//bounds[0] = -0.5;
//bounds[1] = 0.5;
//bounds[2] = -0.5;
//bounds[3] = 0.5;
//bounds[4] = -0.5;
//bounds[5] = 0.5;
/************************************************************************/
void vtkBoxWidget::PlaceWidget(double bds[6])
{
	int i;
	double bounds[6], center[3];

	this->AdjustBounds(bds,bounds,center); // 返回bounds为新的

	this->Points->SetPoint(0, bounds[0], bounds[2], bounds[4]);
	this->Points->SetPoint(1, bounds[1], bounds[2], bounds[4]);
	this->Points->SetPoint(2, bounds[1], bounds[3], bounds[4]);
	this->Points->SetPoint(3, bounds[0], bounds[3], bounds[4]);
	this->Points->SetPoint(4, bounds[0], bounds[2], bounds[5]);
	this->Points->SetPoint(5, bounds[1], bounds[2], bounds[5]);
	this->Points->SetPoint(6, bounds[1], bounds[3], bounds[5]);
	this->Points->SetPoint(7, bounds[0], bounds[3], bounds[5]);

	for (i=0; i<6; i++)
	{
		this->InitialBounds[i] = bounds[i];
	}
	this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
		(bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
		(bounds[5]-bounds[4])*(bounds[5]-bounds[4]));

	this->PositionHandles();
	this->ComputeNormals();
	this->SizeHandles(); // 调用上面 this->InitialLength , 这就很明显需要对代码内部的成员很熟了
}
/************************************************************************/
/* 返回一个box变化的线性变换矩阵                                        */
/************************************************************************/
void vtkBoxWidget::GetTransform(vtkTransform *t)
{
	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);
	double *p0 = pts;
	double *p1 = pts + 3*1;
	double *p3 = pts + 3*3;
	double *p4 = pts + 3*4;
	double *p14 = pts + 3*14; // 中心点的坐标
	double center[3], translate[3], scale[3], scaleVec[3][3];
	double InitialCenter[3];
	int i;

	// The transformation is relative to the initial bounds.
	// Initial bounds are set when PlaceWidget() is invoked.
	t->Identity();

	// Translation 平移
	for (i=0; i<3; i++)
	{
		InitialCenter[i] =
			(this->InitialBounds[2*i+1]+this->InitialBounds[2*i]) / 2.0;
		center[i] = p14[i] - InitialCenter[i];
	}
	translate[0] = center[0] + InitialCenter[0];
	translate[1] = center[1] + InitialCenter[1];
	translate[2] = center[2] + InitialCenter[2];  // 晕死,这不直接就是 p14 吗
	t->Translate(translate[0], translate[1], translate[2]);

	// Orientation 方向
	vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
	this->PositionHandles();
	this->ComputeNormals();
	for (i=0; i<3; i++)
	{ // xyz 负方向的单位向量
		matrix->SetElement(i,0,this->N[1][i]);
		matrix->SetElement(i,1,this->N[3][i]);
		matrix->SetElement(i,2,this->N[5][i]);
	}
	t->Concatenate(matrix);
	matrix->Delete();

	// Scale
	for (i=0; i<3; i++)
	{
		scaleVec[0][i] = (p1[i] - p0[i]);
		scaleVec[1][i] = (p3[i] - p0[i]);
		scaleVec[2][i] = (p4[i] - p0[i]);
	}

	scale[0] = vtkMath::Norm(scaleVec[0]);
	if (this->InitialBounds[1] != this->InitialBounds[0])
	{
		scale[0] = scale[0] / (this->InitialBounds[1]-this->InitialBounds[0]); // x 轴
	}
	scale[1] = vtkMath::Norm(scaleVec[1]);
	if (this->InitialBounds[3] != this->InitialBounds[2])
	{
		scale[1] = scale[1] / (this->InitialBounds[3]-this->InitialBounds[2]); // y 轴
	}
	scale[2] = vtkMath::Norm(scaleVec[2]);
	if (this->InitialBounds[5] != this->InitialBounds[4])
	{
		scale[2] = scale[2] / (this->InitialBounds[5]-this->InitialBounds[4]); // z 轴
	}
	t->Scale(scale[0],scale[1],scale[2]);

	// Add back in the contribution due to non-origin center
	t->Translate(-InitialCenter[0], -InitialCenter[1], -InitialCenter[2]);
}
/************************************************************************/
/* 输入变化矩阵,为每个顶点实现变换                                     */
/************************************************************************/
void vtkBoxWidget::SetTransform(vtkTransform* t)
{
	if (!t)
	{
		vtkErrorMacro(<<"vtkTransform t must be non-NULL");
		return;
	}

	double *pts =
		static_cast<vtkDoubleArray *>(this->Points->GetData())->GetPointer(0);
	double xIn[3];
	// make sure the transform is up-to-date before using it
	t->Update();

	// Position the eight points of the box and then update the
	// position of the other handles.
	double *bounds=this->InitialBounds;

	xIn[0] = bounds[0]; xIn[1] = bounds[2]; xIn[2] = bounds[4];
	t->InternalTransformPoint(xIn,pts);

	xIn[0] = bounds[1]; xIn[1]= bounds[2]; xIn[2] = bounds[4];
	t->InternalTransformPoint(xIn,pts+3);

	xIn[0] = bounds[1]; xIn[1]= bounds[3]; xIn[2] = bounds[4];
	t->InternalTransformPoint(xIn,pts+6);

	xIn[0] = bounds[0]; xIn[1]= bounds[3]; xIn[2] = bounds[4];
	t->InternalTransformPoint(xIn,pts+9);

	xIn[0] = bounds[0]; xIn[1]= bounds[2]; xIn[2] = bounds[5];
	t->InternalTransformPoint(xIn,pts+12);

	xIn[0] = bounds[1]; xIn[1]= bounds[2]; xIn[2] = bounds[5];
	t->InternalTransformPoint(xIn,pts+15);

	xIn[0] = bounds[1]; xIn[1]= bounds[3]; xIn[2] = bounds[5];
	t->InternalTransformPoint(xIn,pts+18);

	xIn[0] = bounds[0]; xIn[1]= bounds[3]; xIn[2] = bounds[5];
	t->InternalTransformPoint(xIn,pts+21);

	this->PositionHandles();
}
/************************************************************************/
/* 获取这个六边形的数据信息                                             */
/************************************************************************/
void vtkBoxWidget::GetPolyData(vtkPolyData *pd)
{
	pd->SetPoints(this->HexPolyData->GetPoints());
	pd->SetPolys(this->HexPolyData->GetPolys());
}
/************************************************************************/
/* 设置值                                                               */
/************************************************************************/
void vtkBoxWidget::SetOutlineFaceWires(int newValue)
{
	if (this->OutlineFaceWires != newValue)
	{
		this->OutlineFaceWires = newValue;
		this->Modified();
		// the outline is dependent on this value, so we have to regen
		this->GenerateOutline();
	}
}

void vtkBoxWidget::SetOutlineCursorWires(int newValue)
{
	if (this->OutlineCursorWires != newValue)
	{
		this->OutlineCursorWires = newValue;
		this->Modified();
		// the outline is dependent on this value, so we have to regen
		this->GenerateOutline();
	}
}
/************************************************************************/
/* 更新每条线的数据: 对角线和坐标轴数据信息                            */
/************************************************************************/
void vtkBoxWidget::GenerateOutline()
{
	// Whatever the case may be, we have to reset the Lines of the
	// OutlinePolyData (i.e. nuke all current line data)
	vtkCellArray *cells = this->OutlinePolyData->GetLines();
	cells->Reset();

	/*
	初始化:
	// Control orientation of normals
	this->InsideOut = 0;
	this->OutlineFaceWires = 0;
	this->OutlineCursorWires = 1;
	前提:
	也就是说要使用的前提就是需要 OutlineFaceWiresOn() 
	*/
	// Now the outline lines 
	if ( ! this->OutlineFaceWires && ! this->OutlineCursorWires )
	{
		return;
	}

	vtkIdType pts[2];

	if ( this->OutlineFaceWires ) // 这个还有判断的必要吗?
	{
		pts[0] = 0; pts[1] = 7;       //the -x face
		cells->InsertNextCell(2,pts);
		pts[0] = 3; pts[1] = 4;
		cells->InsertNextCell(2,pts);
		pts[0] = 1; pts[1] = 6;       //the +x face
		cells->InsertNextCell(2,pts);
		pts[0] = 2; pts[1] = 5;
		cells->InsertNextCell(2,pts);
		pts[0] = 1; pts[1] = 4;       //the -y face
		cells->InsertNextCell(2,pts);
		pts[0] = 0; pts[1] = 5;
		cells->InsertNextCell(2,pts);
		pts[0] = 3; pts[1] = 6;       //the +y face
		cells->InsertNextCell(2,pts);
		pts[0] = 2; pts[1] = 7;
		cells->InsertNextCell(2,pts);
		pts[0] = 0; pts[1] = 2;       //the -z face
		cells->InsertNextCell(2,pts);
		pts[0] = 1; pts[1] = 3;
		cells->InsertNextCell(2,pts);
		pts[0] = 4; pts[1] = 6;       //the +Z face
		cells->InsertNextCell(2,pts);
		pts[0] = 5; pts[1] = 7;
		cells->InsertNextCell(2,pts);
	}
	if ( this->OutlineCursorWires )
	{
		pts[0] = 8; pts[1] = 9;         //the x cursor line
		cells->InsertNextCell(2,pts);
		pts[0] = 10; pts[1] = 11;       //the y cursor line
		cells->InsertNextCell(2,pts);
		pts[0] = 12; pts[1] = 13;       //the z cursor line
		cells->InsertNextCell(2,pts);
	}

	this->OutlinePolyData->Modified();  // 对应前面的 vtkCellArray *cells = this->OutlinePolyData->GetLines();
	if ( this->OutlineProperty)
	{
		this->OutlineProperty->SetRepresentationToWireframe();
		this->SelectedOutlineProperty->SetRepresentationToWireframe();
	}
}

//------------------------------------------------------------------------------
void vtkBoxWidget::RegisterPickers()
{
	this->Interactor->GetPickingManager()->AddPicker(this->HandlePicker, this);
	this->Interactor->GetPickingManager()->AddPicker(this->HexPicker, this);
}
//Contact GitHub API Training Shop Blog About
//2016 GitHub, Inc. Terms Privacy Security Status Help


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值