Commit 959e9b16 authored by finetjul's avatar finetjul

BUG: Fix import of hierarchy node with existing ID

Note that it does not fix the import of annotation hierarchies.
For some reasons (see vtkSlicerAnnotationModuleLogic::OnSceneNodeAdded),
the hierarchies are automatically loaded into the wrong hierarchy node
parent.
Issue #2849

git-svn-id: http://svn.slicer.org/Slicer4/trunk@21561 3bd1e089-480b-0410-8dfb-8563597acbee
parent f19f7b43
......@@ -25,8 +25,24 @@
#include <vtkNew.h>
#include <vtkPolyData.h>
bool ImportIDModelHierarchyConflictTest();
bool ImportModelHierarchyTwiceTest();
//---------------------------------------------------------------------------
int vtkMRMLSceneImportIDModelHierarchyConflictTest(int vtkNotUsed(argc), char * vtkNotUsed(argv) [])
{
bool res = true;
res = ImportIDModelHierarchyConflictTest() && res;
res = ImportModelHierarchyTwiceTest() && res;
return res ? EXIT_SUCCESS : EXIT_FAILURE;
}
//---------------------------------------------------------------------------
// The test makes sure the model hierarchy nodes correctly support node ID
// conflict. There are 2 steps in this test
// a) populates a scene with a model with flat hierarchy node
// b) and imports a similar scene into the existing scene.
bool ImportIDModelHierarchyConflictTest()
{
vtkNew<vtkMRMLScene> scene;
......@@ -54,7 +70,7 @@ int vtkMRMLSceneImportIDModelHierarchyConflictTest(int vtkNotUsed(argc), char *
<< "model display id: " << modelDisplayNode->GetID()<< " "
<< "display node: " << modelNode.GetPointer()->GetDisplayNode()
<< std::endl;
return EXIT_FAILURE;
return false;
}
// does the display node point to the correct polydata?
std::cout<< "Model display node poly data pointer = "
......@@ -66,7 +82,7 @@ int vtkMRMLSceneImportIDModelHierarchyConflictTest(int vtkNotUsed(argc), char *
<<" model poly data = " << modelNode.GetPointer()->GetPolyData()
<< ", display node polydata = " << modelDisplayNode.GetPointer()->GetInputPolyData()
<< std::endl;
return EXIT_FAILURE;
return false;
}
// add a model hierarchy node
......@@ -121,7 +137,7 @@ int vtkMRMLSceneImportIDModelHierarchyConflictTest(int vtkNotUsed(argc), char *
<< " or scene model display node 1 " << scene->GetNodeByID("vtkMRMLModelDisplayNode1")
<< " != original model dipslay node " << modelDisplayNode.GetPointer()
<< std::endl;
return EXIT_FAILURE;
return false;
}
vtkMRMLModelNode* modelNode2 = vtkMRMLModelNode::SafeDownCast(
......@@ -147,7 +163,7 @@ int vtkMRMLSceneImportIDModelHierarchyConflictTest(int vtkNotUsed(argc), char *
}
}
std::cerr << std::endl;
return EXIT_FAILURE;
return false;
}
// check that the hierarchies point to the right display nodes
......@@ -155,30 +171,30 @@ int vtkMRMLSceneImportIDModelHierarchyConflictTest(int vtkNotUsed(argc), char *
if (!hierarchyNode2)
{
std::cerr << "Import failure: imported hierarchy node is not using id vtkMRMLModelHierarchyNode2" << std::endl;
return EXIT_FAILURE;
return false;
}
if (!hierarchyNode2->GetDisplayNodeID())
{
std::cerr << "Import failure: imported hierarchy node does not have a display node" << std::endl;
return EXIT_FAILURE;
return false;
}
if (strcmp(hierarchyNode2->GetDisplayNodeID(), "vtkMRMLModelDisplayNode4") != 0)
{
std::cerr << "Import failure: new model hierarchy should point to new display node with id vtkMRMLModelDisplayNode4, instead points to "
<< hierarchyNode2->GetDisplayNodeID() << std::endl;
return EXIT_FAILURE;
return false;
}
// check that the hierarchies point to the right model nodes
if (!hierarchyNode2->GetAssociatedNodeID())
{
std::cerr << "Import failure: imported hierarchy node does not have an associated node" << std::endl;
return EXIT_FAILURE;
return false;
}
if (strcmp(hierarchyNode2->GetAssociatedNodeID(), "vtkMRMLModelNode2") != 0)
{
std::cerr << "Import failure: new model hierarchy shoudl point to new model node with id vtkMRMLModelNode2, instead points to "
<< hierarchyNode2->GetAssociatedNodeID() << std::endl;
return EXIT_FAILURE;
return false;
}
// check that the model nodes and model display nodes point to the right poly data
......@@ -195,7 +211,7 @@ int vtkMRMLSceneImportIDModelHierarchyConflictTest(int vtkNotUsed(argc), char *
<< vtkMRMLModelDisplayNode::SafeDownCast(modelNode2->GetDisplayNode())
->GetInputPolyData()
<< std::endl;
return EXIT_FAILURE;
return false;
}
std::cout << "Imported model poly data and display node poly data are properly null" << std::endl;
......@@ -203,20 +219,79 @@ int vtkMRMLSceneImportIDModelHierarchyConflictTest(int vtkNotUsed(argc), char *
{
std::cerr << "Import failed: original model node should not have null polydata"
<< std::endl;
return EXIT_FAILURE;
return false;
}
if (vtkMRMLModelDisplayNode::SafeDownCast(modelNode->GetDisplayNode())->GetInputPolyData() == NULL)
{
std::cerr << "Import failed: original model display node should not have null polydata"
<< std::endl;
return EXIT_FAILURE;
return false;
}
if (modelNode->GetPolyData() != vtkMRMLModelDisplayNode::SafeDownCast(
modelNode->GetDisplayNode())->GetInputPolyData())
{
std::cerr << "Import failed: original model node and display node don't have the same poly data"
<< std::endl;
return EXIT_FAILURE;
return false;
}
return true;
}
//---------------------------------------------------------------------------
bool ImportModelHierarchyTwiceTest()
{
vtkNew<vtkMRMLScene> scene;
// Add model node
vtkNew<vtkMRMLModelNode> modelNode;
scene->AddNode(modelNode.GetPointer());
vtkNew<vtkMRMLModelDisplayNode> hierachyDisplayNode;
scene->AddNode(hierachyDisplayNode.GetPointer());
// Add a model hierarchy node
vtkNew<vtkMRMLModelHierarchyNode> modelHierarchyNode;
scene->AddNode(modelHierarchyNode.GetPointer());
modelHierarchyNode->SetAndObserveDisplayNodeID(hierachyDisplayNode.GetPointer()->GetID());
modelHierarchyNode->SetAssociatedNodeID(modelNode.GetPointer()->GetID());
vtkNew<vtkMRMLHierarchyNode> hierarchyNode;
scene->AddNode(hierarchyNode.GetPointer());
modelHierarchyNode->SetParentNodeID(hierarchyNode->GetID());
std::cout << "Starting scene has " << scene->GetNumberOfNodes() << " nodes" << std::endl;
/// At this point the following node id should be in the scene:
/// - vtkMRMLModelNode1 with valid polydata
/// - vtkMRMLModelDisplayNode2 with null polydata
/// - vtkMRMLModelHierarchyNode1 (pointing to vtkMRMLModelDisplayNode1 and vtkMRMLModelNode1)
/// - vtkMRMLModelHierarchyNode2 (parent of vtkMRMLModelHierarchyNode1)
// Save
scene->SetSaveToXMLString(1);
scene->Commit();
std::string xmlScene = scene->GetSceneXMLString();
std::cout << xmlScene << std::endl;
// Load same scene into scene
scene->SetSceneXMLString(xmlScene);
scene->SetLoadFromXMLString(1);
scene->Import();
vtkMRMLModelHierarchyNode* modelHierarchyNode2= vtkMRMLModelHierarchyNode::SafeDownCast(
scene->GetNodeByID("vtkMRMLModelHierarchyNode2"));
vtkMRMLHierarchyNode* hierarchyNode2= vtkMRMLHierarchyNode::SafeDownCast(
scene->GetNodeByID("vtkMRMLHierarchyNode2"));
if (!modelHierarchyNode2 || !hierarchyNode2 ||
modelHierarchyNode2->GetParentNode() != hierarchyNode2)
{
std::cerr << "Failed to import scene at line " << __LINE__ << " :"
<< " model hierarchy #2: " << modelHierarchyNode2;
if (modelHierarchyNode2)
{
std::cerr << " model hierarchy #2 parent: " << modelHierarchyNode2->GetParentNode();
}
std::cerr << " hierarchy #2: " << hierarchyNode2 << std::endl;
return false;
}
return EXIT_SUCCESS;
return true;
}
......@@ -213,6 +213,7 @@ vtkMRMLHierarchyNode* vtkMRMLHierarchyNode::GetParentNode()
void vtkMRMLHierarchyNode::SetSceneReferences()
{
this->Superclass::SetSceneReferences();
this->Scene->AddReferencedNodeID(this->ParentNodeIDReference, this);
this->Scene->AddReferencedNodeID(this->AssociatedNodeIDReference, this);
}
......@@ -260,7 +261,10 @@ void vtkMRMLHierarchyNode::SetParentNodeID(const char* ref)
this->SetSortingValue(++MaximumSortingValue);
this->HierarchyIsModified(this->GetScene());
if (this->GetScene())
{
this->GetScene()->AddReferencedNodeID(ref, this);
}
this->EndModify(disableModify);
vtkMRMLHierarchyNode *parentNode = this->GetParentNode();
......
......@@ -37,6 +37,7 @@ create_test_sourcelist(Tests ${KIT}CxxTests.cxx
#vtkMRMLAnnotationRulerDisplayableManagerTest1.cxx
#vtkMRMLAnnotationTextNodeAndWidgetTest1.cxx
vtkSlicerAnnotationModuleLogicTest1.cxx
vtkSlicerAnnotationModuleLogicImportSceneTest.cxx
#qSlicerAnnotationModuleAnnotationPropertyDialogTest1.cxx
#TestAnnAngleWidget3D.cxx
EXTRA_INCLUDE vtkMRMLDebugLeaksMacro.h
......
/*==============================================================================
Program: 3D Slicer
Copyright (c) Kitware Inc.
See COPYRIGHT.txt
or http://www.slicer.org/copyright/copyright.txt for details.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// MRML includes
#include "vtkMRMLInteractionNode.h"
#include "vtkMRMLScene.h"
#include "vtkMRMLSelectionNode.h"
// Annotations includes
#include "vtkMRMLAnnotationRulerNode.h"
#include "vtkMRMLAnnotationHierarchyNode.h"
#include "vtkSlicerAnnotationModuleLogic.h"
// STD includes
#include <vtkNew.h>
bool ImportTwiceTest(bool verbose);
//---------------------------------------------------------------------------
int vtkSlicerAnnotationModuleLogicImportSceneTest(int vtkNotUsed(argc), char * vtkNotUsed(argv) [])
{
bool verbose = true;
bool res = true;
res = ImportTwiceTest(verbose) && res;
return res ? EXIT_SUCCESS : EXIT_FAILURE;
}
//---------------------------------------------------------------------------
// The tests makes sure the annotation hierarchy nodes can be loaded twice.
// a) populates a scene with an annotation
// b) and imports a similar scene into the existing scene.
bool ImportTwiceTest(bool verbose)
{
vtkNew<vtkMRMLScene> scene;
vtkNew<vtkSlicerAnnotationModuleLogic > logic;
logic->SetMRMLScene(scene.GetPointer());
vtkNew<vtkMRMLSelectionNode> selectionNode;
scene->AddNode(selectionNode.GetPointer());
vtkNew<vtkMRMLInteractionNode> interactionNode;
scene->AddNode(interactionNode.GetPointer());
logic->AddHierarchy();
vtkNew<vtkMRMLAnnotationRulerNode> rnode;
rnode->Initialize(scene.GetPointer());
std::cout << "Starting scene has " << scene->GetNumberOfNodes() << " nodes" << std::endl;
/// At this point the following node id should be in the scene:
/// - vtkMRMLAnnotationHierarchyNode
/// - vtkMRMLAnnotationHierarchyNode -> vtkMRMLFiducialAnnotationNode -> vtkMRMLFiducialAnnotationDisplayNode
/// -
/// - vtkMRMLModelHierarchyNode1 (pointing to vtkMRMLModelDisplayNode1 and vtkMRMLModelNode1)
/// - vtkMRMLModelHierarchyNode2 (parent of vtkMRMLModelHierarchyNode1)
vtkMRMLAnnotationRulerNode* ruler1 = vtkMRMLAnnotationRulerNode::SafeDownCast(
scene->GetNodeByID("vtkMRMLAnnotationRulerNode1"));
vtkMRMLAnnotationHierarchyNode* rulerHierarchy1 = vtkMRMLAnnotationHierarchyNode::SafeDownCast(
vtkMRMLDisplayableHierarchyNode::GetDisplayableHierarchyNode(
scene.GetPointer(),
ruler1->GetID()));
vtkMRMLAnnotationHierarchyNode* listNode1 = vtkMRMLAnnotationHierarchyNode::SafeDownCast(
scene->GetNodeByID("vtkMRMLAnnotationHierarchyNode2"));
vtkMRMLAnnotationHierarchyNode* allAnnotationsNode1 = vtkMRMLAnnotationHierarchyNode::SafeDownCast(
scene->GetNodeByID("vtkMRMLAnnotationHierarchyNode1"));
if (rulerHierarchy1->GetParentNode() != listNode1)
{
std::cerr << __LINE__ << ": Import failed." << std::endl;
return false;
}
if (listNode1->GetParentNode() != allAnnotationsNode1)
{
std::cerr << __LINE__ << ": Import failed." << std::endl;
return false;
}
// Save
scene->SetSaveToXMLString(1);
scene->Commit();
std::string xmlScene = scene->GetSceneXMLString();
if (verbose)
{
std::cout << xmlScene << std::endl;
}
// Load same scene into scene
scene->SetSceneXMLString(xmlScene);
scene->SetLoadFromXMLString(1);
scene->Import();
if (verbose)
{
scene->SetSaveToXMLString(1);
scene->Commit();
xmlScene = scene->GetSceneXMLString();
std::cout << "Scene after import: " << std::endl;
std::cout << xmlScene << std::endl;
}
vtkMRMLAnnotationRulerNode* ruler2 = vtkMRMLAnnotationRulerNode::SafeDownCast(
scene->GetNodeByID("vtkMRMLAnnotationRulerNode2"));
vtkMRMLAnnotationHierarchyNode* rulerHierarchy2 = vtkMRMLAnnotationHierarchyNode::SafeDownCast(
vtkMRMLDisplayableHierarchyNode::GetDisplayableHierarchyNode(
scene.GetPointer(),
ruler2->GetID()));
vtkMRMLAnnotationHierarchyNode* listNode2 = vtkMRMLAnnotationHierarchyNode::SafeDownCast(
scene->GetNodeByID("vtkMRMLAnnotationHierarchyNode5"));
vtkMRMLAnnotationHierarchyNode* allAnnotationsNode2 = vtkMRMLAnnotationHierarchyNode::SafeDownCast(
scene->GetNodeByID("vtkMRMLAnnotationHierarchyNode4"));
if (rulerHierarchy2->GetParentNode() != listNode2)
{
std::cerr << __LINE__ << ": Import failed." << std::endl;
return false;
}
if (listNode2->GetParentNode() != allAnnotationsNode2)
{
std::cerr << __LINE__ << ": Import failed." << std::endl;
return false;
}
return true;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment