diff --git a/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationDisplayableManager.cxx b/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationDisplayableManager.cxx index 4470c6a5eb53e227a2ffe953e82223a8b800b6d6..c789fa4f428be6d25e5def4062d4c6744b55bbe2 100644 --- a/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationDisplayableManager.cxx +++ b/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationDisplayableManager.cxx @@ -262,24 +262,11 @@ void vtkMRMLAnnotationDisplayableManager::UpdateFromMRML() // do we have a widget for it? if (this->GetWidget(annotationNode) == NULL) { - vtkDebugMacro("UpdateFromMRML: creating a widget for node " << annotationNode->GetID()); - vtkAbstractWidget *widget = this->CreateWidget(annotationNode); - if (widget) + vtkDebugMacro("UpdateFromMRML: adding node " << annotationNode->GetID()); + if (this->AddAnnotation(annotationNode)) { - // Add widget to the list - this->Helper->Widgets[annotationNode] = widget; - - // Add the node to the list. - this->Helper->AnnotationNodeList.push_back(annotationNode); - - // Refresh observers - this->SetAndObserveNode(annotationNode); - - // tear down widget creation - this->OnWidgetCreated(widget, annotationNode); - // update the new widget from the node - this->PropagateMRMLToWidget(annotationNode, widget); + this->PropagateMRMLToWidget(annotationNode, this->GetWidget(annotationNode)); } } } @@ -418,47 +405,12 @@ void vtkMRMLAnnotationDisplayableManager::OnMRMLSceneNodeAdded(vtkMRMLNode* node vtkDebugMacro("OnMRMLSceneNodeAddedEvent: node " << node->GetID()); - // Node added should not be already managed - vtkMRMLAnnotationDisplayableManagerHelper::AnnotationNodeListIt it = std::find( - this->Helper->AnnotationNodeList.begin(), - this->Helper->AnnotationNodeList.end(), - annotationNode); - if (it != this->Helper->AnnotationNodeList.end()) - { - vtkErrorMacro("OnMRMLSceneNodeAddedEvent: This node is already associated to the displayable manager!") - return; - } - - // There should not be a widget for the new node - if (this->Helper->GetWidget(annotationNode) != 0) + if (!this->AddAnnotation(annotationNode)) { - vtkErrorMacro("OnMRMLSceneNodeAddedEvent: A widget is already associated to this node!"); + vtkErrorMacro("OnMRMLSceneNodeAddedEvent: failed to add annotation node " << node->GetName()); return; } - //std::cout << "OnMRMLSceneNodeAddedEvent ThreeD -> CreateWidget" << std::endl; - - // Create the Widget and add it to the list. - vtkAbstractWidget* newWidget = this->CreateWidget(annotationNode); - if (!newWidget) - { - vtkErrorMacro("OnMRMLSceneNodeAddedEvent: Widget was not created!") - return; - } - this->Helper->Widgets[annotationNode] = newWidget; - - // Add the node to the list. - this->Helper->AnnotationNodeList.push_back(annotationNode); - - // Refresh observers - this->SetAndObserveNode(annotationNode); - - // TODO do we need this render call? - this->RequestRender(); - - // tear down widget creation - this->OnWidgetCreated(newWidget, annotationNode); - // Remove all placed seeds this->Helper->RemoveSeeds(); @@ -736,8 +688,10 @@ void vtkMRMLAnnotationDisplayableManager::OnMRMLSliceNodeModifiedEvent(vtkMRMLSl if (visibleOnSlice) { - // it's visible, just update the position - this->UpdatePosition(this->Helper->GetWidget(annotationNode), annotationNode); + // it's visible, but if just update the position, don't get updates + //necessary when switch into and out of lightbox + vtkDebugMacro("OnMRMLSliceNodeModifiedEvent: visible, propagate mrml to widget"); + this->PropagateMRMLToWidget(annotationNode, this->Helper->GetWidget(annotationNode)); } else @@ -890,15 +844,12 @@ bool vtkMRMLAnnotationDisplayableManager::IsWidgetDisplayable(vtkMRMLSliceNode* if (this->IsInLightboxMode()) { - /// BUG mantis issue 1690: if in lightbox mode, don't show fiducials or - /// rulers - if (!strcmp(this->m_Focus, "vtkMRMLAnnotationFiducialNode") || - !strcmp(this->m_Focus, "vtkMRMLAnnotationRulerNode")) + /// BUG mantis issue 1690: if in lightbox mode, don't show rulers + if (!strcmp(this->m_Focus, "vtkMRMLAnnotationRulerNode")) { return false; } } - int numberOfControlPoints = controlPointsNode->GetNumberOfControlPoints(); // the text node saves it's second control point in viewport coordinates, so @@ -926,7 +877,7 @@ bool vtkMRMLAnnotationDisplayableManager::IsWidgetDisplayable(vtkMRMLSliceNode* // get the corresponding lightbox index for this display coordinate and // check if it's in the range of the current number of light boxes being // displayed in the grid rows/columns. - int lightboxIndex = (int)(displayCoordinates[2]+0.5); + int lightboxIndex = this->GetLightboxIndex(controlPointsNode); int numberOfLightboxes = sliceNode->GetLayoutGridColumns() * sliceNode->GetLayoutGridRows(); //std::cout << "IsWidgetDisplayable: " << sliceNode->GetName() << ": lightbox mode, index = " << lightboxIndex << ", rows = " << sliceNode->GetLayoutGridRows() << ", cols = " << sliceNode->GetLayoutGridColumns() << ", number of light boxes = " << numberOfLightboxes << std::endl; if (lightboxIndex < 0 || @@ -937,84 +888,128 @@ bool vtkMRMLAnnotationDisplayableManager::IsWidgetDisplayable(vtkMRMLSliceNode* else { // get the right renderer index by checking the z coordinate - int rendererIndex = lightboxIndex; - - // get all renderers associated with this renderWindow - // when lightbox mode is enabled, there will be different renderers - // associated with the renderWindow of the sliceView (there may also - // be more renderers than light boxes) - vtkRendererCollection* rendererCollection = this->GetInteractor()->GetRenderWindow()->GetRenderers(); - - // check if the rendererIndex is valid for the current lightbox view - if (rendererIndex >= 0 && rendererIndex < rendererCollection->GetNumberOfItems()) + vtkRenderer* currentRenderer = this->GetRenderer(lightboxIndex); + + // now we get the widget.. + vtkAbstractWidget* widget = this->GetWidget(node); + + // TODO this code blocks the movement of the widget in lightbox mode + if (widget && + (widget->GetCurrentRenderer() != currentRenderer || + widget->GetRepresentation()->GetRenderer() != currentRenderer)) { - - vtkRenderer* currentRenderer = vtkRenderer::SafeDownCast(rendererCollection->GetItemAsObject(rendererIndex)); - - // now we get the widget.. - vtkAbstractWidget* widget = this->GetWidget(node); - - // TODO this code blocks the movement of the widget in lightbox mode - if (widget && - (widget->GetCurrentRenderer() != currentRenderer || - widget->GetRepresentation()->GetRenderer() != currentRenderer)) + vtkDebugMacro("IsWidgetDisplayable: updating renderer on widget and representation"); + // if the widget is on, need to turn it off to set the renderer + bool toggleOffOn = false; + if (widget->GetEnabled()) { - // if the widget is on, need to turn it off to set the renderer - bool toggleOffOn = false; - if (widget->GetEnabled()) - { - // turn it off.. - widget->Off(); - toggleOffOn = true; - } - // ..place it and its representation to the right renderer.. - widget->SetCurrentRenderer(currentRenderer); - widget->GetRepresentation()->SetRenderer(currentRenderer); - if (toggleOffOn) - { - // ..and turn it on again! - widget->On(); - } - // if it's a seed widget, go to complete interaction state - vtkSeedWidget *seedWidget = vtkSeedWidget::SafeDownCast(widget); - if (seedWidget) - { - vtkDebugMacro("SeedWidget: Complete interaction"); - seedWidget->CompleteInteraction(); - } + // turn it off.. + widget->Off(); + toggleOffOn = true; + } + // ..place it and its representation to the right renderer.. + + widget->SetCurrentRenderer(currentRenderer); + widget->GetRepresentation()->SetRenderer(currentRenderer); + + if (toggleOffOn) + { + // ..and turn it on again! + widget->On(); + } + // if it's a seed widget, go to complete interaction state + vtkSeedWidget *seedWidget = vtkSeedWidget::SafeDownCast(widget); + if (seedWidget) + { + vtkDebugMacro("SeedWidget: Complete interaction"); + seedWidget->CompleteInteraction(); + } - // we need to render again - if (currentRenderer) - { - currentRenderer->Render(); - } + // we need to render again + if (currentRenderer) + { + currentRenderer->Render(); } } - else - { - // it's out of range of the current collection of renderers - showWidget = false; - } + } // // End of Lightbox specific code // } - else + + // check if the annotation is close enough to the slice to be shown + if (showWidget) { - // the third coordinate of the displayCoordinates is the distance to the slice - float distanceToSlice = displayCoordinates[2]; - float maxDistance = 0.5 + (sliceNode->GetDimensions()[2] - 1); - if (distanceToSlice < -0.5 || distanceToSlice >= maxDistance) + if (this->IsInLightboxMode()) { - // if the distance to the slice is more than 0.5mm, we know that at least one coordinate of the widget is outside the current activeSlice - // hence, we do not want to show this widget - showWidget = false; - // we don't even need to continue parsing the controlpoints, because we know the widget will not be shown - break; + // get the volume's spacing to determine the distance between the slice + // location and the annotation + // default to spacing 1.0 in case can't get volume slice spacing from + // the logic as that will be a multiplicative no-op + double spacing = 1.0; + vtkMRMLSliceLogic *sliceLogic = NULL; + vtkMRMLApplicationLogic *mrmlAppLogic = this->GetMRMLApplicationLogic(); + if (mrmlAppLogic) + { + sliceLogic = mrmlAppLogic->GetSliceLogic(this->GetSliceNode()); + } + if (sliceLogic) + { + double *volumeSliceSpacing = sliceLogic->GetLowestVolumeSliceSpacing(); + if (volumeSliceSpacing != NULL) + { + vtkDebugMacro("Slice node " << this->GetSliceNode()->GetName() << ": volumeSliceSpacing = " << volumeSliceSpacing[0] << ", " << volumeSliceSpacing[1] << ", " << volumeSliceSpacing[2]); + spacing = volumeSliceSpacing[2]; + } + } + vtkDebugMacro("displayCoordinates: " << displayCoordinates[0] << "," << displayCoordinates[1] << "," << displayCoordinates[2] << "\n\tworld coords: " << transformedWorldCoordinates[0] << "," << transformedWorldCoordinates[1] << "," << transformedWorldCoordinates[2]); + // calculate the distance from the annotation in world space to the + // plane defined by the slice node normal and origin (using same + // convention as the vtkMRMLThreeDReformatDisplayableManager) + vtkMatrix4x4 *sliceToRAS = this->GetSliceNode()->GetSliceToRAS(); + double slicePlaneNormal[3], slicePlaneOrigin[3]; + slicePlaneNormal[0] = sliceToRAS->GetElement(0,2); + slicePlaneNormal[1] = sliceToRAS->GetElement(1,2); + slicePlaneNormal[2] = sliceToRAS->GetElement(2,2); + slicePlaneOrigin[0] = sliceToRAS->GetElement(0,3); + slicePlaneOrigin[1] = sliceToRAS->GetElement(1,3); + slicePlaneOrigin[2] = sliceToRAS->GetElement(2,3); + double distanceToPlane = slicePlaneNormal[0]*(transformedWorldCoordinates[0]-slicePlaneOrigin[0]) + + slicePlaneNormal[1]*(transformedWorldCoordinates[1]-slicePlaneOrigin[1]) + + slicePlaneNormal[2]*(transformedWorldCoordinates[2]-slicePlaneOrigin[2]); + // this gives the distance to light box plane 0, but have to offset by + // number of light box planes (as determined by the light box index) times the volume + // slice spacing + int lightboxIndex = this->GetLightboxIndex(controlPointsNode); + double lightboxOffset = lightboxIndex * spacing; + double distanceToSlice = distanceToPlane - lightboxOffset; + double maxDistance = 0.5; + vtkDebugMacro("\n\tdistance to plane = " << distanceToPlane << "\n\tlightboxIndex = " << lightboxIndex << "\n\tlightboxOffset = " << lightboxOffset << "\n\tdistance to slice = " << distanceToSlice); + // check that it's within 0.5mm + if (distanceToSlice < -0.5 || distanceToSlice >= maxDistance) + { + vtkDebugMacro("Distance to slice is greater than max distance, not showing the widget"); + showWidget = false; + break; + } + } + else + { + // the third coordinate of the displayCoordinates is the distance to the slice + float distanceToSlice = displayCoordinates[2]; + float maxDistance = 0.5 + (sliceNode->GetDimensions()[2] - 1); + vtkDebugMacro("Slice node " << this->GetSliceNode()->GetName() << ": distance to slice = " << distanceToSlice << ", maxDistance = " << maxDistance << "\n\tslice node dimenions[2] = " << sliceNode->GetDimensions()[2]); + if (distanceToSlice < -0.5 || distanceToSlice >= maxDistance) + { + // if the distance to the slice is more than 0.5mm, we know that at least one coordinate of the widget is outside the current activeSlice + // hence, we do not want to show this widget + showWidget = false; + // we don't even need to continue parsing the controlpoints, because we know the widget will not be shown + break; + } } } - // ----------------------------------------- // special cases when the slices get panned: @@ -1623,3 +1618,96 @@ bool vtkMRMLAnnotationDisplayableManager::IsInLightboxMode() return flag; } + + +//--------------------------------------------------------------------------- +int vtkMRMLAnnotationDisplayableManager::GetLightboxIndex(vtkMRMLAnnotationNode *node, int controlPointIndex) +{ + int index = -1; + + if (!node) + { + return index; + } + if (!this->IsInLightboxMode()) + { + return index; + } + + // down cast the node as a controlpoints node to get the coordinates + vtkMRMLAnnotationControlPointsNode * controlPointsNode = vtkMRMLAnnotationControlPointsNode::SafeDownCast(node); + + if (!controlPointsNode) + { + vtkErrorMacro("GetLightboxIndex: Could not get the controlpoints node.") + return index; + } + + if (controlPointIndex < 0 || + controlPointIndex >= controlPointsNode->GetNumberOfControlPoints()) + { + return index; + } + + double transformedWorldCoordinates[4]; + controlPointsNode->GetControlPointWorldCoordinates(controlPointIndex, transformedWorldCoordinates); + double displayCoordinates[4]; + this->GetWorldToDisplayCoordinates(transformedWorldCoordinates,displayCoordinates); + + index = (int)(floor(displayCoordinates[2]+0.5)); + + + return index; +} + +//--------------------------------------------------------------------------- +bool vtkMRMLAnnotationDisplayableManager::AddAnnotation(vtkMRMLAnnotationNode *annotationNode) +{ + if (!annotationNode || !this->GetMRMLScene()) + { + return false; + } + + // Node added should not be already managed + vtkMRMLAnnotationDisplayableManagerHelper::AnnotationNodeListIt it = std::find( + this->Helper->AnnotationNodeList.begin(), + this->Helper->AnnotationNodeList.end(), + annotationNode); + if (it != this->Helper->AnnotationNodeList.end()) + { + vtkErrorMacro("AddAnnotation: This node is already associated to the displayable manager!"); + return false; + } + + // There should not be a widget for the new node + if (this->Helper->GetWidget(annotationNode) != 0) + { + vtkErrorMacro("AddAnnotation: A widget is already associated to this node!"); + return false; + } + + vtkDebugMacro("AddAnnotation: ThreeD -> CreateWidget"); + + // Create the Widget and add it to the list. + vtkAbstractWidget* newWidget = this->CreateWidget(annotationNode); + if (!newWidget) + { + vtkErrorMacro("AddAnnotation: Widget was not created!") + return false; + } + this->Helper->Widgets[annotationNode] = newWidget; + + // Add the node to the list. + this->Helper->AnnotationNodeList.push_back(annotationNode); + + // Refresh observers + this->SetAndObserveNode(annotationNode); + + // TODO do we need this render call? + this->RequestRender(); + + // tear down widget creation + this->OnWidgetCreated(newWidget, annotationNode); + + return true; +} diff --git a/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationDisplayableManager.h b/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationDisplayableManager.h index 4b5a89f8c04ca9ae100d2810641ebf48adad3c65..8e2cb2f184d938e7000b06f2e8609304d78204bb 100644 --- a/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationDisplayableManager.h +++ b/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationDisplayableManager.h @@ -88,6 +88,18 @@ public: /// grid columns or rows > 1 bool IsInLightboxMode(); + /// Gets the world coordinate of the annotation node, transforms it to + /// display coordinates. + /// Defaults to returning the 0th control point's light box index. Returns + /// -1 if not in lightbox mode. + int GetLightboxIndex(vtkMRMLAnnotationNode *node, int controlPointIndex = 0); + + /// Set up data structures for an annotation node. Returns false on failure + /// or if it's already set up. Can be called to reinitialise a node's widgets + /// after calling RemoveWidgetAndNode on the Helper + /// \sa vtkMRMLAnnotationDisplayableManagerHelper::RemoveWidgetAndNode() + bool AddAnnotation(vtkMRMLAnnotationNode *node); + protected: vtkMRMLAnnotationDisplayableManager(); diff --git a/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationFiducialDisplayableManager.cxx b/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationFiducialDisplayableManager.cxx index 245959badfa8e781687a1ca0b02b7e67490efe3d..595cd73360dd7ac383ee610d82c90c27b8d5cf4b 100644 --- a/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationFiducialDisplayableManager.cxx +++ b/Modules/Loadable/Annotations/MRMLDisplayableManager/vtkMRMLAnnotationFiducialDisplayableManager.cxx @@ -104,7 +104,11 @@ public: // only if we had to restrict the coordinates aka. if the coordinates changed, we update the positions if (this->m_DisplayableManager->GetDisplayCoordinatesChanged(displayCoordinates1,restrictedDisplayCoordinates1)) { - representation->SetSeedDisplayPosition(0,restrictedDisplayCoordinates1); + if (representation->GetRenderer() && + representation->GetRenderer()->GetActiveCamera()) + { + representation->SetSeedDisplayPosition(0,restrictedDisplayCoordinates1); + } } } @@ -180,18 +184,35 @@ vtkAbstractWidget * vtkMRMLAnnotationFiducialDisplayableManager::CreateWidget(vt std::cout<<"No DisplayNode!"<::iterator iter = this->NodeGlyphTypes.find(displayNode); + if (iter != this->NodeGlyphTypes.end()) + { + vtkDebugMacro("CreateWidget: found a glyph type already defined for this node: " << iter->second); + this->NodeGlyphTypes[displayNode] = vtkMRMLAnnotationPointDisplayNode::GlyphMin - 1; + } vtkNew rep; - vtkNew handle; - - // default to a starburst glyph, update in propagate mrml to widget - vtkNew glyphSource; - glyphSource->SetGlyphType(vtkMRMLAnnotationPointDisplayNode::StarBurst2D); - glyphSource->Update(); - glyphSource->SetScale(1.0); - handle->SetHandle(glyphSource->GetOutput()); + if (!this->IsInLightboxMode()) + { + vtkDebugMacro("CreateWidget: not in light box mode, making a 3d handle"); + vtkNew handle; + // default to a sphere glyph, update in propagate mrml to widget + vtkNew glyphSource; + glyphSource->SetGlyphType(vtkMRMLAnnotationPointDisplayNode::Sphere3D); + glyphSource->Update(); + glyphSource->SetScale(1.0); + handle->SetHandle(glyphSource->GetOutput()); + rep->SetHandleRepresentation(handle.GetPointer()); + } + else + { + vtkDebugMacro("CreateWidget: in light box mode, making a 2d handle"); + vtkNew handle; + rep->SetHandleRepresentation(handle.GetPointer()); + } - rep->SetHandleRepresentation(handle.GetPointer()); + //seed widget @@ -201,7 +222,18 @@ vtkAbstractWidget * vtkMRMLAnnotationFiducialDisplayableManager::CreateWidget(vt seedWidget->SetRepresentation(rep.GetPointer()); seedWidget->SetInteractor(this->GetInteractor()); - seedWidget->SetCurrentRenderer(this->GetRenderer()); + // set the renderer on the widget and representation + if (!this->IsInLightboxMode()) + { + seedWidget->SetCurrentRenderer(this->GetRenderer()); + seedWidget->GetRepresentation()->SetRenderer(this->GetRenderer()); + } + else + { + int lightboxIndex = this->GetLightboxIndex(fiducialNode); + seedWidget->SetCurrentRenderer(this->GetRenderer(lightboxIndex)); + seedWidget->GetRepresentation()->SetRenderer(this->GetRenderer(lightboxIndex)); + } //seedWidget->ProcessEventsOff(); @@ -297,7 +329,7 @@ void vtkMRMLAnnotationFiducialDisplayableManager::PropagateMRMLToWidget(vtkMRMLA vtkErrorMacro("PropagateMRMLToWidget: Could not get seed widget!") return; } - + // cast to the specific mrml node vtkMRMLAnnotationFiducialNode* fiducialNode = vtkMRMLAnnotationFiducialNode::SafeDownCast(node); @@ -312,7 +344,11 @@ void vtkMRMLAnnotationFiducialDisplayableManager::PropagateMRMLToWidget(vtkMRMLA // now get the widget properties (coordinates, measurement etc.) and if the mrml node has changed, propagate the changes vtkSeedRepresentation * seedRepresentation = vtkSeedRepresentation::SafeDownCast(seedWidget->GetRepresentation()); - + if (!seedRepresentation) + { + vtkErrorMacro("PropagateMRMLToWidget: Could not get seed representation from widget!") + return; + } vtkMRMLAnnotationPointDisplayNode *displayNode = fiducialNode->GetAnnotationPointDisplayNode(); @@ -322,6 +358,54 @@ void vtkMRMLAnnotationFiducialDisplayableManager::PropagateMRMLToWidget(vtkMRMLA } vtkOrientedPolygonalHandleRepresentation3D *handleRep = vtkOrientedPolygonalHandleRepresentation3D::SafeDownCast(seedRepresentation->GetHandleRepresentation(0)); + // might be in lightbox mode where using a 2d point handle + vtkPointHandleRepresentation2D *pointHandleRep = vtkPointHandleRepresentation2D::SafeDownCast(seedRepresentation->GetHandleRepresentation(0)); + // double check that if switch in and out of light box mode, the handle rep + // is updated + bool updateHandleType = false; + if (this->IsInLightboxMode()) + { + if (handleRep) + { + vtkDebugMacro("PropagateMRMLToWidget: have a 3d handle representation in 2d light box, resetting it."); + updateHandleType = true; + } + } + else + { + if (pointHandleRep) + { + vtkDebugMacro("PropagateMRMLToWidget: Not in light box, but have a point handle."); + updateHandleType = true; + } + } + if (updateHandleType) + { + vtkDebugMacro("PropagateMRMLToWidget: removing widget..."); + // clean it out + this->Helper->RemoveWidgetAndNode(node); + // recreate it + vtkMRMLAnnotationNode *annotationNode = vtkMRMLAnnotationNode::SafeDownCast(node); + if (annotationNode) + { + this->AddAnnotation(annotationNode); + } + // did it come back in here + vtkDebugMacro("PropagateMRMLToWidget: did it end up calling this method already?"); + // probably not, so call and return + vtkAbstractWidget * widget = this->Helper->GetWidget(annotationNode); + if (widget) + { + this->PropagateMRMLToWidget(annotationNode, widget); + } + else + { + vtkWarningMacro("PropagateMRMLToWidget: failed to add a new widget for node " << node->GetName()); + return; + } + vtkDebugMacro("PropagateMRMLToWidget: NOW returning after calling self from self"); + return; + } if (handleRep) { if (displayNode) @@ -464,7 +548,50 @@ void vtkMRMLAnnotationFiducialDisplayableManager::PropagateMRMLToWidget(vtkMRMLA handleRep->LabelVisibilityOff(); } }//if (handleRep) - + else if (pointHandleRep) + { + if (displayNode) + { + // glyph type + /* + std::map::iterator iter = this->NodeGlyphTypes.find(displayNode); + if (iter == this->NodeGlyphTypes.end() || iter->second != displayNode->GetGlyphType()) + { + // map the 3d sphere to a filled circle, the 3d diamond to a filled + // diamond + vtkNew glyphSource; + if (displayNode->GetGlyphType() == vtkMRMLAnnotationPointDisplayNode::Sphere3D) + { + glyphSource->SetGlyphType(vtkMRMLAnnotationPointDisplayNode::Circle2D); + } + else if (displayNode->GetGlyphType() == vtkMRMLAnnotationPointDisplayNode::Diamond3D) + { + glyphSource->SetGlyphType(vtkMRMLAnnotationPointDisplayNode::Diamond2D); + } + else + { + glyphSource->SetGlyphType(displayNode->GetGlyphType()); + } + glyphSource->Update(); + glyphSource->SetScale(1.0); + std::cout << "PropagateMRMLToWidget: " << this->GetSliceNode()->GetName() << ": setting point handle rep cursor shape " << glyphSource->GetOutput() << std::endl; + pointHandleRep->SetCursorShape(glyphSource->GetOutput()); + this->NodeGlyphTypes[displayNode] = displayNode->GetGlyphType(); + } + */ + // set the color + if (fiducialNode->GetSelected()) + { + // use the selected color + pointHandleRep->GetProperty()->SetColor(displayNode->GetSelectedColor()); + } + else + { + // use the unselected color + pointHandleRep->GetProperty()->SetColor(displayNode->GetColor()); + } + } + } // now update the position this->UpdatePosition(widget, node); @@ -762,7 +889,13 @@ void vtkMRMLAnnotationFiducialDisplayableManager::UpdatePosition(vtkAbstractWidg { // only update when really changed vtkDebugMacro("UpdatePosition: " << this->GetSliceNode()->GetName() << ": display coordinates changed:\n\tseed display = " << displayCoordinatesBuffer1[0] << ", " << displayCoordinatesBuffer1[1] << "\n\tfid display = " << displayCoordinates1[0] << ", " << displayCoordinates1[1] ); - seedRepresentation->SetSeedDisplayPosition(0,displayCoordinates1); + // make sure the representation has a renderer and an active camera to + // avoid a crash in vtkRenderer::ViewToWorld + if (seedRepresentation->GetRenderer() && + seedRepresentation->GetRenderer()->GetActiveCamera()) + { + seedRepresentation->SetSeedDisplayPosition(0,displayCoordinates1); + } positionChanged = true; } else