#include "vtkKWMeshVisu.h" #include "vtkKWApplication.h" #include "vtkKWFrame.h" #include "vtkKWColorTransferFunctionEditor.h" #include "vtkKWMenuButton.h" #include "vtkKWMenuButtonWithSpinButtons.h" #include "vtkKWMenuButtonWithSpinButtonsWithLabel.h" #include "vtkKWNotebook.h" #include "vtkKWRenderWidget.h" #include "vtkKWWindow.h" #include "vtkObjectFactory.h" #include "vtkKWMenu.h" #include "vtkToolkits.h" #include "vtkColorTransferFunction.h" #include "vtkKWPushButtonSet.h" #include "vtkKWPushButton.h" #include "vtkKWLoadSaveDialog.h" #include "vtkKWScaleWithEntry.h" #include "vtkKWScale.h" #include "vtkKWMessageDialog.h" #include "vtkKWChangeColorButton.h" #include #include // ITK-includes #include #include #include #include // VTK-includes #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkActor.h" #include "vtkPointData.h" #include "vtkFloatArray.h" #include "vtkPolyDataNormals.h" #include "vtkGlyph3D.h" #include "vtkTensorGlyph.h" #include "vtkArrowSource.h" #include "vtkSphereSource.h" #include "vtkAssignAttribute.h" #include "vtkProperty.h" #include "vtkTransform.h" #include "vtkTransformPolyDataFilter.h" #include "vtkRenderer.h" #include "vtkCamera.h" #include "vtkBMPWriter.h" #include "vtkWindowToImageFilter.h" #include "vtkPolyLine.h" #include "vtkUnstructuredGrid.h" #include "vtkDataSetMapper.h" #include "vtkPolyDataNormals.h" #include "vtkPolyDataWriter.h" #include "vtkPolyDataReader.h" #include #include #include "argio.hh" //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWMeshVisu ); vtkCxxRevisionMacro(vtkKWMeshVisu, "$Revision: 1.14 $"); //---------------------------------------------------------------------------- vtkKWMeshVisu::vtkKWMeshVisu () { this->vtkMesh = 0 ; this->meshMapper = vtkPolyDataMapper::New(); this->meshActor = 0 ; this->normalFilter = vtkPolyDataNormals::New (); this->arrowGlyphMapper = vtkPolyDataMapper::New(); this->arrowGlyphActor = 0 ; this->arrowGlyphFilter = vtkGlyph3D::New(); this->arrowSource = vtkArrowSource::New(); this->ellipsoidGlyphMapper = vtkPolyDataMapper::New(); this->ellipsoidGlyphActor = 0 ; this->ellipsoidGlyphFilter = vtkTensorGlyph::New(); this->ellipsoidSource = vtkSphereSource::New(); /*vtkTransform *transform = vtkTransform::New() ; transform->Scale(1, 2, 3); vtkTransformPolyDataFilter *transformer = vtkTransformPolyDataFilter::New(); transformer->SetInputConnection(ellipsoidSource->GetOutputPort()); transformer->SetTransform(transform); this->ellipsoidSource = transformer->GetOutput(); */ this->opacityScale = vtkKWScaleWithEntry::New(); this->featureScale = vtkKWScaleWithEntry::New(); this->attributeDimension = 0 ; this->FixedTFunc = 0 ; this->commandLine = false ; this->aPolyLineActor = vtkActor::New() ; } vtkKWMeshVisu::~vtkKWMeshVisu() { if ( this->vtkMesh ) this->vtkMesh->Delete () ; if ( this->meshActor ) this->meshActor->Delete() ; if ( this->arrowGlyphActor ) this->arrowGlyphActor->Delete (); if ( this->ellipsoidGlyphActor ) this->ellipsoidGlyphActor->Delete (); if ( this->aPolyLineActor ) this->aPolyLineActor->Delete() ; this->meshMapper->Delete(); this->normalFilter->Delete(); this->arrowGlyphMapper->Delete(); this->arrowGlyphFilter->Delete(); this->arrowSource->Delete(); this->ellipsoidGlyphMapper->Delete(); this->ellipsoidGlyphFilter->Delete(); this->ellipsoidSource->Delete(); this->opacityScale->Delete(); this->featureScale->Delete(); if ( this->FixedTFunc ) this->FixedTFunc->Delete(); if ( this->commandLine ) { this->win->Close(); this->DistanceMapTFunc->Delete(); this->PValueTFunc->Delete(); this->RenderWidget->Delete(); this->win->Delete(); } } int vtkKWMeshVisu::Run(int argc, char *argv[]) { vtkKWChangeColorButton *ccb ; vtkKWMenuButtonWithSpinButtonsWithLabel *colormode_menubutton; vtkKWPushButtonSet *filebuttons ; vtkKWApplication *app ; // Process some command-line arguments // The --test option here is used to run this example as a non-interactive // test for software quality purposes. You can ignore it. int option_test = 0; vtksys::CommandLineArguments args; args.Initialize(argc, argv); args.AddArgument( "--test", vtksys::CommandLineArguments::NO_ARGUMENT, &option_test, ""); args.Parse(); // Create the application // If --test was provided, ignore all registry settings, and exit silently // Restore the settings that have been saved to the registry, like // the geometry of the user interface so far. app = this->GetApplication(); app->SetName("KWMeshVisu"); if (option_test) { app->SetRegistryLevel(0); app->PromptBeforeExitOff(); } app->RestoreApplicationSettingsFromRegistry(); // Add a window // Set 'SupportHelp' to automatically add a menu entry for the help link this->win = vtkKWWindow::New(); this->win->SupportHelpOn(); app->AddWindow(this->win); this->win->Create(); this->win->SecondaryPanelVisibilityOff(); if ( !this->commandLine ) { // Set a help link. Can be a remote link (URL), or a local file app->SetHelpDialogStartingPage("http://www.kwwidgets.org"); } // Populate file menu if ( !this->commandLine ) { vtkKWMenu *file_menu = this->win->GetFileMenu() ; file_menu->InsertCommand(0, "Load Mesh", this, "LoadMeshCallback"); file_menu->InsertCommand(1, "Load 1D Attribute", this, "Load1DAttributeCallback"); file_menu->InsertCommand(2, "Load 3D Attribute", this, "Load3DAttributeCallback"); file_menu->InsertCommand(3, "Load Ellipsoid Field", this, "LoadEllipsoidFieldCallback"); file_menu->InsertCommand(4, "Load Curve", this, "LoadCurveCallback"); file_menu->InsertCommand(5, "Clean Attributes", this, "CleanAttributeCallback"); file_menu->InsertCommand(6, "Load Attribute Mesh", this, "LoadAttributeMeshCallback"); file_menu->InsertCommand(7, "Save Attribute Mesh", this, "SaveAttributeMeshCallback"); file_menu->InsertCommand(8, "Get Camera", this, "GetCameraCallback"); file_menu->InsertSeparator (9) ; // Also add push butttons for file menu options filebuttons = vtkKWPushButtonSet::New(); filebuttons->SetParent(this->win->GetMainPanelFrame()); filebuttons->Create(); filebuttons->SetPadX(2); filebuttons->SetPadY(2); filebuttons->SetBorderWidth(2); filebuttons->SetReliefToGroove(); filebuttons->ExpandWidgetsOn(); filebuttons->SetWidgetsPadY(1); app->Script("pack %s -expand n -fill x -padx 2 -pady 2", filebuttons->GetWidgetName()); vtkKWPushButton *pb = filebuttons->AddWidget(0); pb->SetText("Load Mesh"); pb->SetCommand(this, "LoadMeshCallback"); pb = filebuttons->AddWidget(1); pb->SetText("Load 1D Attribute"); pb->SetCommand(this, "Load1DAttributeCallback"); pb = filebuttons->AddWidget(2); pb->SetText("Load 3D Attribute"); pb->SetCommand(this, "Load3DAttributeCallback"); pb = filebuttons->AddWidget(3); pb->SetText("Load Ellipsoid Field"); pb->SetCommand(this, "LoadEllipsoidFieldCallback"); pb = filebuttons->AddWidget(4); pb->SetText("Load Curve"); pb->SetCommand(this, "LoadCurveCallback"); pb = filebuttons->AddWidget(5); pb->SetText("Clean Attributes"); pb->SetCommand(this, "CleanAttributesCallback"); pb = filebuttons->AddWidget(6); pb->SetText("Load Attribute Mesh"); pb->SetCommand(this, "LoadAttributeMeshCallback"); pb = filebuttons->AddWidget(7); pb->SetText("Save Attribute Mesh"); pb->SetCommand(this, "SaveAttributeMeshCallback"); pb = filebuttons->AddWidget(8) ; pb->SetText("Get Camera"); pb->SetCommand(this, "GetCameraCallback"); } // Add a render widget, attach it to the view frame, and pack this->RenderWidget = vtkKWRenderWidget::New(); this->RenderWidget->SetParent(this->win->GetViewFrame()); this->RenderWidget->Create(); this->RenderWidget->SetRendererBackgroundColor(0, 0, 0); if ( this->commandLine ) { this->RenderWidget->OffScreenRenderingOn(); } app->Script("pack %s -expand y -fill both -anchor c -expand y", this->RenderWidget->GetWidgetName()); if ( !this->commandLine ) { // Create a menu button to control the orientation colormode_menubutton = vtkKWMenuButtonWithSpinButtonsWithLabel::New(); colormode_menubutton->SetParent(this->win->GetMainPanelFrame()); colormode_menubutton->Create(); colormode_menubutton->SetLabelText("Visualization Mode:"); colormode_menubutton->SetPadX(2); colormode_menubutton->SetPadY(2); colormode_menubutton->SetBorderWidth(2); colormode_menubutton->SetReliefToGroove(); app->Script("pack %s -side top -anchor nw -expand n -fill x -padx 2 -pady 2", colormode_menubutton->GetWidgetName()); this->ColorMode = colormode_menubutton->GetWidget()->GetWidget(); this->ColorMode->GetMenu()->AddRadioButton("P Value", this, "PValueCallback"); this->ColorMode->GetMenu()->AddRadioButton("Distance Map", this, "DistanceMapCallback"); // Create a transfer function editor this->TFuncEditor = vtkKWColorTransferFunctionEditor::New(); this->TFuncEditor->SetParent(this->win->GetMainPanelFrame()); this->TFuncEditor->Create(); this->TFuncEditor->SetPadX(2); this->TFuncEditor->SetPadY(2); this->TFuncEditor->SetBorderWidth(2); this->TFuncEditor->SetReliefToGroove(); this->TFuncEditor->DisableAddAndRemoveOn(); this->TFuncEditor->MidPointVisibilityOff(); this->TFuncEditor->ParameterTicksVisibilityOn(); this->TFuncEditor->SetRangeLabelPositionToTop(); this->TFuncEditor->SetLabelPositionToTop(); this->TFuncEditor->SetFunctionChangingCommand (this->RenderWidget, "Render" ); this->TFuncEditor->SetFunctionChangedCommand (this->RenderWidget, "Render" ); app->Script("pack %s -side top -anchor nw -expand n -fill x -padx 2 -pady 2", this->TFuncEditor->GetWidgetName()); } // Create default color transfer functions for pvalue and distance map this->PValueTFunc = vtkColorTransferFunction::New(); this->PValueTFunc->SetColorSpaceToHSV(); this->DistanceMapTFunc = vtkColorTransferFunction::New(); this->DistanceMapTFunc->SetColorSpaceToHSV(); if ( !this->commandLine ) { this->PValueTFunc->AddHSVPoint(0, 0, 1, 1); this->PValueTFunc->AddHSVPoint(0.05, 0.27, 0.6, 0.97, 0, 1); this->PValueTFunc->AddHSVPoint(1, 0.6, 1, 1); this->UpdateDistanceMapTFunc(); // Set default color mode this->ColorMode->SetValue("P Value"); this->PValueCallback (); this->opacityScale->SetParent(this->win->GetMainPanelFrame()); this->opacityScale->Create(); this->opacityScale->SetRange(0.0, 1.0); this->opacityScale->SetResolution(0.01); this->opacityScale->GetScale()->SetLength(350); this->opacityScale->SetValue(1.0); this->opacityScale->SetLabelText("Mesh Opacity:"); this->opacityScale->SetLabelPositionToTop(); this->opacityScale->SetEntryPositionToTop(); this->opacityScale->RangeVisibilityOn(); this->opacityScale->SetCommand(this, "OpacityCallback"); app->Script("pack %s -side top -anchor nw -expand n -fill none -padx 2 -pady 6", this->opacityScale->GetWidgetName()); this->featureScale->SetParent(this->win->GetMainPanelFrame()); this->featureScale->Create(); this->featureScale->SetRange(0.0, 20.0); this->featureScale->SetResolution(0.01); this->featureScale->GetScale()->SetLength(350); this->featureScale->SetValue(1.0); this->featureScale->SetLabelText("Feature scale:"); this->featureScale->SetLabelPositionToTop(); this->featureScale->SetEntryPositionToTop(); this->featureScale->RangeVisibilityOn(); this->featureScale->SetCommand(this, "FeatureScaleCallback"); app->Script("pack %s -side top -anchor nw -expand n -fill none -padx 2 -pady 6", this->featureScale->GetWidgetName()); // change background button ccb = vtkKWChangeColorButton::New(); ccb->SetParent(this->win->GetMainPanelFrame()); ccb->Create(); ccb->SetColor(1.0, 0.0, 0.0); ccb->SetLabelPositionToLeft(); ccb->SetLabelText("Set Background Color"); ccb->SetCommand(this->RenderWidget, "SetRendererBackgroundColor"); ccb->SetColor(0, 0, 0); app->Script( "pack %s -side top -anchor nw -expand n -padx 2 -pady 2", ccb->GetWidgetName()); } // Start the application // If --test was provided, do not enter the event loop and run this example // as a non-interactive test for software quality purposes. int ret = 0; this->win->Display(); if ((!option_test) && (!this->commandLine)) { app->Start(argc, argv); ret = app->GetExitStatus(); this->win->Close(); // Deallocate and exit ccb->Delete(); colormode_menubutton->Delete(); filebuttons->Delete(); this->RenderWidget->Delete(); this->TFuncEditor->Delete(); this->DistanceMapTFunc->Delete(); this->PValueTFunc->Delete(); this->win->Delete(); } return ret; } //---------------------------------------------------------------------------- void vtkKWMeshVisu::LoadMeshCallback() { vtkKWLoadSaveDialog *dialog = vtkKWLoadSaveDialog::New() ; dialog->SetParent(this->RenderWidget->GetParentTopLevel()) ; dialog->Create(); dialog->RetrieveLastPathFromRegistry("DataPath"); dialog->SetTitle ("Load Mesh"); dialog->SetFileTypes ("{{ITK Mesh File} {.meta}}"); dialog->SetDefaultExtension (".meta"); if ( dialog->Invoke () == 0 ) { return ; } dialog->SaveLastPathToRegistry("DataPath"); this->LoadMesh (dialog->GetFileName()); dialog->Delete(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::Load1DAttributeCallback() { if ( this->vtkMesh == 0 ) return ; // get the file name for reading the attributes vtkKWLoadSaveDialog *dialog = vtkKWLoadSaveDialog::New() ; dialog->SetParent(this->RenderWidget->GetParentTopLevel()) ; dialog->Create(); dialog->RetrieveLastPathFromRegistry("DataPath"); dialog->SetTitle ("Load 1D Attributes"); dialog->SetFileTypes ("{{Attribute File} {.txt}}"); dialog->SetDefaultExtension (".txt"); if ( dialog->Invoke () == 0 ) { dialog->Delete(); return ; } dialog->SaveLastPathToRegistry("DataPath"); this->LoadScalarField ( dialog->GetFileName() ); dialog->Delete (); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::Load3DAttributeCallback() { if ( this->vtkMesh == 0 ) return ; // get the file name for reading the attributes vtkKWLoadSaveDialog *dialog = vtkKWLoadSaveDialog::New() ; dialog->SetParent(this->RenderWidget->GetParentTopLevel()) ; dialog->Create(); dialog->RetrieveLastPathFromRegistry("DataPath"); dialog->SetTitle ("Load 3D Attributes"); dialog->SetFileTypes ("{{Attribute File} {.txt}}"); dialog->SetDefaultExtension (".txt"); if ( dialog->Invoke () == 0 ) { dialog->Delete(); return ; } dialog->SaveLastPathToRegistry("DataPath"); this->LoadVectorField ( dialog->GetFileName() ) ; dialog->Delete(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::LoadCurveCallback() { if ( this->vtkMesh == 0 ) return ; // get the file name for reading the attributes vtkKWLoadSaveDialog *dialog = vtkKWLoadSaveDialog::New() ; dialog->SetParent(this->RenderWidget->GetParentTopLevel()) ; dialog->Create(); dialog->RetrieveLastPathFromRegistry("DataPath"); dialog->SetTitle ("Load Curve"); dialog->SetFileTypes ("{{Attribute File} {.txt}}"); dialog->SetDefaultExtension (".txt"); if ( dialog->Invoke () == 0 ) { dialog->Delete(); return ; } dialog->SaveLastPathToRegistry("DataPath"); this->LoadCurve( dialog->GetFileName() ) ; dialog->Delete(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::LoadEllipsoidFieldCallback() { if ( this->vtkMesh == 0 ) return ; // get the file name for reading the attributes vtkKWLoadSaveDialog *dialog = vtkKWLoadSaveDialog::New() ; dialog->SetParent(this->RenderWidget->GetParentTopLevel()) ; dialog->Create(); dialog->RetrieveLastPathFromRegistry("DataPath"); dialog->SetTitle ("Load Ellipsoid Field"); dialog->SetFileTypes ("{{Attribute File} {.txt}}"); dialog->SetDefaultExtension (".txt"); if ( dialog->Invoke () == 0 ) { dialog->Delete(); return ; } dialog->SaveLastPathToRegistry("DataPath"); this->LoadEllipsoidField ( dialog->GetFileName() ) ; dialog->Delete(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::CleanAttributesCallback() { if ( this->attributeDimension == 0 ) return ; this->vtkMesh->GetPointData()->Reset(); this->meshMapper->ScalarVisibilityOff (); vtkDataArray *vectors, *tensors ; vectors = this->vtkMesh->GetPointData()->GetVectors() ; tensors = this->vtkMesh->GetPointData()->GetTensors() ; if ( vectors ) { this->RenderWidget->RemoveViewProp(this->arrowGlyphActor); } if ( tensors ) { this->RenderWidget->RemoveViewProp(this->ellipsoidGlyphActor); } this->attributeDimension = 0 ; this->featureScale->SetValue(1) ; this->ColorMode->SetValue("P Value"); this->PValueCallback (); this->RenderWidget->Render(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::LoadAttributeMeshCallback() { vtkKWLoadSaveDialog *dialog = vtkKWLoadSaveDialog::New() ; dialog->SetParent(this->RenderWidget->GetParentTopLevel()) ; dialog->Create(); dialog->RetrieveLastPathFromRegistry("DataPath"); dialog->SetTitle ("Load Attributed Mesh"); dialog->SetFileTypes ("{{VTK PolyData File} {.vtk}}"); dialog->SetDefaultExtension (".vtk"); if ( dialog->Invoke () == 0 ) { return ; } dialog->SaveLastPathToRegistry("DataPath"); vtkPolyDataReader *reader = vtkPolyDataReader::New () ; reader->SetFileName ( dialog->GetFileName() ) ; reader->Update () ; this->vtkMesh = reader->GetOutput() ; // make the final connections this->normalFilter->SetInput (this->vtkMesh); // setup vtk rendering this->meshMapper->SetInput(this->normalFilter->GetOutput()); this->meshMapper->Update() ; this->meshActor = vtkActor::New(); this->meshActor->SetMapper(this->meshMapper); // setup the vector field visualization this->arrowGlyphFilter->SetInput(this->meshMapper->GetInput()); this->arrowGlyphFilter->SetSource(this->arrowSource->GetOutput()); this->arrowGlyphFilter->SetScaleModeToScaleByVector(); this->arrowGlyphFilter->SetVectorModeToUseVector(); this->arrowGlyphFilter->SetColorModeToColorByVector(); this->arrowGlyphFilter->OrientOn (); this->arrowGlyphMapper->SetInput(this->arrowGlyphFilter->GetOutput()); this->arrowGlyphActor = vtkActor::New(); this->arrowGlyphActor->SetMapper (this->arrowGlyphMapper); // setup the ellipsoid field visualization this->ellipsoidGlyphFilter->SetInput(this->meshMapper->GetInput()); this->ellipsoidGlyphFilter->SetSource(this->ellipsoidSource->GetOutput()); this->ellipsoidGlyphFilter->SetScaleFactor (1); this->ellipsoidGlyphFilter->ThreeGlyphsOff () ; this->ellipsoidGlyphFilter->ColorGlyphsOn () ; this->ellipsoidGlyphFilter->SetColorModeToEigenvalues(); this->ellipsoidGlyphFilter->ExtractEigenvaluesOff(); // make sure the normals for the ellipsoids are in the correct direction, // to be able to color them properly vtkPolyDataNormals *normals = vtkPolyDataNormals::New() ; normals->SetInput (this->ellipsoidGlyphFilter->GetOutput()) ; this->ellipsoidGlyphMapper->SetInput(normals->GetOutput()); this->ellipsoidGlyphActor = vtkActor::New(); this->ellipsoidGlyphActor->SetMapper (this->ellipsoidGlyphMapper); this->RenderWidget->AddViewProp (this->meshActor) ; this->RenderWidget->ResetCamera(); this->attributeDimension = 1 ; this->UpdateDistanceMapTFunc(); this->meshMapper->ScalarVisibilityOn (); // make sure we're not drawing arrows or spheres this->RenderWidget->RemoveViewProp(this->arrowGlyphActor); this->RenderWidget->RemoveViewProp(this->ellipsoidGlyphActor); if ( !this->commandLine ) { this->ColorMode->SetValue("P Value"); } this->PValueCallback (); this->RenderWidget->Render(); dialog->Delete(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::SaveAttributeMeshCallback() { vtkKWLoadSaveDialog *dialog = vtkKWLoadSaveDialog::New() ; dialog->SetParent(this->RenderWidget->GetParentTopLevel()) ; dialog->Create(); dialog->RetrieveLastPathFromRegistry("DataPath"); dialog->SetTitle ("Load Attributed Mesh"); dialog->SetFileTypes ("{{VTK PolyData File} {.vtk}}"); dialog->SetDefaultExtension (".vtk"); dialog->SaveDialogOn() ; if ( dialog->Invoke () == 0 ) { return ; } dialog->SaveLastPathToRegistry("DataPath"); vtkPolyDataWriter *writer = vtkPolyDataWriter::New () ; writer->SetInput ( this->vtkMesh ) ; writer->SetFileName ( dialog->GetFileName() ) ; writer->Update () ; dialog->Delete(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::PValueCallback() { if ( this->commandLine ) { return ; } this->TFuncEditor->SetColorTransferFunction (this->PValueTFunc) ; this->TFuncEditor->LockEndPointsParameterOn(); this->TFuncEditor->SetLabelText ("P-Value Color Map"); // if we are not in 1D attribute mode, leave the 1D visualization alone if ( this->attributeDimension == 1 ) { this->meshMapper->SetLookupTable (this->PValueTFunc) ; this->meshMapper->SetColorModeToMapScalars (); } this->arrowGlyphMapper->SetLookupTable (this->PValueTFunc) ; this->ellipsoidGlyphMapper->SetLookupTable (this->PValueTFunc) ; //this->meshMapper->ScalarVisibilityOn (); this->TFuncEditor->SetWholeParameterRange(0.0, 1.0); this->RenderWidget->Render(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::DistanceMapCallback() { if ( this->commandLine ) { return ; } this->TFuncEditor->SetColorTransferFunction (this->DistanceMapTFunc) ; this->TFuncEditor->LockEndPointsParameterOff(); this->TFuncEditor->SetLabelText ("Distance Color Map"); this->arrowGlyphMapper->SetLookupTable (this->DistanceMapTFunc) ; this->ellipsoidGlyphMapper->SetLookupTable (this->DistanceMapTFunc) ; // if we are not in 1D attribute mode, leave the 1D visualization alone if ( this->attributeDimension == 1 ) { this->meshMapper->SetLookupTable (this->DistanceMapTFunc) ; this->meshMapper->SetColorModeToMapScalars (); } // add some cushioning to the parameter range double range[2] ; this->GetAttributeRange ( range ) ; double dist = range[1] - range[0] ; this->TFuncEditor->SetWholeParameterRange(range[0]-dist, range[1]+dist) ; this->TFuncEditor->SetVisibleParameterRange (range); this->RenderWidget->Render(); } //---------------------------------------------------------------------------- void vtkKWMeshVisu::OpacityCallback(double d) { double val = this->opacityScale->GetValue() ; this->meshActor->GetProperty()->SetOpacity(val); this->RenderWidget->Render(); } void vtkKWMeshVisu::FeatureScaleCallback(double d) { double val = this->featureScale->GetValue() ; this->arrowGlyphFilter->SetScaleFactor(val); this->ellipsoidGlyphFilter->SetScaleFactor(val); this->RenderWidget->Render(); } void vtkKWMeshVisu::UpdateDistanceMapTFunc () { double range[2]; if (!this->vtkMesh) { return; } if ( this->commandLine ) { return ; } this->GetAttributeRange ( range ) ; this->DistanceMapTFunc->RemoveAllPoints () ; this->DistanceMapTFunc->AddHSVPoint(range[0], 0.3, 1, 1); this->DistanceMapTFunc->AddHSVPoint(range[1], 0, 1, 1); } void vtkKWMeshVisu::GetAttributeRange (double *r ) { double temp[2] ; if ( this->attributeDimension == 1 ) { this->vtkMesh->GetScalarRange (temp) ; r[0] = temp[0] ; r[1] = temp[1] ; } else if ( this->attributeDimension == 3 ) { double range ; r[0] = r[1] = 0 ; for ( int i = 0 ; i < 3 ; i++ ) { this->vtkMesh->GetPointData()->GetVectors()->GetRange(temp, i) ; if (temp[0]<0) temp[0] *= -1 ; if (temp[1]<0) temp[1] *= -1 ; if ( temp[0] > temp[1] ) { range = temp[0] ; } else { range = temp[1] ; } r[1] += range * range; } r[1] = sqrt ( r[1] ) ; } else if ( this->attributeDimension == 9 ) { double range ; r[0] = r[1] = 0 ; for ( int i = 0 ; i < 9 ; i++ ) { this->vtkMesh->GetPointData()->GetTensors()->GetRange(temp, i) ; if (temp[0]<0) temp[0] *= -1 ; if (temp[1]<0) temp[1] *= -1 ; if ( temp[0] > temp[1] ) { range = temp[0] ; } else { range = temp[1] ; } r[1] += range * range; } r[1] = sqrt ( r[1] ) ; } } void vtkKWMeshVisu::Stabilize1DVisualization () { if ( this->commandLine ) return ; if ( this->FixedTFunc ) this->FixedTFunc->Delete(); this->FixedTFunc = vtkColorTransferFunction::New(); if ( strcmp (this->ColorMode->GetValue(), "P Value") == 0 ) { this->FixedTFunc->DeepCopy (this->PValueTFunc) ; } else { this->FixedTFunc->DeepCopy (this->DistanceMapTFunc) ; } this->meshMapper->SetLookupTable ( this->FixedTFunc ) ; } void vtkKWMeshVisu::GetCameraCallback () { vtkCamera *camera ; double pos[3], dir[3], up[3], scale ; camera = this->RenderWidget->GetRenderer()->GetActiveCamera(); camera->GetPosition(pos); camera->GetFocalPoint(dir); camera->GetViewUp(up); scale = camera->GetParallelScale(); vtkKWMessageDialog *dlg = vtkKWMessageDialog::New(); dlg->SetParent(this->RenderWidget->GetParent()); dlg->SetMasterWindow(this->RenderWidget->GetParentTopLevel()); dlg->SetStyleToOkCancel(); dlg->Create(); dlg->SetTitle("Current camera parameters"); char text[256] ; sprintf (text, "Position: %f %f %f\nFocal Point: %f %f %f\nUp: %f %f %f\nScale:%f", pos[0], pos[1], pos[2], dir[0], dir[1], dir[2], up[0], up[1], up[2], scale); dlg->SetText(text); this->RenderWidget->Render(); dlg->Invoke(); dlg->Delete(); } void vtkKWMeshVisu::LoadMesh (char *fileName) { typedef double real ; typedef itk::DefaultDynamicMeshTraits < real, 3, 3, real, real > MeshTraitsType ; typedef itk::Mesh < real, 3, MeshTraitsType > itkMeshType ; typedef itk::MeshSpatialObject < itkMeshType > itkMeshSOType ; typedef itk::MetaMeshConverter < 3, real, MeshTraitsType > MeshConverterType ; // read the data in itk format MeshConverterType * itkConverter = new MeshConverterType() ; itkMeshSOType::Pointer meshSO = itkConverter->ReadMeta (fileName) ; itkMeshType::Pointer mesh = meshSO->GetMesh() ; delete (itkConverter); // convert to vtk format itkMeshTovtkPolyData * ITKVTKConverter = new itkMeshTovtkPolyData; ITKVTKConverter->SetInput ( mesh ) ; this->vtkMesh = ITKVTKConverter->GetOutput () ; delete (ITKVTKConverter); this->normalFilter->SetInput (this->vtkMesh); // setup vtk rendering this->meshMapper->SetInput(this->normalFilter->GetOutput()); this->meshMapper->Update() ; this->meshActor = vtkActor::New(); this->meshActor->SetMapper(this->meshMapper); // setup the vector field visualization this->arrowGlyphFilter->SetInput(this->meshMapper->GetInput()); this->arrowGlyphFilter->SetSource(this->arrowSource->GetOutput()); this->arrowGlyphFilter->SetScaleModeToScaleByVector(); //this->arrowGlyphFilter->SetScaleModeToDataScalingOff(); //this->arrowGlyphFilter->SetScaleFactor(1); this->arrowGlyphFilter->SetVectorModeToUseVector(); this->arrowGlyphFilter->SetColorModeToColorByVector(); this->arrowGlyphFilter->OrientOn (); this->arrowGlyphMapper->SetInput(this->arrowGlyphFilter->GetOutput()); this->arrowGlyphActor = vtkActor::New(); this->arrowGlyphActor->SetMapper (this->arrowGlyphMapper); // setup the ellipsoid field visualization this->ellipsoidGlyphFilter->SetInput(this->meshMapper->GetInput()); this->ellipsoidGlyphFilter->SetSource(this->ellipsoidSource->GetOutput()); this->ellipsoidGlyphFilter->SetScaleFactor (1); this->ellipsoidGlyphFilter->ThreeGlyphsOff () ; this->ellipsoidGlyphFilter->ColorGlyphsOn () ; this->ellipsoidGlyphFilter->SetColorModeToEigenvalues(); this->ellipsoidGlyphFilter->ExtractEigenvaluesOff(); //vtkReverseSense *reverse = vtkReverseSense::New() ; //reverse->SetInput (this->ellipsoidGlyphFilter->GetOutput()) ; //this->ellipsoidGlyphMapper->SetInput(this->ellipsoidGlyphFilter->GetOutput()); // make sure the normals for the ellipsoids are in the correct direction, // to be able to color them properly vtkPolyDataNormals *normals = vtkPolyDataNormals::New() ; normals->SetInput (this->ellipsoidGlyphFilter->GetOutput()) ; this->ellipsoidGlyphMapper->SetInput(normals->GetOutput()); this->ellipsoidGlyphActor = vtkActor::New(); this->ellipsoidGlyphActor->SetMapper (this->ellipsoidGlyphMapper); this->RenderWidget->AddViewProp (this->meshActor) ; this->RenderWidget->ResetCamera(); this->RenderWidget->Render(); this->attributeDimension = 0 ; } void vtkKWMeshVisu::LoadScalarField (char *fileName) { int nPts = this->vtkMesh->GetNumberOfPoints() ; double data ; vtkFloatArray *scalars = vtkFloatArray::New() ; // read in the file std::ifstream attrFile ; attrFile.open ( fileName ) ; // check the header int nPtsFile, nDim ; // This is a quite sloppy implementation of reading keyword/value pairs! bool found; char * valuePtr; char typeString[1001], line[1001]; attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "NUMBER_OF_POINTS" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %d ", &nPtsFile); attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "DIMENSION" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %d ", &nDim); attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "TYPE" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %s ", typeString); assert ( nPtsFile == nPts ) ; assert ( nDim == 1 ) ; assert ( strcmp ( typeString, "Scalar" ) == 0 ) ; attrFile.seekg(0,std::ios::beg); const int numEntries = 3; int counter = 0; while ( counter < numEntries && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if ((line[0] != '#')) counter++; } for (int i = 0 ; i < nPts ; i++ ) { attrFile >> data ; scalars->InsertTuple1 (i, data) ; } attrFile.close () ; // make the final connections this->vtkMesh->GetPointData()->SetScalars ( scalars ) ; this->attributeDimension = 1 ; this->UpdateDistanceMapTFunc(); this->meshMapper->ScalarVisibilityOn (); // make sure we're not drawing arrows or spheres this->RenderWidget->RemoveViewProp(this->arrowGlyphActor); this->RenderWidget->RemoveViewProp(this->ellipsoidGlyphActor); if ( !this->commandLine ) { this->ColorMode->SetValue("P Value"); } this->PValueCallback (); this->RenderWidget->Render(); scalars->Delete (); } void vtkKWMeshVisu::LoadVectorField (char *fileName) { int nPts = this->vtkMesh->GetNumberOfPoints() ; float x[3] ; vtkFloatArray *vectors = vtkFloatArray::New() ; // read in the file std::ifstream attrFile ; attrFile.open ( fileName ) ; // This is a quite sloppy implementation of reading keyword/value pairs! bool found; char * valuePtr; int nPtsFile, nDim ; char typeString[1001], line[1001]; attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "NUMBER_OF_POINTS" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %d ", &nPtsFile); attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "DIMENSION" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %d ", &nDim); attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "TYPE" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %s ", typeString); assert ( nPtsFile == nPts ) ; assert ( nDim == 3 ) ; assert ( strcmp ( typeString, "Vector" ) == 0 ) ; attrFile.seekg(0,std::ios::beg); const int numEntries = 3; int counter = 0; while ( counter < numEntries && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if ((line[0] != '#')) counter++; } vectors->SetNumberOfComponents (3); for (int i = 0 ; i < nPts ; i++ ) { attrFile >> x[0] >> x[1] >> x[2] ; vectors->InsertNextTuple3 (x[0], x[1], x[2]) ; } attrFile.close () ; this->vtkMesh->GetPointData()->SetVectors ( vectors ) ; if ( this->attributeDimension == 1 ) { this->Stabilize1DVisualization(); } this->attributeDimension = 3 ; this->UpdateDistanceMapTFunc () ; this->RenderWidget->AddViewProp(this->arrowGlyphActor); //this->meshMapper->ScalarVisibilityOff (); if ( !this->commandLine ) { this->opacityScale->SetValue(0.5); } this->meshActor->GetProperty()->SetOpacity(0.5) ; this->RenderWidget->Render(); vectors->Delete(); } void vtkKWMeshVisu::LoadCurve (char *fileName) { // read in the file std::ifstream attrFile ; attrFile.open ( fileName ) ; // This is a quite sloppy implementation of reading keyword/value pairs! bool found; char * valuePtr; int nPts, nDim ; char typeString[1001], line[1001]; attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "NUMBER_OF_POINTS" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %d ", &nPts); attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "DIMENSION" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %d ", &nDim); attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "TYPE" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %s ", typeString); assert ( nPts > 0 ) ; assert ( nDim == 3 ) ; assert ( strcmp ( typeString, "Curve" ) == 0 ) ; attrFile.seekg(0,std::ios::beg); const int numEntries = 3; int counter = 0; while ( counter < numEntries && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if ((line[0] != '#')) counter++; } int i ; double x[3] ; vtkPoints *polyLinePoints = vtkPoints::New() ; polyLinePoints->SetNumberOfPoints (nPts) ; vtkPolyLine *aPolyLine = vtkPolyLine::New() ; aPolyLine->GetPointIds()->SetNumberOfIds (nPts) ; for ( i = 0 ; i < nPts ; i++ ) { attrFile >> x[0] >> x[1] >> x[2] ; polyLinePoints->InsertPoint(i, x[0], x[1], x[2]); aPolyLine->GetPointIds()->SetId(i, i) ; } attrFile.close () ; vtkUnstructuredGrid *aPolyLineGrid = vtkUnstructuredGrid::New() ; aPolyLineGrid->Allocate(1, 1) ; aPolyLineGrid->InsertNextCell(aPolyLine->GetCellType(), aPolyLine->GetPointIds()); aPolyLineGrid->SetPoints(polyLinePoints) ; vtkDataSetMapper *aPolyLineMapper = vtkDataSetMapper::New() ; aPolyLineMapper->SetInput(aPolyLineGrid); this->aPolyLineActor->SetMapper(aPolyLineMapper) ; this->aPolyLineActor->GetProperty()->SetColor(1, 0, 0) ; this->aPolyLineActor->GetProperty()->SetLineWidth (3) ; this->RenderWidget->AddViewProp (this->aPolyLineActor) ; this->RenderWidget->Render(); } void vtkKWMeshVisu::LoadEllipsoidField (char *fileName) { int nPts = this->vtkMesh->GetNumberOfPoints() ; vtkFloatArray *vectors = vtkFloatArray::New() ; // read in the file std::ifstream attrFile ; attrFile.open ( fileName ) ; // This is a quite sloppy implementation of reading keyword/value pairs! bool found; char * valuePtr; int nPtsFile, nDim ; char typeString[1001], line[1001]; attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "NUMBER_OF_POINTS" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %d ", &nPtsFile); attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "DIMENSION" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %d ", &nDim); attrFile.seekg(0,std::ios::beg); found = false ; while ( !found && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if (line[0] != '#' && strstr ( line, "TYPE" )) found = true; } valuePtr=strchr(line, '='); if (!valuePtr) return; valuePtr++; sscanf(valuePtr, " %s ", typeString); assert ( nPtsFile == nPts ) ; assert ( nDim == 9 ) ; assert ( strcmp ( typeString, "Ellipsoid" ) == 0 ) ; attrFile.seekg(0,std::ios::beg); const int numEntries = 3; int counter = 0; while ( counter < numEntries && !attrFile.eof()) { attrFile.getline ( line, 1000 ) ; if ((line[0] != '#')) counter++; } double x[9]; vectors->SetNumberOfComponents (9); for (int i = 0 ; i < nPts ; i++ ) { attrFile >> x[0] >> x[1] >> x[2] ; attrFile >> x[3] >> x[4] >> x[5] ; attrFile >> x[6] >> x[7] >> x[8] ; vectors->InsertNextTuple9 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]) ; } attrFile.close () ; if ( this->attributeDimension == 1 ) { this->Stabilize1DVisualization(); } this->vtkMesh->GetPointData()->SetTensors ( vectors ) ; this->attributeDimension = 9 ; this->UpdateDistanceMapTFunc () ; this->RenderWidget->AddViewProp(this->ellipsoidGlyphActor); if ( !this->commandLine ) { this->opacityScale->SetValue(0.5); } this->meshActor->GetProperty()->SetOpacity(0.5) ; this->RenderWidget->Render(); vectors->Delete(); } int vtkKWMeshVisu::CommandLine (int argc, const char *argv[]) { char *meshFile, *scalarFile, *vectorFile, *ellipsoidFile, *inputFile, *outputFile, *imageFile ; float opacity, scale, pvalueThreshold, distMapMin, distMapMax ; float posx, posy, posz, focx, focy, focz, upx, upy, upz, zoom ; float r, g, b ; this->commandLine = true ; this->Run (argc, (char **)argv) ; meshFile = ipGetStringArgument(argv, "--mesh", NULL); scalarFile = ipGetStringArgument(argv, "--scalar", NULL); vectorFile = ipGetStringArgument(argv, "--vector", NULL); ellipsoidFile = ipGetStringArgument(argv, "--ellipsoid", NULL); inputFile = ipGetStringArgument(argv, "--input", NULL); outputFile = ipGetStringArgument(argv, "--output", NULL); imageFile = ipGetStringArgument(argv, "--image", NULL); opacity = ipGetFloatArgument(argv, "--opacity", 1); scale = ipGetFloatArgument(argv, "--scale", 1); pvalueThreshold = ipGetFloatArgument(argv, "--pvalue", -1); distMapMin = ipGetFloatArgument(argv, "--distMapMin", -1); distMapMax = ipGetFloatArgument(argv, "--distMapMax", -1); posx = ipGetFloatArgument(argv, "--posx", -1); posy = ipGetFloatArgument(argv, "--posy", -1); posz = ipGetFloatArgument(argv, "--posz", -1); focx = ipGetFloatArgument(argv, "--focx", -1); focy = ipGetFloatArgument(argv, "--focy", -1); focz = ipGetFloatArgument(argv, "--focz", -1); upx = ipGetFloatArgument(argv, "--upx", -1); upy = ipGetFloatArgument(argv, "--upy", -1); upz = ipGetFloatArgument(argv, "--upz", -1); zoom = ipGetFloatArgument(argv, "--zoom", -1); r = ipGetFloatArgument(argv, "--br", 0); g = ipGetFloatArgument(argv, "--bg", 0); b = ipGetFloatArgument(argv, "--bb", 0); if ( ( !meshFile && !inputFile ) || ipExistsArgument(argv, "--help") ) { cout << "Usage:" << endl ; cout << "KWMeshVisu " << endl ; cout << "[--mesh Meshfile [--scalar 1dfile] [--vector 3dfile] [--ellipsoid 9dfile]]" << endl ; cout << "[--input attributedMeshfile]" << endl ; cout << "[--output attributedMeshfile]" << endl ; cout << "[--image bmpfile [--opacity o] [--scale s] [--br BackgroundR] [--bg BackgroundG] [--bb BackgroundB]]" << endl ; cout << "[--pvalue threshold] [--distMapMin min --distMapMax max]" << endl ; cout << "[--posx x --posy x --posz x --focx x --focy x --focz x --upx x --upy x --upz x --zoom x]" << endl ; return 0 ; } if (inputFile) { } else { this->LoadMesh (meshFile) ; if ( scalarFile ) { this->LoadScalarField ( scalarFile ) ; } if ( vectorFile ) { this->LoadVectorField ( vectorFile ) ; } if ( ellipsoidFile ) { this->LoadEllipsoidField ( ellipsoidFile ) ; } } this->RenderWidget->SetRendererBackgroundColor(r, g, b) ; this->meshActor->GetProperty()->SetOpacity(opacity); this->arrowGlyphFilter->SetScaleFactor(scale); this->ellipsoidGlyphFilter->SetScaleFactor(scale); if ( pvalueThreshold != -1 ) { this->PValueTFunc->AddHSVPoint(0, 0, 1, 1); this->PValueTFunc->AddHSVPoint(pvalueThreshold, 0.27, 0.6, 0.97, 0, 1); this->PValueTFunc->AddHSVPoint(1, 0.6, 1, 1); this->meshMapper->SetLookupTable (this->PValueTFunc) ; this->meshMapper->SetColorModeToMapScalars (); this->arrowGlyphMapper->SetLookupTable (this->PValueTFunc) ; this->ellipsoidGlyphMapper->SetLookupTable (this->PValueTFunc) ; } if ( ( distMapMin != -1 ) || ( distMapMax != -1 ) ) { this->DistanceMapTFunc->AddHSVPoint(distMapMin, 0, 1, 1); this->DistanceMapTFunc->AddHSVPoint(distMapMax, 0.6, 1, 1); this->meshMapper->SetLookupTable (this->DistanceMapTFunc) ; this->meshMapper->SetColorModeToMapScalars (); this->arrowGlyphMapper->SetLookupTable (this->DistanceMapTFunc) ; this->ellipsoidGlyphMapper->SetLookupTable (this->DistanceMapTFunc) ; } if ( ( posx != -1 ) || ( posy != -1 ) || ( posz != -1 ) || ( focx != -1 ) || ( focy != -1 ) || ( focz != -1 ) || ( upx != -1 ) || ( upy != -1 ) || ( upz != -1 ) || ( zoom != -1 ) ) { vtkCamera *camera = this->RenderWidget->GetRenderer()->GetActiveCamera(); camera->SetPosition(posx, posy, posz); camera->SetFocalPoint(focx, focy, focz); camera->SetViewUp(upx, upy, upz); camera->SetParallelScale(zoom); } this->RenderWidget->Render () ; if ( imageFile ) { this->SaveRenderAsBMP ( imageFile ) ; } return 0 ; } void vtkKWMeshVisu::SaveRenderAsBMP(const char *filename) { // mostly using the example in SOV vtkWindowToImageFilter* exporter = vtkWindowToImageFilter::New(); exporter->SetInput((vtkWindow *)this->RenderWidget->GetRenderWindow()); exporter->Update(); vtkBMPWriter* writer = vtkBMPWriter::New(); writer->SetInput(exporter->GetOutput()); writer->SetFileName(filename); writer->Write(); writer->Delete(); exporter->Delete(); }