/*========================================================================= Program: Visualization Toolkit Module: vtkResliceCursorRepresentation.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 "vtkResliceCursorRepresentation.h" #include "vtkResliceCursor.h" #include "vtkResliceCursorPolyDataAlgorithm.h" #include "vtkHandleRepresentation.h" #include "vtkCoordinate.h" #include "vtkRenderer.h" #include "vtkMath.h" #include "vtkWindow.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper2D.h" #include "vtkPolyDataMapper.h" #include "vtkActor2D.h" #include "vtkTextMapper.h" #include "vtkTextProperty.h" #include "vtkTextActor.h" #include "vtkProperty2D.h" #include "vtkPointHandleRepresentation2D.h" #include "vtkObjectFactory.h" #include "vtkImageReslice.h" #include "vtkMath.h" #include "vtkMatrix4x4.h" #include "vtkImageData.h" #include "vtkPlaneSource.h" #include "vtkPlane.h" #include "vtkLookupTable.h" #include "vtkScalarsToColors.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkInteractorObserver.h" #include "vtkActor.h" #include "vtkTexture.h" #include "vtkImageActor.h" #include "vtkCamera.h" #include "vtkImageMapper3D.h" #include vtkCxxSetObjectMacro(vtkResliceCursorRepresentation, ColorMap, vtkImageMapToColors); //---------------------------------------------------------------------- vtkResliceCursorRepresentation::vtkResliceCursorRepresentation() { this->ManipulationMode = None; this->Modifier = 0; this->Tolerance = 5; this->ShowReslicedImage = 1; this->RestrictPlaneToVolume = 1; this->OriginalWindow = 1.0; this->OriginalLevel = 0.5; this->InitialWindow = 1.0; this->InitialLevel = 0.5; this->CurrentWindow = 1.0; this->CurrentLevel = 0.5; this->ThicknessTextProperty = vtkTextProperty::New(); this->ThicknessTextProperty->SetBold(1); this->ThicknessTextProperty->SetItalic(1); this->ThicknessTextProperty->SetShadow(1); this->ThicknessTextProperty->SetFontFamilyToArial(); this->ThicknessTextMapper = vtkTextMapper::New(); this->ThicknessTextMapper->SetTextProperty(this->ThicknessTextProperty); this->ThicknessTextMapper->SetInput("0.0"); this->ThicknessTextActor = vtkActor2D::New(); this->ThicknessTextActor->SetMapper(this->ThicknessTextMapper); this->ThicknessTextActor->VisibilityOff(); this->Reslice = nullptr; this->CreateDefaultResliceAlgorithm(); this->PlaneSource = vtkPlaneSource::New(); this->ThicknessLabelFormat = new char[6]; snprintf(this->ThicknessLabelFormat,6,"%s","%0.3g"); this->ResliceAxes = vtkMatrix4x4::New(); this->NewResliceAxes = vtkMatrix4x4::New(); this->LookupTable = nullptr; this->ColorMap = vtkImageMapToColors::New(); this->Texture = vtkTexture::New(); this->Texture->SetInputConnection( this->ColorMap->GetOutputPort()); this->Texture->SetInterpolate(1); this->TexturePlaneActor = vtkActor::New(); this->LookupTable = this->CreateDefaultLookupTable(); this->ColorMap->SetLookupTable(this->LookupTable); this->ColorMap->SetOutputFormatToRGBA(); this->ColorMap->PassAlphaToOutputOn(); vtkPolyDataMapper* texturePlaneMapper = vtkPolyDataMapper::New(); texturePlaneMapper->SetInputConnection( this->PlaneSource->GetOutputPort()); texturePlaneMapper->SetResolveCoincidentTopologyToPolygonOffset(); this->Texture->SetQualityTo32Bit(); this->Texture->SetColorMode(VTK_COLOR_MODE_DEFAULT); this->Texture->SetInterpolate(1); this->Texture->RepeatOff(); this->Texture->SetLookupTable(this->LookupTable); this->TexturePlaneActor->SetMapper(texturePlaneMapper); this->TexturePlaneActor->SetTexture(this->Texture); this->TexturePlaneActor->PickableOn(); texturePlaneMapper->Delete(); this->UseImageActor = false; this->ImageActor = vtkImageActor::New(); this->ImageActor->GetMapper()->SetInputConnection( this->ColorMap->GetOutputPort()); // Represent the text: annotation for cursor position and W/L this->DisplayText = 1; this->TextActor = vtkTextActor::New(); this->GenerateText(); } //---------------------------------------------------------------------- vtkResliceCursorRepresentation::~vtkResliceCursorRepresentation() { this->ThicknessTextProperty->Delete(); this->ThicknessTextMapper->Delete(); this->ThicknessTextActor->Delete(); this->SetThicknessLabelFormat(nullptr); this->ImageActor->Delete(); if (this->Reslice) { this->Reslice->Delete(); } this->PlaneSource->Delete(); this->ResliceAxes->Delete(); this->NewResliceAxes->Delete(); if ( this->LookupTable ) { this->LookupTable->UnRegister(this); } this->ColorMap->Delete(); this->Texture->Delete(); this->TexturePlaneActor->Delete(); this->TextActor->Delete(); } //---------------------------------------------------------------------- void vtkResliceCursorRepresentation::SetLookupTable(vtkScalarsToColors *l) { vtkSetObjectBodyMacro(LookupTable, vtkScalarsToColors, l); this->LookupTable = l; if (this->ColorMap) { this->ColorMap->SetLookupTable(this->LookupTable); } } //---------------------------------------------------------------------- char* vtkResliceCursorRepresentation::GetThicknessLabelText() { return this->ThicknessTextMapper->GetInput(); } //---------------------------------------------------------------------- double* vtkResliceCursorRepresentation::GetThicknessLabelPosition() { return this->ThicknessTextActor->GetPosition(); } //---------------------------------------------------------------------- void vtkResliceCursorRepresentation::GetThicknessLabelPosition(double pos[3]) { this->ThicknessTextActor->GetPositionCoordinate()->GetValue(pos); } //---------------------------------------------------------------------- void vtkResliceCursorRepresentation::GetWorldThicknessLabelPosition(double pos[3]) { double viewportPos[3], worldPos[4]; pos[0] = pos[1] = pos[2] = 0.0; if (!this->Renderer) { vtkErrorMacro("GetWorldLabelPosition: no renderer!"); return; } this->ThicknessTextActor->GetPositionCoordinate()->GetValue(viewportPos); this->Renderer->ViewportToNormalizedViewport(viewportPos[0], viewportPos[1]); this->Renderer->NormalizedViewportToView(viewportPos[0], viewportPos[1], viewportPos[2]); this->Renderer->SetViewPoint(viewportPos); this->Renderer->ViewToWorld(); this->Renderer->GetWorldPoint(worldPos); if (worldPos[3] != 0.0) { pos[0] = worldPos[0]/worldPos[3]; pos[1] = worldPos[1]/worldPos[3]; pos[2] = worldPos[2]/worldPos[3]; } else { vtkErrorMacro("GetWorldLabelPosition: world position at index 3 is 0, not dividing by 0"); } } //---------------------------------------------------------------------- void vtkResliceCursorRepresentation::SetManipulationMode( int m ) { this->ManipulationMode = m; } //---------------------------------------------------------------------- void vtkResliceCursorRepresentation::BuildRepresentation() { this->Reslice->SetInputData(this->GetResliceCursor()->GetImage()); this->TexturePlaneActor->SetVisibility( this->GetResliceCursor()->GetImage() ? (this->ShowReslicedImage && !this->UseImageActor): 0); this->ImageActor->SetVisibility( this->GetResliceCursor()->GetImage() ? (this->ShowReslicedImage && this->UseImageActor) : 0); // Update the reslice plane if the plane is being manipulated if (this->GetManipulationMode() != WindowLevelling ) { this->UpdateReslicePlane(); } this->ImageActor->SetDisplayExtent(this->ColorMap->GetOutput()->GetExtent()); // Update any text annotations this->ManageTextDisplay(); } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::InitializeReslicePlane() { if ( !this->GetResliceCursor()->GetImage()) { return; } // this->GetResliceCursor()->GetImage()->UpdateInformation(); // Initialize the reslice plane origins. Offset should be zero within // this function here. this->ComputeReslicePlaneOrigin(); // Finally reset the camera to whatever orientation they were staring in this->ResetCamera(); } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::ResetCamera() { // Reset the camera back to the default and the focal point to where // the cursor center is if (this->Renderer) { double center[3], camPos[3], n[3]; this->GetResliceCursor()->GetCenter(center); this->Renderer->GetActiveCamera()->SetFocalPoint(center); const int normalAxis = this->GetCursorAlgorithm()->GetReslicePlaneNormal(); this->GetResliceCursor()->GetPlane(normalAxis)->GetNormal(n); vtkMath::Add( center, n, camPos ); this->Renderer->GetActiveCamera()->SetPosition(camPos); // Reset the camera in response to changes. this->Renderer->ResetCamera(); this->Renderer->ResetCameraClippingRange(); } } //---------------------------------------------------------------------------- // This is the first axis of the reslice on the currently resliced plane // void vtkResliceCursorRepresentation::GetVector1(double v1[3]) { // From the initial view up vector, compute its cross product with the // current plane normal. This is Vector1. Then Vector2 is the cross product // of Vector1 and the normal. double v2[3]; double* p2 = this->PlaneSource->GetPoint2(); double* o = this->PlaneSource->GetOrigin(); // Vector p2 -> o vtkMath::Subtract( p2, o, v2 ); const int planeOrientation = this->GetCursorAlgorithm()->GetReslicePlaneNormal(); vtkPlane *plane = this->GetResliceCursor()->GetPlane(planeOrientation); double planeNormal[3]; plane->GetNormal(planeNormal); vtkMath::Cross( v2, planeNormal, v1 ); vtkMath::Normalize(v1); } //---------------------------------------------------------------------------- // This is the second axis of the reslice on the currently resliced plane // It is orthogonal to v1 and to the plane normal. Note that this is not the // same as the reslice cursor's axes, which need not be orthogonal to each // other. The goal of vector1 and vector2 is to compute the X and Y axes of // the resliced plane. // void vtkResliceCursorRepresentation::GetVector2(double v2[3]) { const int planeOrientation = this->GetCursorAlgorithm()->GetReslicePlaneNormal(); vtkPlane *plane = this->GetResliceCursor()->GetPlane(planeOrientation); double planeNormal[3]; plane->GetNormal(planeNormal); double v1[3]; this->GetVector1(v1); vtkMath::Cross( planeNormal, v1, v2 ); vtkMath::Normalize(v2); } //---------------------------------------------------------------------- // Compute the origin of the reslice plane prior to transformations. // void vtkResliceCursorRepresentation::ComputeReslicePlaneOrigin() { double bounds[6]; this->GetResliceCursor()->GetImage()->GetBounds(bounds); double center[3], imageCenter[3], offset[3]; this->GetResliceCursor()->GetCenter(center); this->GetResliceCursor()->GetImage()->GetCenter(imageCenter); // Offset based on the center of the image and how far from it the // reslice cursor is. This allows us to capture the whole image even // if we resliced in awkward places. for (int i = 0; i < 3; i++) { offset[i] = -fabs(center[i] - imageCenter[i]); } // Now resize the plane based on these offsets. const int planeOrientation = this->GetCursorAlgorithm()->GetReslicePlaneNormal(); // Now set the size of the plane based on the location of the cursor so as to // at least completely cover the viewed region if ( planeOrientation == 1 ) { this->PlaneSource->SetOrigin(bounds[0]+offset[0],center[1],bounds[4]+offset[2]); this->PlaneSource->SetPoint1(bounds[1]-offset[0],center[1],bounds[4]+offset[2]); this->PlaneSource->SetPoint2(bounds[0]+offset[0],center[1],bounds[5]-offset[2]); } else if ( planeOrientation == 2 ) { this->PlaneSource->SetOrigin(bounds[0]+offset[0],bounds[2]+offset[1],center[2]); this->PlaneSource->SetPoint1(bounds[1]-offset[0],bounds[2]+offset[1],center[2]); this->PlaneSource->SetPoint2(bounds[0]+offset[0],bounds[3]-offset[1],center[2]); } else if ( planeOrientation == 0 ) { this->PlaneSource->SetOrigin(center[0],bounds[2]+offset[1],bounds[4]+offset[2]); this->PlaneSource->SetPoint1(center[0],bounds[3]-offset[1],bounds[4]+offset[2]); this->PlaneSource->SetPoint2(center[0],bounds[2]+offset[1],bounds[5]-offset[2]); } } //---------------------------------------------------------------------- void vtkResliceCursorRepresentation::UpdateReslicePlane() { if ( !this->GetResliceCursor()->GetImage() || !this->TexturePlaneActor->GetVisibility() ) { return; } // Reinitialize the reslice plane.. We will recompute everything here. if (this->PlaneSource->GetPoint1()[0] == 0.5 && this->PlaneSource->GetOrigin()[0] == -0.5) { this->InitializeReslicePlane(); } // Calculate appropriate pixel spacing for the reslicing // // this->GetResliceCursor()->UpdateInformation(); double spacing[3]; this->GetResliceCursor()->GetImage()->GetSpacing(spacing); double origin[3]; this->GetResliceCursor()->GetImage()->GetOrigin(origin); int extent[6]; this->GetResliceCursor()->GetImage()->GetExtent(extent); for (int i = 0; i < 3; i++) { if (extent[2*i] > extent[2*i + 1]) { vtkErrorMacro("Invalid extent [" << extent[0] << ", " << extent[1] << ", " << extent[2] << ", " << extent[3] << ", " << extent[4] << ", " << extent[5] << "]." << " Perhaps the input data is empty?"); break; } } const int planeOrientation = this->GetCursorAlgorithm()->GetReslicePlaneNormal(); vtkPlane *plane = this->GetResliceCursor()->GetPlane(planeOrientation); double planeNormal[3]; plane->GetNormal(planeNormal); // Compute the origin of the reslice plane prior to transformations. this->ComputeReslicePlaneOrigin(); this->PlaneSource->SetNormal(planeNormal); this->PlaneSource->SetCenter(plane->GetOrigin()); double planeAxis1[3]; double planeAxis2[3]; double* p1 = this->PlaneSource->GetPoint1(); double* o = this->PlaneSource->GetOrigin(); vtkMath::Subtract( p1, o, planeAxis1 ); double* p2 = this->PlaneSource->GetPoint2(); vtkMath::Subtract( p2, o, planeAxis2 ); // The x,y dimensions of the plane // const double planeSizeX = vtkMath::Normalize(planeAxis1); const double planeSizeY = vtkMath::Normalize(planeAxis2); double normal[3]; this->PlaneSource->GetNormal(normal); this->NewResliceAxes->Identity(); for ( int i = 0; i < 3; i++ ) { this->NewResliceAxes->SetElement(0,i,planeAxis1[i]); this->NewResliceAxes->SetElement(1,i,planeAxis2[i]); this->NewResliceAxes->SetElement(2,i,normal[i]); } const double spacingX = fabs(planeAxis1[0]*spacing[0])+ fabs(planeAxis1[1]*spacing[1])+ fabs(planeAxis1[2]*spacing[2]); const double spacingY = fabs(planeAxis2[0]*spacing[0])+ fabs(planeAxis2[1]*spacing[1])+ fabs(planeAxis2[2]*spacing[2]); double planeOrigin[4]; this->PlaneSource->GetOrigin(planeOrigin); planeOrigin[3] = 1.0; double originXYZW[4]; double neworiginXYZW[4]; this->NewResliceAxes->MultiplyPoint(planeOrigin, originXYZW); this->NewResliceAxes->Transpose(); this->NewResliceAxes->MultiplyPoint(originXYZW, neworiginXYZW); this->NewResliceAxes->SetElement(0,3,neworiginXYZW[0]); this->NewResliceAxes->SetElement(1,3,neworiginXYZW[1]); this->NewResliceAxes->SetElement(2,3,neworiginXYZW[2]); // Compute a new set of resliced extents int extentX, extentY; // Pad extent up to a power of two for efficient texture mapping // make sure we're working with valid values double realExtentX = ( spacingX == 0 ) ? VTK_INT_MAX : planeSizeX / spacingX; // Sanity check the input data: // * if realExtentX is too large, extentX will wrap // * if spacingX is 0, things will blow up. if (realExtentX > (VTK_INT_MAX >> 1)) { vtkErrorMacro(<<"Invalid X extent: " << realExtentX); extentX = 0; } else { extentX = 1; while (extentX < realExtentX) { extentX = extentX << 1; } } // make sure extentY doesn't wrap during padding double realExtentY = ( spacingY == 0 ) ? VTK_INT_MAX : planeSizeY / spacingY; if (realExtentY > (VTK_INT_MAX >> 1)) { vtkErrorMacro(<<"Invalid Y extent: " << realExtentY); extentY = 0; } else { extentY = 1; while (extentY < realExtentY) { extentY = extentY << 1; } } double outputSpacingX = (extentX == 0) ? 1.0 : planeSizeX/extentX; double outputSpacingY = (extentY == 0) ? 1.0 : planeSizeY/extentY; bool modify = false; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { double d = this->NewResliceAxes->GetElement(i,j); if (d != this->ResliceAxes->GetElement(i,j)) { this->ResliceAxes->SetElement(i,j,d); modify = true; } } } if (modify) { this->ResliceAxes->Modified(); } this->SetResliceParameters( outputSpacingX, outputSpacingY, extentX, extentY ); } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::ComputeOrigin(vtkMatrix4x4 *m) { double center[4] = {0,0,0,1}; double centerTransformed[4]; this->GetResliceCursor()->GetCenter(center); m->MultiplyPoint(center, centerTransformed); for (int i = 0; i < 3; i++) { m->SetElement(i, 3, m->GetElement(i,3) + center[i] - centerTransformed[i]); } } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation ::SetResliceParameters( double outputSpacingX, double outputSpacingY, int extentX, int extentY ) { vtkImageReslice *reslice = vtkImageReslice::SafeDownCast(this->Reslice); if (reslice) { // Set the default color the minimum scalar value double range[2]; vtkImageData::SafeDownCast(reslice->GetInput())-> GetScalarRange( range ); reslice->SetBackgroundLevel(range[0]); this->ColorMap->SetInputConnection(reslice->GetOutputPort()); reslice->TransformInputSamplingOff(); reslice->AutoCropOutputOn(); reslice->SetResliceAxes(this->ResliceAxes); reslice->SetOutputSpacing(outputSpacingX, outputSpacingY, 1); reslice->SetOutputOrigin(0.5*outputSpacingX, 0.5*outputSpacingY, 0); reslice->SetOutputExtent(0, extentX-1, 0, extentY-1, 0, 0); } } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation ::SetWindowLevel(double window, double level, int copy) { if ( copy ) { this->CurrentWindow = window; this->CurrentLevel = level; return; } if ( this->CurrentWindow == window && this->CurrentLevel == level ) { return; } // if the new window is negative and the old window was positive invert table if ( (( window < 0 && this->CurrentWindow > 0 ) || ( window > 0 && this->CurrentWindow < 0 )) ) { this->InvertTable(); } this->CurrentWindow = window; this->CurrentLevel = level; double rmin = this->CurrentLevel - 0.5*fabs( this->CurrentWindow ); double rmax = rmin + fabs( this->CurrentWindow ); this->LookupTable->SetRange( rmin, rmax ); this->Modified(); } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::GetWindowLevel(double wl[2]) { wl[0] = this->CurrentWindow; wl[1] = this->CurrentLevel; } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::WindowLevel(double X, double Y) { if ( !this->Renderer ) { return; } int *size = this->Renderer->GetSize(); double window = this->InitialWindow; double level = this->InitialLevel; // Compute normalized delta double dx = 2.0 * ( X - this->StartEventPosition[0] ) / size[0]; double dy = 2.0 * ( this->StartEventPosition[1] - Y ) / size[1]; // Scale by current values if ( fabs( window ) > 0.01 ) { dx = dx * window; } else { dx = dx * ( window < 0 ? -0.01 : 0.01 ); } if ( fabs( level ) > 0.01 ) { dy = dy * level; } else { dy = dy * ( level < 0 ? -0.01 : 0.01 ); } // Abs so that direction does not flip if ( window < 0.0 ) { dx = -1 * dx; } if ( level < 0.0 ) { dy = -1 * dy; } // Compute new window level double newWindow = dx + window; double newLevel = level - dy; if ( fabs( newWindow ) < 0.01 ) { newWindow = 0.01 * ( newWindow < 0 ? -1 : 1 ); } if ( fabs( newLevel ) < 0.01 ) { newLevel = 0.01 * ( newLevel < 0 ? -1 : 1 ); } if (( newWindow < 0 && this->CurrentWindow > 0 ) || ( newWindow > 0 && this->CurrentWindow < 0 )) { this->InvertTable(); } double rmin = newLevel - 0.5*fabs( newWindow ); double rmax = rmin + fabs( newWindow ); this->LookupTable->SetRange( rmin, rmax ); if (this->DisplayText && (this->CurrentWindow != newWindow || this->CurrentLevel != newLevel) ) { this->CurrentWindow = newWindow; this->CurrentLevel = newLevel; } } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::InvertTable() { vtkLookupTable *lut = vtkLookupTable::SafeDownCast(this->LookupTable); if ( lut ) { int index = lut->GetNumberOfTableValues(); unsigned char swap[4]; size_t num = 4*sizeof(unsigned char); vtkUnsignedCharArray* table = lut->GetTable(); for ( int count = 0; count < --index; count++ ) { unsigned char *rgba1 = table->GetPointer(4*count); unsigned char *rgba2 = table->GetPointer(4*index); memcpy( swap, rgba1, num ); memcpy( rgba1, rgba2, num ); memcpy( rgba2, swap, num ); } // force the lookuptable to update its InsertTime to avoid // rebuilding the array double temp[4]; lut->GetTableValue( 0, temp ); lut->SetTableValue( 0, temp ); } } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::CreateDefaultResliceAlgorithm() { // Allows users to optionally use their own reslice filters or other // algorithms here. if (!this->Reslice) { this->Reslice = vtkImageReslice::New(); } } //---------------------------------------------------------------------------- vtkScalarsToColors* vtkResliceCursorRepresentation::CreateDefaultLookupTable() { vtkLookupTable* lut = vtkLookupTable::New(); lut->Register(this); lut->Delete(); lut->SetNumberOfColors( 256); lut->SetHueRange( 0, 0); lut->SetSaturationRange( 0, 0); lut->SetValueRange( 0 ,1); lut->SetAlphaRange( 1, 1); lut->Build(); return lut; } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::ActivateText(int i) { this->TextActor->SetVisibility(this->Renderer && this->GetVisibility() && i && this->DisplayText ); } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::ManageTextDisplay() { if ( !this->DisplayText ) { return; } if ( this->ManipulationMode == vtkResliceCursorRepresentation::WindowLevelling ) { snprintf(this->TextBuff, VTK_RESLICE_CURSOR_REPRESENTATION_MAX_TEXTBUFF, "Window, Level: ( %g, %g )", this->CurrentWindow, this->CurrentLevel ); } else if (this->ManipulationMode == vtkResliceCursorRepresentation::ResizeThickness ) { // For now all the thickness' are the same anyway. snprintf(this->TextBuff, VTK_RESLICE_CURSOR_REPRESENTATION_MAX_TEXTBUFF, "Reslice Thickness: %g mm", this->GetResliceCursor()->GetThickness()[0] ); } this->TextActor->SetInput(this->TextBuff); this->TextActor->Modified(); } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::SetTextProperty(vtkTextProperty* tprop) { this->TextActor->SetTextProperty(tprop); } //---------------------------------------------------------------------------- vtkTextProperty* vtkResliceCursorRepresentation::GetTextProperty() { return this->TextActor->GetTextProperty(); } //---------------------------------------------------------------------------- void vtkResliceCursorRepresentation::GenerateText() { snprintf(this->TextBuff, VTK_RESLICE_CURSOR_REPRESENTATION_MAX_TEXTBUFF, "NA"); this->TextActor->SetInput(this->TextBuff); this->TextActor->SetTextScaleModeToNone(); vtkTextProperty* textprop = this->TextActor->GetTextProperty(); textprop->SetColor(1,1,1); textprop->SetFontFamilyToArial(); textprop->SetFontSize(18); textprop->BoldOff(); textprop->ItalicOff(); textprop->ShadowOff(); textprop->SetJustificationToLeft(); textprop->SetVerticalJustificationToBottom(); vtkCoordinate* coord = this->TextActor->GetPositionCoordinate(); coord->SetCoordinateSystemToNormalizedViewport(); coord->SetValue(.01, .01); this->TextActor->VisibilityOff(); } //---------------------------------------------------------------------- // 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 vtkResliceCursorRepresentation::PrintSelf(ostream& os, vtkIndent indent) { //Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h this->Superclass::PrintSelf(os,indent); os << indent << "Tolerance: " << this->Tolerance << "\n"; os << indent << "Thickness Label Text: " << this->GetThicknessLabelText() << "\n"; os << indent << "PlaneSource: " << this->PlaneSource << "\n"; if (this->PlaneSource) { this->PlaneSource->PrintSelf(os,indent.GetNextIndent()); } os << indent << "PlaneSource: " << this->PlaneSource << "\n"; vtkPrintMemberObjectMacro( ThicknessLabelFormat, os, indent ); vtkPrintMemberObjectMacro( Reslice, os, indent ); vtkPrintMemberObjectMacro( ThicknessTextProperty, os, indent ); vtkPrintMemberObjectMacro( ThicknessTextMapper, os, indent ); vtkPrintMemberObjectMacro( ThicknessTextActor, os, indent ); vtkPrintMemberObjectMacro( ResliceAxes, os, indent ); vtkPrintMemberObjectMacro( NewResliceAxes, os, indent ); vtkPrintMemberObjectMacro( ColorMap, os, indent ); vtkPrintMemberObjectMacro( TexturePlaneActor, os, indent ); vtkPrintMemberObjectMacro( Texture, os, indent ); vtkPrintMemberObjectMacro( LookupTable, os, indent ); vtkPrintMemberObjectMacro( ImageActor, os, indent ); vtkPrintMemberObjectMacro( TextActor, os, indent ); os << indent << "RestrictPlaneToVolume: " << this->RestrictPlaneToVolume << "\n"; os << indent << "ShowReslicedImage: " << this->ShowReslicedImage << "\n"; os << indent << "OriginalWindow: " << this->OriginalWindow << "\n"; os << indent << "OriginalLevel: " << this->OriginalLevel << "\n"; os << indent << "CurrentWindow: " << this->CurrentWindow << "\n"; os << indent << "CurrentLevel: " << this->CurrentLevel << "\n"; os << indent << "InitialWindow: " << this->InitialWindow << "\n"; os << indent << "InitialLevel: " << this->InitialLevel << "\n"; os << indent << "UseImageActor: " << this->UseImageActor << "\n"; os << indent << "DisplayText: " << this->DisplayText << "\n"; // this->ManipulationMode // this->LastEventPosition[2] // this->TextBuff[128]; // this->ResliceAxes; // this->LookupTable; // this->Reslice; // this->ThicknessLabelFormat; // this->ColorMap; // this->ImageActor; // this->ThicknessTextProperty; // this->ThicknessTextMapper; // this->ThicknessTextActor; // this->NewResliceAxes; // this->TexturePlaneActor; // this->Texture; // this->TextActor; }