/*========================================================================= Program: Visualization Toolkit Module: vtkResliceCursorActor.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 "vtkResliceCursorActor.h" #include "vtkActor.h" #include "vtkBoundingBox.h" #include "vtkMath.h" #include "vtkMatrix4x4.h" #include "vtkObjectFactory.h" #include "vtkPlane.h" #include "vtkPolyDataMapper.h" #include "vtkProperty.h" #include "vtkResliceCursor.h" #include "vtkResliceCursorPolyDataAlgorithm.h" #include "vtkViewport.h" vtkStandardNewMacro(vtkResliceCursorActor); //------------------------------------------------------------------------------ vtkResliceCursorActor::vtkResliceCursorActor() { this->CursorAlgorithm = vtkResliceCursorPolyDataAlgorithm::New(); for (int i = 0; i < 3; i++) { this->CursorCenterlineMapper[i] = vtkPolyDataMapper::New(); this->CursorCenterlineActor[i] = vtkActor::New(); this->CursorThickSlabMapper[i] = vtkPolyDataMapper::New(); this->CursorThickSlabActor[i] = vtkActor::New(); this->CursorCenterlineMapper[i]->ScalarVisibilityOff(); this->CursorThickSlabMapper[i]->ScalarVisibilityOff(); this->CursorCenterlineActor[i]->SetMapper(this->CursorCenterlineMapper[i]); this->CursorThickSlabActor[i]->SetMapper(this->CursorThickSlabMapper[i]); this->CenterlineProperty[i] = vtkProperty::New(); this->ThickSlabProperty[i] = vtkProperty::New(); this->CursorCenterlineActor[i]->SetProperty(this->CenterlineProperty[i]); this->CursorThickSlabActor[i]->SetProperty(this->ThickSlabProperty[i]); } this->CenterlineProperty[0]->SetColor(1, 0, 0); this->CenterlineProperty[1]->SetColor(0, 1, 0); this->CenterlineProperty[2]->SetColor(0, 0, 1); this->ThickSlabProperty[0]->SetColor(1, 0.6, 0.6); this->ThickSlabProperty[1]->SetColor(0.6, 1, 0.6); this->ThickSlabProperty[2]->SetColor(0.6, 0.6, 1); this->CenterlineProperty[0]->SetEdgeColor(1, 0, 0); this->CenterlineProperty[1]->SetEdgeColor(0, 1, 0); this->CenterlineProperty[2]->SetEdgeColor(0, 0, 1); this->ThickSlabProperty[0]->SetEdgeColor(1, 0.6, 0.6); this->ThickSlabProperty[1]->SetEdgeColor(0.6, 1, 0.6); this->ThickSlabProperty[2]->SetEdgeColor(0.6, 0.6, 1); this->CenterlineProperty[0]->SetEdgeVisibility(1); this->CenterlineProperty[1]->SetEdgeVisibility(1); this->CenterlineProperty[2]->SetEdgeVisibility(1); this->ThickSlabProperty[0]->SetEdgeVisibility(1); this->ThickSlabProperty[1]->SetEdgeVisibility(1); this->ThickSlabProperty[2]->SetEdgeVisibility(1); } //------------------------------------------------------------------------------ vtkResliceCursorActor::~vtkResliceCursorActor() { for (int i = 0; i < 3; i++) { this->CursorCenterlineMapper[i]->Delete(); this->CursorCenterlineActor[i]->Delete(); this->CursorThickSlabMapper[i]->Delete(); this->CursorThickSlabActor[i]->Delete(); this->CenterlineProperty[i]->Delete(); this->ThickSlabProperty[i]->Delete(); } this->CursorAlgorithm->Delete(); } //------------------------------------------------------------------------------ // Description: // Support the standard render methods. int vtkResliceCursorActor::RenderOpaqueGeometry(vtkViewport* viewport) { int result = 0; if (this->CursorAlgorithm->GetResliceCursor()) { this->UpdateViewProps(viewport); for (int i = 0; i < 3; i++) { if (this->CursorCenterlineActor[i]->GetVisibility()) { result += this->CursorCenterlineActor[i]->RenderOpaqueGeometry(viewport); } if (this->CursorThickSlabActor[i]->GetVisibility()) { result += this->CursorThickSlabActor[i]->RenderOpaqueGeometry(viewport); } } } return result; } //------------------------------------------------------------------------------ // Description: // Does this prop have some translucent polygonal geometry? No. vtkTypeBool vtkResliceCursorActor::HasTranslucentPolygonalGeometry() { return false; } //------------------------------------------------------------------------------ void vtkResliceCursorActor::ReleaseGraphicsResources(vtkWindow* window) { for (int i = 0; i < 3; i++) { this->CursorCenterlineActor[i]->ReleaseGraphicsResources(window); this->CursorThickSlabActor[i]->ReleaseGraphicsResources(window); } } //------------------------------------------------------------------------------ // Get the bounds for this Actor as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). double* vtkResliceCursorActor::GetBounds() { // we cannot initialize the Bounds the same way vtkBoundingBox does because // vtkProp3D::GetLength() does not check if the Bounds are initialized or // not and makes a call to sqrt(). This call to sqrt with invalid values // would raise a floating-point overflow exception (notably on BCC). // As vtkMath::UninitializeBounds initialized finite unvalid bounds, it // passes silently and GetLength() returns 0. vtkMath::UninitializeBounds(this->Bounds); this->UpdateViewProps(); vtkBoundingBox* bb = new vtkBoundingBox(); double bounds[6]; for (int i = 0; i < 3; i++) { if (this->CursorCenterlineActor[i]->GetVisibility() && this->CursorCenterlineActor[i]->GetUseBounds()) { this->CursorCenterlineActor[i]->GetBounds(bounds); bb->AddBounds(bounds); } if (this->CursorThickSlabActor[i]->GetVisibility() && this->CursorThickSlabActor[i]->GetUseBounds()) { this->CursorThickSlabActor[i]->GetBounds(bounds); bb->AddBounds(bounds); } } bb->GetBounds(this->Bounds); delete bb; return this->Bounds; } //------------------------------------------------------------------------------ vtkMTimeType vtkResliceCursorActor::GetMTime() { vtkMTimeType mTime = this->Superclass::GetMTime(); if (this->CursorAlgorithm) { vtkMTimeType time; time = this->CursorAlgorithm->GetMTime(); if (time > mTime) { mTime = time; } } return mTime; } //------------------------------------------------------------------------------ vtkProperty* vtkResliceCursorActor::GetCenterlineProperty(int i) { return this->CenterlineProperty[i]; } //------------------------------------------------------------------------------ vtkProperty* vtkResliceCursorActor::GetThickSlabProperty(int i) { return this->ThickSlabProperty[i]; } //------------------------------------------------------------------------------ void vtkResliceCursorActor::UpdateHoleSize(vtkViewport* v) { vtkResliceCursor* r = this->CursorAlgorithm->GetResliceCursor(); if (r->GetHoleWidthInPixels() && r->GetHole() && v) { // Get the reslice center in display coords. double dCenter[4], wCenter[4], wCenterHoleWidthAway[4]; r->GetCenter(wCenter); wCenter[3] = 1.0; v->SetWorldPoint(wCenter); v->WorldToDisplay(); v->GetDisplayPoint(dCenter); // Get the world position of a point "holeWidth pixels" away from the // reslice center dCenter[0] += (r->GetHoleWidthInPixels() / 2.0); v->SetDisplayPoint(dCenter); v->DisplayToWorld(); v->GetWorldPoint(wCenterHoleWidthAway); const double holeWidth = 2.0 * sqrt(vtkMath::Distance2BetweenPoints(wCenter, wCenterHoleWidthAway)); if (fabs(r->GetHoleWidth() - holeWidth) > 1e-5) { r->SetHoleWidth(holeWidth); } // MTime checks ensure that this will update only if the hole width // has actually changed. this->CursorAlgorithm->Update(); } } //------------------------------------------------------------------------------ void vtkResliceCursorActor::UpdateViewProps(vtkViewport* v) { if (this->CursorAlgorithm->GetResliceCursor() == nullptr) { vtkDebugMacro(<< "no cursor to represent."); return; } this->CursorAlgorithm->Update(); // Update the cursor to reflect a constant hole size in pixels, if necessary this->UpdateHoleSize(v); // Rebuild cursor to have the right hole with if necessary const int axisNormal = this->CursorAlgorithm->GetReslicePlaneNormal(); const int axis1 = this->CursorAlgorithm->GetPlaneAxis1(); const int axis2 = this->CursorAlgorithm->GetPlaneAxis2(); this->CursorCenterlineMapper[axis1]->SetInputConnection(this->CursorAlgorithm->GetOutputPort(0)); this->CursorCenterlineMapper[axis2]->SetInputConnection(this->CursorAlgorithm->GetOutputPort(1)); const bool thickMode = this->CursorAlgorithm->GetResliceCursor()->GetThickMode() != 0; if (thickMode) { this->CursorThickSlabMapper[axis1]->SetInputConnection(this->CursorAlgorithm->GetOutputPort(2)); this->CursorThickSlabMapper[axis2]->SetInputConnection(this->CursorAlgorithm->GetOutputPort(3)); this->CursorThickSlabActor[axis1]->SetVisibility(1); this->CursorThickSlabActor[axis2]->SetVisibility(1); } this->CursorThickSlabActor[axis1]->SetVisibility(thickMode); this->CursorThickSlabActor[axis2]->SetVisibility(thickMode); this->CursorThickSlabActor[axisNormal]->SetVisibility(0); this->CursorCenterlineActor[axis1]->SetVisibility(1); this->CursorCenterlineActor[axis2]->SetVisibility(1); this->CursorCenterlineActor[axisNormal]->SetVisibility(0); this->CursorThickSlabActor[axis1]->GetProperty()->SetEdgeVisibility(thickMode); this->CursorThickSlabActor[axis2]->GetProperty()->SetEdgeVisibility(thickMode); this->CursorThickSlabActor[axisNormal]->GetProperty()->SetEdgeVisibility(0); this->CursorCenterlineActor[axis1]->GetProperty()->SetEdgeVisibility(1); this->CursorCenterlineActor[axis2]->GetProperty()->SetEdgeVisibility(1); this->CursorCenterlineActor[axisNormal]->GetProperty()->SetEdgeVisibility(0); } //------------------------------------------------------------------------------ void vtkResliceCursorActor::SetUserMatrix(vtkMatrix4x4* m) { this->CursorThickSlabActor[0]->SetUserMatrix(m); this->CursorThickSlabActor[1]->SetUserMatrix(m); this->CursorThickSlabActor[2]->SetUserMatrix(m); this->CursorCenterlineActor[0]->SetUserMatrix(m); this->CursorCenterlineActor[1]->SetUserMatrix(m); this->CursorCenterlineActor[2]->SetUserMatrix(m); this->Superclass::SetUserMatrix(m); } //------------------------------------------------------------------------------ vtkActor* vtkResliceCursorActor::GetCenterlineActor(int axis) { return this->CursorCenterlineActor[axis]; } //------------------------------------------------------------------------------ // Prints an object if it exists. #define vtkPrintMemberObjectMacro(obj, os, indent) \ os << (indent) << #obj << ": "; \ if (this->obj) \ { \ os << this->obj << "\n"; \ } \ else \ { \ os << "(null)\n"; \ } //------------------------------------------------------------------------------ void vtkResliceCursorActor::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); vtkPrintMemberObjectMacro(CursorCenterlineActor[0], os, indent); vtkPrintMemberObjectMacro(CursorCenterlineActor[1], os, indent); vtkPrintMemberObjectMacro(CursorCenterlineActor[2], os, indent); vtkPrintMemberObjectMacro(CursorAlgorithm, os, indent); // this->CursorCenterlineMapper[3]; // this->CursorCenterlineActor[3]; // this->CursorThickSlabMapper[3]; // this->CursorThickSlabActor[3]; // this->CenterlineProperty[3]; // this->ThickSlabProperty[3]; // this->CursorAlgorithm; }