Skip to content

Commit

Permalink
Cleaned up module structure; added automatic linear object segmentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewsholden committed Jan 22, 2014
1 parent 75de76b commit 43371b7
Show file tree
Hide file tree
Showing 30 changed files with 768 additions and 568 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ endif()
add_subdirectory(MRML)
add_subdirectory(Logic)
add_subdirectory(Widgets)
add_subdirectory(Utilities)

#-----------------------------------------------------------------------------
set(MODULE_EXPORT_DIRECTIVE "Q_SLICER_QTMODULES_${MODULE_NAME_UPPER}_EXPORT")
Expand All @@ -27,6 +28,10 @@ set(MODULE_INCLUDE_DIRECTORIES
${CMAKE_CURRENT_BINARY_DIR}/Logic
${CMAKE_CURRENT_SOURCE_DIR}/Widgets
${CMAKE_CURRENT_BINARY_DIR}/Widgets
${CMAKE_CURRENT_SOURCE_DIR}/MRML
${CMAKE_CURRENT_BINARY_DIR}/MRML
${CMAKE_CURRENT_SOURCE_DIR}/Utilities
${CMAKE_CURRENT_BINARY_DIR}/Utilities
)

set(MODULE_SRCS
Expand All @@ -49,6 +54,7 @@ set(MODULE_UI_SRCS
)

set(MODULE_TARGET_LIBRARIES
vtkSlicer${MODULE_NAME}ModuleUtilities
vtkSlicer${MODULE_NAME}ModuleMRML
vtkSlicer${MODULE_NAME}ModuleLogic
qSlicer${MODULE_NAME}ModuleWidgets
Expand Down
2 changes: 2 additions & 0 deletions Logic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set(KIT ${PROJECT_NAME})
set(${KIT}_EXPORT_DIRECTIVE "VTK_SLICER_${MODULE_NAME_UPPER}_MODULE_LOGIC_EXPORT")

set(${KIT}_INCLUDE_DIRECTORIES
${vtkSlicer${MODULE_NAME}ModuleUtilities_SOURCE_DIR}
${vtkSlicer${MODULE_NAME}ModuleUtilities_BINARY_DIR}
)

set(${KIT}_SRCS
Expand Down
180 changes: 63 additions & 117 deletions Logic/vtkSlicerLinearObjectRegistrationLogic.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,6 @@
// LinearObjectRegistration Logic includes
#include "vtkSlicerLinearObjectRegistrationLogic.h"

const double FILTER_WIDTH = 5.0;
const double EXTRACTION_THRESHOLD = 0.5;
const double MATCHING_THRESHOLD = 10.0;

const int MINIMUM_COLLECTION_FRAMES = 100;
const int DIRECTION_SCALE = 100;


void PrintToFile( std::string str )
{
Expand All @@ -29,9 +22,6 @@ vtkStandardNewMacro( vtkSlicerLinearObjectRegistrationLogic );
vtkSlicerLinearObjectRegistrationLogic
::vtkSlicerLinearObjectRegistrationLogic()
{
this->ObservedTransformNode = NULL;
this->ActivePositionBuffer = vtkSmartPointer< vtkMRMLLORPositionBufferNode >::New();

this->OutputMessage = "";
}

Expand Down Expand Up @@ -143,25 +133,6 @@ ::SetOutputMessage( std::string newOutputMessage )
}


void vtkSlicerLinearObjectRegistrationLogic
::ObserveTransformNode( vtkMRMLNode* node )
{
vtkMRMLLinearTransformNode* transformNode = vtkMRMLLinearTransformNode::SafeDownCast( node );
if ( transformNode == NULL )
{
return;
}
if ( this->ObservedTransformNode != NULL )
{
this->ObservedTransformNode->RemoveObservers( vtkMRMLLinearTransformNode::TransformModifiedEvent, (vtkCommand*) this->GetMRMLNodesCallbackCommand() );
}

transformNode->AddObserver( vtkMRMLLinearTransformNode::TransformModifiedEvent, (vtkCommand*) this->GetMRMLNodesCallbackCommand() );

this->ObservedTransformNode = transformNode;
}


// Let the selection node singleton keep track of this - we will just offer convenience functions
void vtkSlicerLinearObjectRegistrationLogic
::SetActiveCollectionNode( vtkMRMLLORLinearObjectCollectionNode* newActiveCollectionNode )
Expand Down Expand Up @@ -192,72 +163,6 @@ ::GetActiveCollectionNode()
}



// This makes the module ready to record - see the ProcessMRMLNodesEvents for this class to see whether or not any recording actually happens
void vtkSlicerLinearObjectRegistrationLogic
::InitializeActivePositionBuffer( std::string collectType )
{
this->ActivePositionBuffer->Clear();
this->CollectType = collectType;
}


void vtkSlicerLinearObjectRegistrationLogic
::FinalizeActivePositionBuffer()
{
if ( this->ActivePositionBuffer == NULL )
{
return;
}

vtkSmartPointer< vtkMRMLLORLinearObjectNode > currentLinearObject;

if ( this->CollectType.compare( "Reference" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( this->ActivePositionBuffer, REFERENCE_DOF );
}
else if ( this->CollectType.compare( "Point" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( this->ActivePositionBuffer, POINT_DOF );
}
else if ( this->CollectType.compare( "Line" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( this->ActivePositionBuffer, LINE_DOF );
}
else if ( this->CollectType.compare( "Plane" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( this->ActivePositionBuffer, PLANE_DOF );
}
else
{
currentLinearObject = this->PositionBufferToLinearObject( this->ActivePositionBuffer, UNKNOWN_DOF );
}

if ( currentLinearObject == NULL )
{
this->ActivePositionBuffer->Clear();
return;
}

currentLinearObject->SetPositionBuffer( this->ActivePositionBuffer->DeepCopy() );
this->InsertNewLinearObject( currentLinearObject );
this->ActivePositionBuffer->Clear();
}


void vtkSlicerLinearObjectRegistrationLogic
::InsertNewLinearObject( vtkMRMLLORLinearObjectNode* linearObject )
{
if ( this->GetActiveCollectionNode() == NULL )
{
return;
}

this->GetActiveCollectionNode()->AddLinearObject( linearObject );
// TODO: Need to insert the current linear object into the correct slot in the collection
}


// Return smart pointer since we created the object in this function
vtkSmartPointer< vtkMRMLLORLinearObjectNode > vtkSlicerLinearObjectRegistrationLogic
::PositionBufferToLinearObject( vtkMRMLLORPositionBufferNode* positionBuffer, int dof )
Expand Down Expand Up @@ -293,23 +198,33 @@ ::PositionBufferToLinearObject( vtkMRMLLORPositionBufferNode* positionBuffer, in
Eigenvector3.at(1) = eigenvectors.get( 1, 2 );
Eigenvector3.at(2) = eigenvectors.get( 2, 2 );

// Get number of eigenvectors with eigenvalues larger than the threshold
double calculatedDOF = 0;
for ( int i = 0; i < vtkMRMLLORPositionNode::SIZE; i++ )
{
if ( abs( eigenvalues.get( i ) ) > vtkMRMLLORConstants::NOISE_THRESHOLD )
{
calculatedDOF++;
}
}

// The threshold noise is twice the extraction threshold
if ( dof == REFERENCE_DOF )
if ( dof == vtkMRMLLORConstants::REFERENCE_DOF )
{
vtkMRMLLORReferenceNode* referenceObject = vtkMRMLLORReferenceNode::New( centroid );
return vtkSmartPointer< vtkMRMLLORReferenceNode >::Take( referenceObject );
}
if ( dof == POINT_DOF )
if ( dof == vtkMRMLLORConstants::POINT_DOF || dof == vtkMRMLLORConstants::UNKNOWN_DOF && calculatedDOF == vtkMRMLLORConstants::POINT_DOF )
{
vtkMRMLLORPointNode* pointObject = vtkMRMLLORPointNode::New( centroid );
return vtkSmartPointer< vtkMRMLLORPointNode >::Take( pointObject );
}
if ( dof == LINE_DOF )
if ( dof == vtkMRMLLORConstants::LINE_DOF || dof == vtkMRMLLORConstants::UNKNOWN_DOF && calculatedDOF == vtkMRMLLORConstants::LINE_DOF )
{
vtkMRMLLORLineNode* lineObject = vtkMRMLLORLineNode::New( centroid, vtkMRMLLORVectorMath::Add( centroid, Eigenvector3 ) );
return vtkSmartPointer< vtkMRMLLORLineNode >::Take( lineObject );
}
if ( dof == PLANE_DOF )
if ( dof == vtkMRMLLORConstants::PLANE_DOF || dof == vtkMRMLLORConstants::UNKNOWN_DOF && calculatedDOF >= vtkMRMLLORConstants::PLANE_DOF )
{
vtkMRMLLORPlaneNode* planeObject = vtkMRMLLORPlaneNode::New( centroid, vtkMRMLLORVectorMath::Add( centroid, Eigenvector2 ), vtkMRMLLORVectorMath::Add( centroid, Eigenvector3 ) );
return vtkSmartPointer< vtkMRMLLORPlaneNode >::Take( planeObject );
Expand Down Expand Up @@ -380,7 +295,7 @@ ::MatchCollections( vtkMRMLLORLinearObjectCollectionNode* collection0, vtkMRMLLO
}
}// for over collection 1

if ( bestDistance < MATCHING_THRESHOLD )
if ( bestDistance < vtkMRMLLORConstants::MATCHING_THRESHOLD )
{
matchedCollection0->AddLinearObject( currentObject0 );
matchedCollection1->AddLinearObject( nonReferenceCollection1->GetLinearObject( bestIndex ) );
Expand Down Expand Up @@ -725,11 +640,11 @@ ::CalculateTransform( vtkMRMLNode* node )
vtkMRMLLORLineNode* CurrentToObject = vtkMRMLLORLineNode::SafeDownCast( toLineCollection->GetLinearObject(i) );

// Add direction vector to projection of origin
testVector = vtkMRMLLORVectorMath::Add( CurrentToObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( DIRECTION_SCALE, CurrentToObject->GetDirection() ) );
testVector = vtkMRMLLORVectorMath::Add( CurrentToObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( vtkMRMLLORConstants::DIRECTION_SCALE, CurrentToObject->GetDirection() ) );
TempToCollection->AddLinearObject( vtkMRMLLORPointNode::New( testVector ) ) ;

// Subtract direction vector to projection of origin
testVector = vtkMRMLLORVectorMath::Subtract( CurrentToObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( DIRECTION_SCALE, CurrentToObject->GetDirection() ) );
testVector = vtkMRMLLORVectorMath::Subtract( CurrentToObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( vtkMRMLLORConstants::DIRECTION_SCALE, CurrentToObject->GetDirection() ) );
TempToCollection->AddLinearObject( vtkMRMLLORPointNode::New( testVector ) );

TempToCollection->Concatenate( toReferenceCollection );
Expand All @@ -738,7 +653,7 @@ ::CalculateTransform( vtkMRMLNode* node )
vtkMRMLLORLineNode* CurrentFromObject = vtkMRMLLORLineNode::SafeDownCast( fromLineCollection->GetLinearObject(i) );

// Add direction vector to projection of origin
testVector = vtkMRMLLORVectorMath::Add( CurrentFromObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( DIRECTION_SCALE, CurrentFromObject->GetDirection() ) );
testVector = vtkMRMLLORVectorMath::Add( CurrentFromObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( vtkMRMLLORConstants::DIRECTION_SCALE, CurrentFromObject->GetDirection() ) );
TempFromCollection->AddLinearObject( vtkMRMLLORPointNode::New( testVector ) );

TempFromCollection->Concatenate( fromReferenceCollection );
Expand Down Expand Up @@ -767,11 +682,11 @@ ::CalculateTransform( vtkMRMLNode* node )
vtkMRMLLORPlaneNode* CurrentToObject = vtkMRMLLORPlaneNode::SafeDownCast( toPlaneCollection->GetLinearObject(i) );

// Add direction vector to projection of origin
testVector = vtkMRMLLORVectorMath::Add( CurrentToObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( DIRECTION_SCALE, CurrentToObject->GetNormal() ) );
testVector = vtkMRMLLORVectorMath::Add( CurrentToObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( vtkMRMLLORConstants::DIRECTION_SCALE, CurrentToObject->GetNormal() ) );
TempToCollection->AddLinearObject( vtkMRMLLORPointNode::New( testVector ) );

// Subtract direction vector to projection of origin
testVector = vtkMRMLLORVectorMath::Subtract( CurrentToObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( DIRECTION_SCALE, CurrentToObject->GetNormal() ) );
testVector = vtkMRMLLORVectorMath::Subtract( CurrentToObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( vtkMRMLLORConstants::DIRECTION_SCALE, CurrentToObject->GetNormal() ) );
TempToCollection->AddLinearObject( vtkMRMLLORPointNode::New( testVector ) );

TempToCollection->Concatenate( toReferenceCollection );
Expand All @@ -780,7 +695,7 @@ ::CalculateTransform( vtkMRMLNode* node )
vtkMRMLLORPlaneNode* CurrentFromObject = vtkMRMLLORPlaneNode::SafeDownCast( fromPlaneCollection->GetLinearObject(i) );

// Add direction vector to projection of origin
testVector = vtkMRMLLORVectorMath::Add( CurrentFromObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( DIRECTION_SCALE, CurrentFromObject->GetNormal() ) );
testVector = vtkMRMLLORVectorMath::Add( CurrentFromObject->ProjectVector( BlankVector ), vtkMRMLLORVectorMath::Multiply( vtkMRMLLORConstants::DIRECTION_SCALE, CurrentFromObject->GetNormal() ) );
TempFromCollection->AddLinearObject( vtkMRMLLORPointNode::New( testVector ) );

TempFromCollection->Concatenate( fromReferenceCollection );
Expand Down Expand Up @@ -1185,24 +1100,54 @@ ::ProcessMRMLNodesEvents( vtkObject* caller, unsigned long event, void* callData
{
// In case the module node is updated
vtkMRMLLinearObjectRegistrationNode* lorNode = vtkMRMLLinearObjectRegistrationNode::SafeDownCast( caller );

// The caller must be a vtkMRMLLinearObjectRegistrationNode
if ( lorNode != NULL )
if ( lorNode != NULL && event == vtkCommand::ModifiedEvent )
{
this->CalculateTransform( lorNode ); // Will create modified event to update widget
}

// In case the observed transform node is updated
vtkMRMLLinearTransformNode* transformNode = vtkMRMLLinearTransformNode::SafeDownCast( caller );
// Must be a transform node
if ( transformNode == NULL || this->ActivePositionBuffer == NULL )
// The position buffer must be ready for conversion to linear object
if ( lorNode != NULL && event == vtkMRMLLinearObjectRegistrationNode::PositionBufferReady )
{
return;
}
if ( strcmp( transformNode->GetID(), this->ObservedTransformNode->GetID() ) == 0 )
{
vtkMatrix4x4* matrix = transformNode->GetMatrixTransformToParent();
this->ActivePositionBuffer->AddPosition( vtkMRMLLORPositionNode::New( matrix ) );
vtkSmartPointer< vtkMRMLLORLinearObjectNode > currentLinearObject = NULL;
vtkSmartPointer< vtkMRMLLORPositionBufferNode > positionBufferCopy = lorNode->GetActivePositionBuffer()->DeepCopy();
lorNode->GetActivePositionBuffer()->Clear();

if ( lorNode->GetCollectionState().compare( "Reference" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( positionBufferCopy, vtkMRMLLORConstants::REFERENCE_DOF );
}
if ( lorNode->GetCollectionState().compare( "Point" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( positionBufferCopy, vtkMRMLLORConstants::POINT_DOF );
}
if ( lorNode->GetCollectionState().compare( "Line" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( positionBufferCopy, vtkMRMLLORConstants::LINE_DOF );
}
if ( lorNode->GetCollectionState().compare( "Plane" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( positionBufferCopy, vtkMRMLLORConstants::PLANE_DOF );
}
if ( lorNode->GetCollectionState().compare( "Collect" ) == 0 )
{
currentLinearObject = this->PositionBufferToLinearObject( positionBufferCopy, vtkMRMLLORConstants::UNKNOWN_DOF );
}
if ( lorNode->GetCollectionState().compare( "Automatic" ) == 0 )
{
positionBufferCopy->Trim( vtkMRMLLORConstants::TRIM_POSITIONS );
currentLinearObject = this->PositionBufferToLinearObject( positionBufferCopy, vtkMRMLLORConstants::UNKNOWN_DOF );
}

if ( currentLinearObject != NULL && this->GetActiveCollectionNode() != NULL )
{
currentLinearObject->SetPositionBuffer( positionBufferCopy );
this->GetActiveCollectionNode()->AddLinearObject( currentLinearObject );
}

}

}


Expand All @@ -1219,6 +1164,7 @@ ::ProcessMRMLSceneEvents( vtkObject* caller, unsigned long event, void* callData
{
// This will get called exactly once, and we will add the observer only once (since node is never replaced)
linearObjectRegistrationNode->AddObserver( vtkCommand::ModifiedEvent, ( vtkCommand* ) this->GetMRMLNodesCallbackCommand() );
linearObjectRegistrationNode->AddObserver( vtkMRMLLinearObjectRegistrationNode::PositionBufferReady, ( vtkCommand* ) this->GetMRMLNodesCallbackCommand() );
linearObjectRegistrationNode->UpdateScene( this->GetMRMLScene() );
linearObjectRegistrationNode->ObserveAllReferenceNodes(); // This will update
this->CalculateTransform( linearObjectRegistrationNode ); // Will create modified event to update widget
Expand Down
20 changes: 1 addition & 19 deletions Logic/vtkSlicerLinearObjectRegistrationLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "vnl/vnl_matrix.h"

// Slicer includes
#include "vtkCommand.h"
#include "vtkSlicerModuleLogic.h"
#include "vtkMRMLLinearTransformNode.h"
#include "vtkMRMLModelNode.h"
Expand Down Expand Up @@ -94,13 +95,6 @@ vtkSlicerLinearObjectRegistrationLogic : public vtkSlicerModuleLogic

public:

static const int REFERENCE_DOF = 4; // This obviously isn't true, but we need to distinguish from points
static const int POINT_DOF = 0;
static const int LINE_DOF = 1;
static const int PLANE_DOF = 2;
static const int UNKNOWN_DOF = -1;


void CalculateTransform( vtkMRMLNode* node );
void UpdateOutputTransform( vtkMRMLLinearTransformNode* outputTransform, vtkMatrix4x4* newTransformMatrix );

Expand All @@ -125,16 +119,9 @@ vtkSlicerLinearObjectRegistrationLogic : public vtkSlicerModuleLogic

vtkSmartPointer< vtkMRMLLORLinearObjectNode > PositionBufferToLinearObject( vtkMRMLLORPositionBufferNode* positionBuffer, int dof = -1 );

void ObserveTransformNode( vtkMRMLNode* node );

vtkMRMLLORLinearObjectCollectionNode* GetActiveCollectionNode();
void SetActiveCollectionNode( vtkMRMLLORLinearObjectCollectionNode* newActiveCollectionNode );

void FinalizeActivePositionBuffer();
void InitializeActivePositionBuffer( std::string collectType );

void InsertNewLinearObject( vtkMRMLLORLinearObjectNode* linearObject );

void MatchCollections( vtkMRMLLORLinearObjectCollectionNode* collection0, vtkMRMLLORLinearObjectCollectionNode* collection1, bool removeUnmatched = false );
vtkSmartPointer< vtkMRMLLORLinearObjectCollectionNode > GetReferences( vtkMRMLLORLinearObjectCollectionNode* collection );
vtkSmartPointer< vtkMRMLLORLinearObjectCollectionNode > GetNonReferences( vtkMRMLLORLinearObjectCollectionNode* collection );
Expand All @@ -147,12 +134,7 @@ vtkSlicerLinearObjectRegistrationLogic : public vtkSlicerModuleLogic

private:

vtkMRMLLinearTransformNode* ObservedTransformNode;
vtkSmartPointer< vtkMRMLLORPositionBufferNode > ActivePositionBuffer;
std::string CollectType;

std::string OutputMessage;

};

#endif
Loading

0 comments on commit 43371b7

Please sign in to comment.