/*========================================================================= medInria Copyright (c) INRIA 2013 - 2018. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =========================================================================*/ #include #include "vtkMatrixToLinearTransform.h" #include "vtkObjectFactory.h" #include "vtkMatrix4x4.h" #include "vtkPoints.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 "vtkPlanes.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkProperty.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkSphereSource.h" #include "vtkTransform.h" #include "vtkReverseSense.h" vtkStandardNewMacro(vtkOrientedBoxWidget); //---------------------------------------------------------------------------- vtkOrientedBoxWidget::vtkOrientedBoxWidget() { this->OrientationMatrix = vtkMatrix4x4::New(); this->OrientationMatrix->Identity(); this->InvertedOrientationMatrix = vtkMatrix4x4::New(); this->InvertedOrientationMatrix->Identity(); } //---------------------------------------------------------------------------- vtkOrientedBoxWidget::~vtkOrientedBoxWidget() { this->OrientationMatrix->Delete(); this->InvertedOrientationMatrix->Delete(); } //---------------------------------------------------------------------------- void vtkOrientedBoxWidget::SetOrientationMatrix(vtkMatrix4x4* matrix) { if (matrix == this->OrientationMatrix) return; if (this->OrientationMatrix) { this->OrientationMatrix->UnRegister (this); this->OrientationMatrix = nullptr; } this->OrientationMatrix = matrix; if ( this->OrientationMatrix ) { this->OrientationMatrix->Register(this); } // move all the actors according to the user-matrix this->HexActor->SetUserMatrix (matrix); this->HexFace->SetUserMatrix (matrix); this->HexOutline->SetUserMatrix (matrix); for (unsigned int i=0; i<7; i++) this->Handle[i]->SetUserMatrix (matrix); if (matrix->Determinant()<0.0) { for (unsigned int i=0; i<7; i++) { if (vtkPolyData *input = vtkPolyData::SafeDownCast (this->Handle[i]->GetMapper()->GetInput())) { vtkReverseSense *reverse = vtkReverseSense::New(); reverse->SetInputData (input); reverse->ReverseNormalsOn(); reverse->ReverseCellsOff(); reverse->Update(); vtkPolyDataMapper::SafeDownCast (this->Handle[i]->GetMapper())->SetInputData (reverse->GetOutput()); reverse->Delete(); } } } if (this->OrientationMatrix) { // initialize inverse matrix vtkMatrix4x4::Invert (this->OrientationMatrix, this->InvertedOrientationMatrix); } } //---------------------------------------------------------------------------- void vtkOrientedBoxWidget::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); // multiply pick points by the inverted orientation matrix // to recover the true movement to apply this->InvertedOrientationMatrix->MultiplyPoint (prevPickPoint, prevPickPoint); this->InvertedOrientationMatrix->MultiplyPoint (pickPoint, 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, nullptr); this->Interactor->Render(); }