/*========================================================================= Program: vtkINRIA3D Module: $Id: vtkViewImage.cxx 1315 2009-ViewImage11-03 12:13:28Z acanale $ Language: C++ Author: $Author: acanale $ Date: $Date: 2009-11-03 13:13:28 +0100 (Tue, 03 Nov 2009) $ Version: $Revision: 1315 $ Copyright (c) 2007 INRIA - Asclepios Project. All rights reserved. See Copyright.txt 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 notices for more information. =========================================================================*/ #include "vtkViewImage.h" #include "vtkObjectFactory.h" #include "vtkProp.h" #include "vtkTextActor.h" #include "vtkCoordinate.h" #include "vtkProperty.h" #include "vtkProperty2D.h" #include "vtkTextProperty.h" #include "vtkScalarsToColors.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkImageData.h" #include "vtkActor.h" #include "vtkRenderWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include vtkCxxRevisionMacro(vtkViewImage, "$Revision: 1315 $"); vtkStandardNewMacro(vtkViewImage); vtkViewImage::vtkViewImage() { this->Image = 0; this->MaskImage = 0; this->OverlappingImage = 0; this->MaskLUT = 0; this->Transform = 0; this->LookupTable = 0; this->LinkWindowLevel = 1; this->LinkPosition = 1; this->LinkZoom = 0; this->LinkVolumeIndex = 0; this->FirstImage = 1; this->FirstResetWindowLevel = 1; this->Visibility = 1; this->SizeDataVisibility = 1; this->Shift = 0.0; this->Scale = 1.0; this->Level = 128.0; this->Window = 255.0; this->LevelForReset = 128.0; this->WindowForReset = 255.0; this->Zoom = 1.0; this->ScalarBar = vtkScalarBarActor::New(); this->ScalarBar->GetLabelTextProperty()->SetColor (1.0,1.0,1.0); this->ScalarBar->GetTitleTextProperty()->SetColor (1.0,1.0,1.0); //this->ScalarBar->SetTextPositionToPrecedeScalarBar(); this->ScalarBar->GetLabelTextProperty()->BoldOff(); this->ScalarBar->GetLabelTextProperty()->ShadowOff(); this->ScalarBar->GetLabelTextProperty()->ItalicOff(); this->ScalarBar->SetNumberOfLabels (3); this->ScalarBar->GetLabelTextProperty()->SetFontSize (1); this->ScalarBar->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport(); this->ScalarBar->SetWidth (0.1); this->ScalarBar->SetHeight (0.5); this->ScalarBar->SetPosition (0.9,0.3); //this->ScalarBar->GetPositionCoordinate()->SetValue ( 0.1, 0.01); this->ScalarBar->PickableOff(); this->ScalarBar->VisibilityOff(); vtkLookupTable* bwLut = vtkLookupTable::New(); bwLut->SetTableRange (0, 1); bwLut->SetSaturationRange (0, 0); bwLut->SetHueRange (0, 0); bwLut->SetValueRange (0, 1); bwLut->SetAlphaRange (0, 1); bwLut->Build(); this->SetLookupTable (bwLut); bwLut->Delete(); this->CurrentPoint[0] = 0.0; this->CurrentPoint[1] = 0.0; this->CurrentPoint[2] = 0.0; this->ResetWindowLevelMode = UserDefinedPercentage; this->WindowLevelPercentage = 0.1; // Increase polygon offsets to support some OpenGL drivers //vtkMapper::SetResolveCoincidentTopologyToPolygonOffset(); //vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(10,10); this->DirectionMatrix = vtkMatrix4x4::New(); this->DirectionMatrix->Identity(); this->VolumeIndex = 0; } vtkViewImage::~vtkViewImage() { if( this->Transform ) { this->Transform->Delete(); } if( this->Image ) { this->Image->Delete(); } this->ScalarBar->Delete(); this->RemoveAllDataSet(); this->DirectionMatrix->Delete(); } void vtkViewImage::Initialize() { vtkSynchronizedView::Initialize(); this->SetLookupTable( this->GetLookupTable() ); this->AddActor (this->ScalarBar); } void vtkViewImage::Uninitialize() { this->RemoveActor (this->ScalarBar); vtkSynchronizedView::Uninitialize(); } void vtkViewImage::RegisterImage(vtkImageData* image) { if(!image) return; if( image != this->Image ) { if( this->Image != NULL ) { this->Image->UnRegister (this); } this->Image = image; this->Image->Register (this); } } double vtkViewImage::GetWholeMinPosition(unsigned int p_axis) { if(!this->Image) { return -VTK_LARGE_FLOAT; } return this->Image->GetBounds()[p_axis * 2]; } double vtkViewImage::GetWholeMaxPosition(unsigned int p_axis) { if(!this->Image) { return VTK_LARGE_FLOAT; } return this->Image->GetBounds()[p_axis * 2 + 1]; } unsigned int vtkViewImage::GetOrthogonalAxis(unsigned int p_plan) { assert(p_planGetDirectionMatrix(), t_directions); //this->GetDirectionMatrix()->MultiplyPoint (axisVec, axisVec); t_directions->MultiplyPoint (axisVec, axisVec); t_directions->Delete(); for (int i=0; i<3; i++) if (fabs (axisVec[i])>0.0 ) { axis = i; break; } /* switch(p_plan) { case SAGITTAL_ID: return X_ID; break; case CORONAL_ID: return Y_ID; break; case AXIAL_ID: return Z_ID; break; } return 0; */ return axis; } int vtkViewImage::GetSliceForPosition(const double pos[3], unsigned int p_plan) { if( !this->GetImage() ) { return 0; } assert(p_plan < NB_DIRECTION_IDS); double* spacing = this->GetImage()->GetSpacing(); double* origin = this->GetImage()->GetOrigin(); int axis = this->GetOrthogonalAxis(p_plan); double soft_pos = pos[axis]; // Treat extreme position at the end of the last pixel /* double pos_max = this->GetWholeMaxPosition(axis); double pos_min = this->GetWholeMinPosition(axis); if ((soft_pos > pos_max-0.005) && (soft_pos < pos_max+0.005)) { soft_pos = pos_max-0.005; } if ((soft_pos > pos_min-0.005) && (soft_pos < pos_min+0.005)) { soft_pos = pos_min+0.005; } */ return (int)vtkMath::Round((soft_pos-origin[axis])/spacing[axis]); } int vtkViewImage::GetSlice(unsigned int p_plan) { const double* pos = this->GetCurrentPoint(); return this->GetSliceForPosition (pos, p_plan); } void vtkViewImage::SetSlice (unsigned int p_plan, int p_zslice) { double pos[3]; this->GetPositionForSlice (p_zslice, p_plan, pos); this->SetCurrentPoint(pos); } void vtkViewImage::GetPositionForSlice (int p_zslice, int orientation, double pos[3]) { if( !this->GetImage() ) { return; } unsigned int axis = this->GetOrthogonalAxis(orientation); double* spacing = this->GetImage()->GetSpacing(); int* extent = this->GetImage()->GetWholeExtent(); double* origin = this->GetImage()->GetOrigin(); int slice = p_zslice; if(slice > extent[2*axis+1]) slice = extent[2*axis+1]; if(slice < extent[2*axis]) slice = extent[2*axis]; this->GetCurrentPoint(pos); pos[axis] = origin[axis] + slice * spacing[axis]; } void vtkViewImage::SyncSetSlice(unsigned int p_plan, int p_zslice) { if( this->IsLocked() ) { return; } if (this->GetLinkPosition()) { this->SetSlice(p_plan, p_zslice); } this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view /*&& view->GetLinkPosition()*/) { view->SyncSetSlice (p_plan, p_zslice); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncSetZSlice(int p_zslice) { if( this->IsLocked() ) { return; } if (this->GetLinkPosition()) { this->SetZSlice(p_zslice); } this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view /*&& view->GetLinkPosition()*/) { view->SyncSetZSlice (p_zslice); view->Update(); } } this->UnLock(); } void vtkViewImage::SetCurrentPoint (const double p_point[3]) { this->CurrentPoint[0] = p_point[0]; this->CurrentPoint[1] = p_point[1]; this->CurrentPoint[2] = p_point[2]; this->UpdatePosition(); this->InvokeEvent (vtkViewImage::ViewImagePositionChangeEvent, NULL); } void vtkViewImage::GetVoxelCoordinates(double pos[3], int p_coordinates[3]) { if(!this->Image) { return; } p_coordinates[this->GetOrthogonalAxis(SAGITTAL_ID)] = this->GetSliceForPosition(pos, SAGITTAL_ID); p_coordinates[this->GetOrthogonalAxis(CORONAL_ID)] = this->GetSliceForPosition(pos, CORONAL_ID); p_coordinates[this->GetOrthogonalAxis(AXIAL_ID)] = this->GetSliceForPosition(pos, AXIAL_ID); } void vtkViewImage::GetCurrentVoxelCoordinates(int p_coordinates[3]) { p_coordinates[this->GetOrthogonalAxis(SAGITTAL_ID)] = this->GetSlice(SAGITTAL_ID); p_coordinates[this->GetOrthogonalAxis(CORONAL_ID)] = this->GetSlice(CORONAL_ID); p_coordinates[this->GetOrthogonalAxis(AXIAL_ID)] = this->GetSlice(AXIAL_ID); } void vtkViewImage::SyncSetCurrentPoint(const double p_point[3]) { if( this->IsLocked() ) { return; } if (this->GetLinkPosition()) { this->SetCurrentPoint (p_point); } this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast( this->Children[i] ); if( view /*&& view->GetLinkPosition()*/) { view->SyncSetCurrentPoint (p_point); view->Update(); } } this->UnLock(); } double vtkViewImage::GetCurrentPointDoubleValue () { if (!this->Image) { return -1; } int coordinates[3]; this->GetCurrentVoxelCoordinates(coordinates); void *scalar = this->GetImage()->GetScalarPointer(coordinates); if( !scalar ) return -1.0; switch (this->GetImage()->GetScalarType()) { case VTK_DOUBLE: return (*(double*)scalar); case VTK_FLOAT: return (double) (*(float*)scalar); case VTK_UNSIGNED_LONG: return (double) (*(unsigned long*)scalar); case VTK_LONG: return (double) (*(long*)scalar); case VTK_UNSIGNED_INT: return (double) (*(unsigned int*)scalar); case VTK_INT: return (double) (*(int*)scalar); case VTK_UNSIGNED_SHORT: return (double) (*(unsigned short*)scalar); case VTK_SHORT: return (double) (*(short*)scalar); case VTK_UNSIGNED_CHAR: return (double) (*(unsigned char*)scalar); case VTK_CHAR: return (double) (*(char*)scalar); } return -1; } void vtkViewImage::SyncResetCurrentPoint() { if( this->IsLocked() ) { return; } if (this->GetLinkPosition()) { this->ResetCurrentPoint(); } this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast( this->Children[i] ); if( view /*&& view->GetLinkPosition()*/ ) { view->SyncResetCurrentPoint (); view->Update(); } } this->UnLock(); } void vtkViewImage::ResetCurrentPoint() { if (!this->Image) { return; } double* bounds = this->GetImage()->GetBounds(); double pos[3] = { (bounds[0]+bounds[1])/2.0, (bounds[2]+bounds[3])/2.0, (bounds[4]+bounds[5])/2.0 }; this->SetCurrentPoint(pos); } void vtkViewImage::SyncSetWindow (double w) { if( this->IsLocked() ) { return; } if (this->GetLinkWindowLevel()) { this->SetWindow (w); } // this boolean is used so that the other observe won't call // SetCurrentPoint again and again and again... this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view /*&& view->GetLinkWindowLevel()*/ ) { view->SyncSetWindow (w); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncStartWindowing () { if( this->IsLocked() ) { return; } if (this->GetLinkWindowLevel()) { this->StartWindowing (); } // this boolean is used so that the other observe won't call // SetCurrentPoint again and again and again... this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view /*&& view->GetLinkWindowLevel()*/ ) { view->SyncStartWindowing (); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncEndWindowing () { if( this->IsLocked() ) { return; } if (this->GetLinkWindowLevel()) { this->EndWindowing (); } // this boolean is used so that the other observe won't call // SetCurrentPoint again and again and again... this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view /*&& view->GetLinkWindowLevel()*/ ) { view->SyncEndWindowing (); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncSetLevel (double l) { if( this->IsLocked() ) { return; } if (this->GetLinkWindowLevel()) { this->SetLevel (l); } // this boolean is used so that the other observe won't call // SetCurrentPoint again and again and again... this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view /*&& view->GetLinkWindowLevel()*/ ) { view->SyncSetLevel (l); view->Update(); } } this->UnLock(); } void vtkViewImage::SetWindowLevelFrom(vtkViewImage* p_view) { if (p_view) { this->SetWindow( p_view->GetWindow() ); this->SetLevel( p_view->GetLevel() ); } } void vtkViewImage::SyncResetWindowLevel() { if( this->IsLocked() ) { return; } if (this->GetLinkWindowLevel()) { this->ResetWindowLevel(); } this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast(this->Children[i]); if( view /*&& view->GetLinkWindowLevel()*/ ) { view->SyncResetWindowLevel (); view->Update(); } } this->UnLock(); } void vtkViewImage::ResetWindowLevel() { if (!this->Image) { return; } this->Image->UpdateInformation(); int* extent = this->Image->GetWholeExtent(); if( extent[0]==extent[1] && extent[2]==extent[3] && extent[4]==extent[5] ) // image has a null extent -> GetScalarRange() will crash { return; } this->Image->SetUpdateExtentToWholeExtent(); this->Image->Update(); if( this->Image->GetScalarType() == VTK_UNSIGNED_CHAR && (this->Image->GetNumberOfScalarComponents()==3 || this->Image->GetNumberOfScalarComponents()==4) ) { return; } double* range = this->Image->GetScalarRange(); double window = range[1]-range[0]; double level = 0.5*(range[1]+range[0]); if( this->ResetWindowLevelMode == FullRange ) { // nothing to do } else if( this->ResetWindowLevelMode == UserDefinedPercentage ) { if( this->FirstResetWindowLevel ) { vtkImageAccumulate* histogram = vtkImageAccumulate::New(); histogram->SetInput ( this->Image ); int binCounts = 1000; int h_extent[6] = {0, binCounts-1, 0, 0, 0, 0}; histogram->SetComponentExtent (h_extent); double spacing[3] = { (range[1]-range[0])/(double)(binCounts), 0.0, 0.0}; histogram->SetComponentSpacing (spacing); double origin[3] = {range[0], 0.0, 0.0}; histogram->SetComponentOrigin (origin); histogram->Update(); vtkImageData* output = histogram->GetOutput(); vtkIntArray* ptData = vtkIntArray::SafeDownCast (output->GetPointData()->GetScalars()); if( !ptData) { vtkErrorMacro( << "Error: Cannot cast point data to integers."); return; } double voxelCount = histogram->GetVoxelCount(); double onePercent = voxelCount/100.0; int start=1; double currentPercent = 0.0; while( currentPercentWindowLevelPercentage && startGetTuple (start, &tuple); currentPercent += tuple/onePercent; start++; } currentPercent = 0.0; int end = binCounts-1; while( currentPercentWindowLevelPercentage && end>0 ) { double tuple; ptData->GetTuple (end, &tuple); currentPercent += tuple/onePercent; end--; } double binLength = (range[1]-range[0])/(double)binCounts; window = (end-start)*binLength; level = 0.5*(start + end)*binLength; this->WindowForReset = window; this->LevelForReset = level; this->FirstResetWindowLevel = 0; histogram->Delete(); } else { window = this->WindowForReset; level = this->LevelForReset; } } window = (window-this->GetShift())/this->GetScale(); level = (level-this->GetShift())/this->GetScale(); this->SetWindow ( window ); this->SetLevel ( level ); } bool vtkViewImage::HasDataSet (vtkDataSet* dataset) { if( !dataset ) { return false; } bool res = false; for( unsigned int i=0; iDataSetList.size(); i++) { if( dataset == this->DataSetList[i] ) { res = true; break; } } return res; } vtkActor* vtkViewImage::SyncAddDataSet (vtkDataSet* dataset, vtkProperty* property) { if( this->IsLocked() ) { return NULL; } vtkActor* actor = this->AddDataSet (dataset, property); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncAddDataSet (dataset, property); } } this->UnLock(); return actor; } vtkActor* vtkViewImage::AddDataSet (vtkDataSet* dataset, vtkProperty* property) { vtkErrorMacro(<<"You should not use this function here\nPlease use vtkViewImage2D or vtkViewImage3D classes instead (or any derived class)."); return NULL; } void vtkViewImage::SyncRemoveDataSet (vtkDataSet* dataset) { if( this->IsLocked() ) { return; } this->RemoveDataSet (dataset); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncRemoveDataSet (dataset); } } this->UnLock(); } void vtkViewImage::RemoveDataSet (vtkDataSet* dataset) { if (!dataset) { return; } std::vector t_actorlist = this->DataSetActorList; std::vector t_datasetlist = this->DataSetList; this->DataSetActorList.clear(); this->DataSetList.clear(); for (unsigned int i=0; iDataSetList.push_back (t_datasetlist[i]); this->DataSetActorList.push_back (t_actorlist[i]); } else { this->RemoveActor (t_actorlist[i]); } } } void vtkViewImage::SyncRemoveAllDataSet () { if( this->IsLocked() ) { return; } this->RemoveAllDataSet (); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncRemoveAllDataSet (); } } this->UnLock(); } void vtkViewImage::RemoveAllDataSet () { for (unsigned int i=0; iDataSetActorList.size(); i++) { this->RemoveActor (this->DataSetActorList[i]); } this->DataSetActorList.clear(); this->DataSetList.clear(); } void vtkViewImage::SyncModifyActors(vtkDataSet* dataset, bool cellColors) { if( this->IsLocked() ) { return; } this->ModifyActors (dataset, cellColors); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncModifyActors (dataset, cellColors); } } this->UnLock(); } void vtkViewImage::ModifyActors(vtkDataSet* dataset, bool cellColors) { bool doit = true; if (!dataset) { doit = false; } vtkMapper* mapper = NULL; if (doit) { for (unsigned int i=0; iDataSetList.size(); i++) { if (dataset == this->DataSetList[i]) { mapper = this->DataSetActorList[i]->GetMapper(); break; } } if (!mapper) { doit = false; } } if (doit) { mapper->Modified(); if ( cellColors ) mapper->SetScalarModeToUseCellData(); else mapper->SetScalarModeToUsePointData(); } } void vtkViewImage::SyncColorDataSetByArray(vtkDataSet* dataset, const char* arrayname, vtkColorTransferFunction* transfer) { if( this->IsLocked() ) { return; } this->ColorDataSetByArray (dataset, arrayname, transfer); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncColorDataSetByArray (dataset, arrayname, transfer); } } this->UnLock(); } void vtkViewImage::ColorDataSetByArray(vtkDataSet* dataset, const char* arrayname, vtkColorTransferFunction* transfer) { bool doit = true; if (!dataset) { doit = false; } vtkDataArray* array = NULL; vtkMapper* mapper = NULL; if (doit) { for (unsigned int i=0; iDataSetList.size(); i++) { if (dataset == this->DataSetList[i]) { mapper = this->DataSetActorList[i]->GetMapper(); break; } } if (!mapper) { doit = false; } } if (doit) { mapper->Modified(); if (dataset->GetCellData()) { array = dataset->GetCellData()->GetArray (arrayname); if (array) { mapper->SetScalarModeToUseCellFieldData(); } } if (!array && dataset->GetPointData()) { array = dataset->GetPointData()->GetArray (arrayname); if (array) { mapper->SetScalarModeToUsePointFieldData(); } } if (!array) { mapper->SetScalarModeToDefault(); mapper->SetInterpolateScalarsBeforeMapping(0); doit = false; } } if (doit) { mapper->SetLookupTable (transfer); mapper->SetScalarRange (array->GetRange()[0], array->GetRange()[1]); mapper->SetInterpolateScalarsBeforeMapping(1); mapper->SelectColorArray (array->GetName()); } } vtkDataSet* vtkViewImage::GetDataSet (unsigned int i) { if ( i>=this->DataSetList.size() ) return NULL; return this->DataSetList[i]; } vtkDataSet* vtkViewImage::GetDataSetFromActor (vtkActor* actor) { for (unsigned int i=0; iDataSetActorList.size(); i++) { if (actor == this->DataSetActorList[i]) return this->DataSetList[i]; } return NULL; } vtkActor* vtkViewImage::GetDataSetActor (unsigned int i) { if ( i>=this->DataSetActorList.size() ) return NULL; return this->DataSetActorList[i]; } vtkActor* vtkViewImage::GetDataSetActor (vtkDataSet* dataset) { if (!dataset) return NULL; for (unsigned int i=0; iDataSetList.size(); i++) { if (dataset == this->DataSetList[i]) return this->DataSetActorList[i]; } return NULL; } void vtkViewImage::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } void vtkViewImage::SyncSetZoom (double factor) { if( this->IsLocked() ) { return; } if (this->GetLinkZoom()) { this->SetZoom (factor); } this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view /*&& view->GetLinkZoom()*/ ) { view->SyncSetZoom (factor); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncSetLookupTable (vtkScalarsToColors* lut) { if( this->IsLocked() ) { return; } this->SetLookupTable (lut); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncSetLookupTable (lut); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncResetZoom () { if( this->IsLocked() ) { return; } if (this->GetLinkZoom()) { this->ResetZoom (); } this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncResetZoom (); view->Update(); } } this->UnLock(); } void vtkViewImage::ResetZoom() { this->ResetCamera(); this->Zoom = 1.0; } void vtkViewImage::SyncReset () { if( this->IsLocked() ) { return; } this->Reset (); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncReset (); view->Update(); } } this->UnLock(); } void vtkViewImage::SetSizeData (const char* str) { this->SizeData_str = str; this->Modified(); } void vtkViewImage::SetPatientNameData (const char* str) { this->PatientNameData = str; this->Modified(); } void vtkViewImage::SetStudyNameData (const char* str) { this->StudyNameData = str; this->Modified(); } void vtkViewImage::SetSerieNameData (const char* str) { this->SerieNameData = str; this->Modified(); } void vtkViewImage::SetSizeDataVisibility (int val) { this->SizeDataVisibility = val; if( val ) { this->SetUpLeftAnnotation ( this->GetSizeData() ); } else { this->SetUpRightAnnotation (""); } } void vtkViewImage::SyncSetMaskImage (vtkImageData* mask, vtkLookupTable* lut) { if( this->IsLocked() ) { return; } this->SetMaskImage (mask, lut); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncSetMaskImage (mask, lut); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncSetOverlappingImage (vtkImageData* image) { if( this->IsLocked() ) { return; } this->SetOverlappingImage (image); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncSetOverlappingImage (image); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncRemoveMaskImage () { if( this->IsLocked() ) { return; } this->RemoveMaskImage (); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncRemoveMaskImage (); view->Update(); } } this->UnLock(); } void vtkViewImage::SyncRemoveOverlappingImage () { if( this->IsLocked() ) { return; } this->RemoveOverlappingImage (); this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncRemoveOverlappingImage (); view->Update(); } } this->UnLock(); } void vtkViewImage::SetDirectionMatrix (vtkMatrix4x4 *mat) { if (!mat) return; this->DirectionMatrix->DeepCopy (mat); double A[3][3]; double Q[3][3]; double M[3][3]; for (int i=0; i<3; i++) for (int j=0; j<3; j++) A[i][j] = mat->GetElement (i,j); vtkMath::Orthogonalize3x3 (A, Q); double detQ = vtkMath::Determinant3x3 (Q); // copy-pasted from nifti1_io.c: nifti_mat44_to_orientation() double vbest = -666.0; int ibest = 1; int jbest = 2; int kbest = 3; int pbest = 1; int qbest = 1; int rbest = 1; for( int i=1; i <= 3; i++ ) { for( int j=1; j <= 3; j++ ) { if( i == j ) continue; for( int k=1; k <= 3; k++ ) { if( i == k || j == k ) continue; A[0][0] = A[0][1] = A[0][2] = A[1][0] = A[1][1] = A[1][2] = A[2][0] = A[2][1] = A[2][2] = 0.0; for( int p=-1; p <= 1; p+=2 ) { for( int q=-1; q <= 1; q+=2 ) { for( int r=-1; r <= 1; r+=2 ) { A[0][i-1] = p; A[1][j-1] = q; A[2][k-1] = r; double detA = vtkMath::Determinant3x3(A); if( detA * detQ <= 0.0 ) continue; vtkMath::Multiply3x3 (A, Q, M); double val = M[0][0] + M[1][1] + M[2][2]; if( val > vbest ) { vbest = val; ibest = i; jbest = j; kbest = k; pbest = p; qbest = q; rbest = r; } } } } } } } this->DirectionMatrix->Zero(); this->DirectionMatrix->SetElement (ibest-1, 0, pbest); this->DirectionMatrix->SetElement (jbest-1, 1, qbest); this->DirectionMatrix->SetElement (kbest-1, 2, rbest); this->DirectionMatrix->SetElement (3, 3, 1.0); this->Modified(); } void vtkViewImage::SyncSetVolumeIndex (vtkIdType volumeIndex) { if( this->IsLocked() ) { return; } if (this->GetLinkVolumeIndex()) { this->SetVolumeIndex (volumeIndex); } this->Lock(); for( unsigned int i=0; iChildren.size(); i++) { vtkViewImage* view = vtkViewImage::SafeDownCast (this->Children[i]); if( view ) { view->SyncSetVolumeIndex (volumeIndex); view->Update(); } } this->UnLock(); } //---------------------------------------------------------------------------- void vtkViewImage::SetVolumeIndex ( vtkIdType index ) { if ( this->VolumeIndex != index ) { this->VolumeIndex = index; this->GetImage ()->UpdateInformation (); this->GetImage ()->PropagateUpdateExtent (); this->InvokeEvent( vtkViewImage::ViewImageVolumeIndexChangedEvent ); this->Modified (); } }