Commit 6289b334 authored by lassoan's avatar lassoan

ENH: Reworked markups fiducials and added line, angle, and curves

Features:
- New markups: angle, line, open curve, closed curve
- Speed improvement: thousands of markup points can be visualized and interactively manipulated (previously, the limit was about 50-100 points)
- Live preview: preview of markup position and label is shown during placement in all views, current point is highlighted in all views
- Slide on surface: in 3D views, markups are kept on visible surfaces (previously, placement was done on visible surface, but adjustments were simply constrained to the view plane)
- Improved keyboard shortcuts:
  - LeftClick to jump to control point
  - LeftClick-and-drag: translate control point
  - Delete: delete highlighted markup
  - Ctrl-LeftClick: insert point along line
  - MiddleClick-and-drag: translate widget (experimental)

Fixes:
- Labels in 3D can no longer be partially obscured by 3D geometry (sometimes labels are visible when the corresponding markup is not visible anymore, but this will be fixed soon)
- Point picking in 3D views is unstable

Infrastructure improvements:
- Focus management is centralized (interactor style queries all the displayable managers if they can process the event and then forwards the event for processing to the most suitable one). This allows much faster event management than using VTK's picking manager.
- Interaction events are converted to vtkEventData type (originally introduced for virtual reality), which can carry all important metadata with them (display and world position, key modifiers, associated view and data nodes, etc.). This allows processing all kinds of interaction events (mouse, keyboard, virtual reality, any new interaction devices, etc.) using the same framework and modules have easy access to lots of metadata in all interaction events.
- Maximum number of markups can be specified for markups fiducials (e.g., if it is set to 1 then the markup node can be used for getting a single point from the user).
- Any point can be placed again (no user interface for this yet) - this can be used for predefining markup names and then place them.
- Keyboard shortcuts are configurable (no user interface yet) - flexible module/application specific keyboard mapping is feasible (VTK's event translator does not support event translation with modifiers, widget-state-dependent shortcuts, etc.)
- No more synchronization needed between MRML and widget states: widget states are directly stored in MRML, including point positions (as vtkPolyData) - in local and world coordinate system. This removed lots of synchronization overhead and potential for bugs.

Note that this first set of changes is just a beginning of a number of new features and improvements.
Co-authored-by: Andras Lasso's avatarAndras Lasso <lasso@queensu.ca>

git-svn-id: http://svn.slicer.org/Slicer4/trunk@27974 3bd1e089-480b-0410-8dfb-8563597acbee
parent f6c71ba2
......@@ -988,3 +988,33 @@ vtkRenderer* vtkMRMLAbstractDisplayableManager::GetRenderer(int idx)
}
}
//---------------------------------------------------------------------------
bool vtkMRMLAbstractDisplayableManager::CanProcessInteractionEvent(vtkMRMLInteractionEventData* eventData, double &distance2)
{
distance2 = VTK_DOUBLE_MAX;
return false;
}
//---------------------------------------------------------------------------
bool vtkMRMLAbstractDisplayableManager::ProcessInteractionEvent(vtkMRMLInteractionEventData* eventData)
{
return false;
}
//---------------------------------------------------------------------------
void vtkMRMLAbstractDisplayableManager::SetHasFocus(bool hasFocus)
{
return;
}
//---------------------------------------------------------------------------
bool vtkMRMLAbstractDisplayableManager::GetGrabFocus()
{
return false;
}
//---------------------------------------------------------------------------
bool vtkMRMLAbstractDisplayableManager::GetInteractive()
{
return false;
}
......@@ -26,6 +26,7 @@
#include "vtkMRMLDisplayableManagerExport.h"
class vtkMRMLInteractionEventData;
class vtkMRMLInteractionNode;
class vtkMRMLSelectionNode;
class vtkMRMLDisplayableManagerGroup;
......@@ -90,6 +91,24 @@ public:
virtual std::string GetDataProbeInfoStringForPosition(
double vtkNotUsed(xyz)[3]) { return ""; }
/// Return true if the displayable manager can process the event.
/// Distance2 is the squared distance in display coordinates from the closest interaction position.
/// The displayable manager with the closest distance will get the chance to process the interaction event.
virtual bool CanProcessInteractionEvent(vtkMRMLInteractionEventData* eventData, double &distance2);
/// Process an interaction event.
/// Returns true if the event should be aborted (not processed any further by other event observers).
virtual bool ProcessInteractionEvent(vtkMRMLInteractionEventData* eventData);
/// Set if the widget gets/loses focus (interaction events are processed by this displayable manager).
virtual void SetHasFocus(bool hasFocus);
/// Displayable manager can indicate that it would like to get all events (even when mouse pointer is outside the window).
virtual bool GetGrabFocus();
/// Displayable manager can indicate that the window is in interactive mode (faster updates).
virtual bool GetInteractive();
protected:
vtkMRMLAbstractDisplayableManager();
......
/*==============================================================================
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.
==============================================================================*/
#ifndef __vtkMRMLInteractionEventData_h
#define __vtkMRMLInteractionEventData_h
// VTK includes
#include "vtkCommand.h"
#include "vtkEvent.h"
#include "vtkEventData.h"
#include "vtkInteractorStyleUser.h"
#include "vtkMatrix4x4.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkWeakPointer.h"
// MRML includes
#include "vtkMRMLDisplayableManagerExport.h"
class vtkMRMLAbstractDisplayableManager;
class vtkMRMLSegmentationDisplayNode;
class vtkMRMLSliceLogic;
class vtkMRMLDisplayableManagerGroup;
class vtkMRMLAbstractViewNode;
/// Class for storing all relevant details of mouse and keyboard events.
/// It stores additional information that is expensive to compute (such as 3D position)
/// or not always easy to get (such as modifiers).
class VTK_MRML_DISPLAYABLEMANAGER_EXPORT vtkMRMLInteractionEventData : public vtkEventData
{
public:
vtkTypeMacro(vtkMRMLInteractionEventData, vtkEventData);
static vtkMRMLInteractionEventData *New()
{
vtkMRMLInteractionEventData *ret = new vtkMRMLInteractionEventData;
ret->InitializeObjectBase();
return ret;
};
/// Extends vtkCommand events
enum MRMLInteractionEvents
{
LeftButtonClickEvent = vtkCommand::UserEvent + 300, // button press and release without moving mouse
MiddleButtonClickEvent,
RightButtonClickEvent
};
void SetType(unsigned long v) { this->Type = v; }
void SetModifiers(int v) { this->Modifiers = v; }
int GetModifiers() { return this->Modifiers; }
void GetWorldPosition(double v[3]) const
{
std::copy(this->WorldPosition, this->WorldPosition + 3, v);
}
const double *GetWorldPosition() const
{
return this->WorldPosition;
}
void SetWorldPosition(const double p[3])
{
this->WorldPosition[0] = p[0];
this->WorldPosition[1] = p[1];
this->WorldPosition[2] = p[2];
this->WorldPositionValid = true;
}
bool IsWorldPositionValid()
{
return this->WorldPositionValid;
}
void SetWorldPositionInvalid()
{
this->WorldPositionValid = false;
}
void GetDisplayPosition(int v[2]) const
{
std::copy(this->DisplayPosition, this->DisplayPosition + 2, v);
}
const int *GetDisplayPosition() const
{
return this->DisplayPosition;
}
void SetDisplayPosition(const int p[2])
{
this->DisplayPosition[0] = p[0];
this->DisplayPosition[1] = p[1];
this->DisplayPositionValid = true;
}
bool IsDisplayPositionValid()
{
return this->DisplayPositionValid;
}
void SetDisplayPositionValid()
{
this->DisplayPositionValid = false;
}
void SetKeyCode(char v) { this->KeyCode = v; }
char GetKeyCode() { return this->KeyCode; }
void SetKeyRepeatCount(char v) { this->KeyRepeatCount = v; }
int GetKeyRepeatCount() { return this->KeyRepeatCount; }
void SetKeySym(const std::string &v) { this->KeySym = v; }
const std::string& GetKeySym() { return this->KeySym; }
void SetViewNode(vtkMRMLAbstractViewNode* viewNode) { this->ViewNode = viewNode; }
vtkMRMLAbstractViewNode* GetViewNode() { return this->ViewNode; }
void SetComponentType(int componentType) { this->ComponentType = componentType; }
int GetComponentType() { return this->ComponentType; }
void SetComponentIndex(int componentIndex) { this->ComponentIndex = componentIndex; }
int GetComponentIndex() { return this->ComponentIndex; }
/// Set Modifiers and Key... attributes from interactor
void SetAttributesFromInteractor(vtkRenderWindowInteractor* interactor)
{
this->Modifiers = 0;
if (interactor->GetShiftKey())
{
this->Modifiers |= vtkEvent::ShiftModifier;
}
if (interactor->GetControlKey())
{
this->Modifiers |= vtkEvent::ControlModifier;
}
if (interactor->GetAltKey())
{
this->Modifiers |= vtkEvent::AltModifier;
}
this->KeyCode = interactor->GetKeyCode();
this->KeySym = (interactor->GetKeySym() ? interactor->GetKeySym() : "");
this->KeyRepeatCount = interactor->GetRepeatCount();
}
protected:
int Modifiers;
int DisplayPosition[2];
double WorldPosition[3];
bool DisplayPositionValid;
bool WorldPositionValid;
vtkMRMLAbstractViewNode* ViewNode;
int ComponentType;
int ComponentIndex;
// For KeyPressEvent
char KeyCode;
int KeyRepeatCount;
std::string KeySym;
bool Equivalent(const vtkEventData *e) const override
{
const vtkMRMLInteractionEventData *edd = static_cast<const vtkMRMLInteractionEventData *>(e);
if (this->Type != edd->Type)
{
return false;
}
if (edd->Modifiers >= 0 && (this->Modifiers != edd->Modifiers))
{
return false;
}
return true;
};
vtkMRMLInteractionEventData()
{
this->Type = 0;
this->Modifiers = 0;
this->DisplayPosition[0] = 0;
this->DisplayPosition[1] = 0;
this->WorldPosition[0] = 0.0;
this->WorldPosition[1] = 0.0;
this->WorldPosition[2] = 0.0;
this->DisplayPositionValid = false;
this->WorldPositionValid = false;
this->KeyRepeatCount = 0;
this->KeyCode = 0;
this->ViewNode = nullptr;
}
~vtkMRMLInteractionEventData() override {}
private:
vtkMRMLInteractionEventData(const vtkMRMLInteractionEventData& c) = delete;
void operator=(const vtkMRMLInteractionEventData&) = delete;
};
#endif
......@@ -167,6 +167,8 @@ vtkMRMLOrientationMarkerDisplayableManager::vtkInternal::vtkInternal(vtkMRMLOrie
this->RendererUpdateObservationId = 0;
this->DisplayedActor = NULL;
this->MarkerRenderer = vtkSmartPointer<vtkRenderer>::New();
// Prevent erasing Z-buffer (important for quick picking and markup label visibility assessment)
this->MarkerRenderer->EraseOff();
this->HumanPolyData = vtkSmartPointer<vtkPolyData>::New();
this->HumanPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
this->AxesActorFontViewportSize = 0.0;
......
......@@ -124,6 +124,8 @@ vtkMRMLRulerDisplayableManager::vtkInternal::vtkInternal(vtkMRMLRulerDisplayable
this->RendererUpdateObservationId = 0;
this->ActorsAddedToRenderer = false;
this->MarkerRenderer = vtkSmartPointer<vtkRenderer>::New();
// Prevent erasing Z-buffer (important for quick picking and markup label visibility assessment)
this->MarkerRenderer->EraseOff();
this->RulerLineActor = vtkSmartPointer<vtkAxisActor2D>::New();
this->RulerTextActor = vtkSmartPointer<vtkTextActor>::New();
}
......
......@@ -18,13 +18,15 @@
// VTK includes
#include "vtkInteractorStyleUser.h"
#include "vtkMatrix4x4.h"
#include "vtkWeakPointer.h"
// MRML includes
#include "vtkMRMLDisplayableManagerExport.h"
class vtkMRMLAbstractDisplayableManager;
class vtkMRMLSegmentationDisplayNode;
class vtkMRMLSliceLogic;
class vtkMRMLDisplayableManagerGroup;
/// \brief Provides customizable interaction routines.
///
......@@ -35,7 +37,8 @@ class vtkMRMLSliceLogic;
/// * Do we need Rotate Mode? Probably better to just rely on the reformat widget
/// * Do we need to set the slice spacing on EnterEvent (I say no, nothing to do
/// with linked slices should go in here)
class VTK_MRML_DISPLAYABLEMANAGER_EXPORT vtkSliceViewInteractorStyle : public vtkInteractorStyleUser
class VTK_MRML_DISPLAYABLEMANAGER_EXPORT vtkSliceViewInteractorStyle :
public vtkInteractorStyleUser
{
public:
static vtkSliceViewInteractorStyle *New();
......@@ -47,29 +50,32 @@ public:
/// and composite node (sometimes using the logic's methods) or
/// they are passed to the vtkInteractorStyleUser, which conditionally
/// passes them to observers if there are any.
///
/// Generic event bindings
virtual void OnMouseMove() VTK_OVERRIDE;
virtual void OnEnter() VTK_OVERRIDE;
virtual void OnLeave() VTK_OVERRIDE;
virtual void OnLeftButtonDown() VTK_OVERRIDE;
virtual void OnLeftButtonUp() VTK_OVERRIDE;
virtual void OnMiddleButtonDown() VTK_OVERRIDE;
virtual void OnMiddleButtonUp() VTK_OVERRIDE;
virtual void OnRightButtonDown() VTK_OVERRIDE;
virtual void OnRightButtonUp() VTK_OVERRIDE;
/// MouseWheel callbacks added for slicer
virtual void OnMouseWheelForward() VTK_OVERRIDE;
virtual void OnMouseWheelBackward() VTK_OVERRIDE;
///
/// Keyboard functions
virtual void OnChar() VTK_OVERRIDE;
virtual void OnKeyPress() VTK_OVERRIDE;
virtual void OnKeyRelease() VTK_OVERRIDE;
///
/// These are more esoteric events, but are useful in some cases.
virtual void OnExpose() VTK_OVERRIDE;
virtual void OnConfigure() VTK_OVERRIDE;
virtual void OnEnter() VTK_OVERRIDE;
virtual void OnLeave() VTK_OVERRIDE;
void SetDisplayableManagers(vtkMRMLDisplayableManagerGroup* displayableManagers);
/// Give a chance to displayable managers to process the event.
/// Return true if the event is processed.
bool ForwardInteractionEventToDisplayableManagers(unsigned long event);
/// Internal state management for multi-event sequences (like click-drag-release)
......@@ -116,6 +122,9 @@ public:
/// Adjust zoom factor. If zoomScaleFactor>1 then view is zoomed in,
/// if 0<zoomScaleFactor<1 then view is zoomed out.
void ScaleZoom(double zoomScaleFactor);
void DoZoom();
void DoRotate();
/// Collect some boilerplate management steps so they can be used
/// in more than one place
......@@ -125,11 +134,13 @@ public:
/// Enter a mode where the mouse moves are used to change the foreground
/// or labelmap opacity.
void StartBlend();
void DoBlend();
void EndBlend();
/// Enter a mode where the mouse moves are used to change the window/level
/// setting.
void StartAdjustWindowLevel();
void DoAdjustWindowLevel();
void EndAdjustWindowLevel();
/// Convert event coordinates (with respect to viewport) into
......@@ -157,8 +168,8 @@ public:
void SetLabelOpacity(double opacity);
double GetLabelOpacity();
protected:
protected:
vtkSliceViewInteractorStyle();
~vtkSliceViewInteractorStyle();
......@@ -175,10 +186,6 @@ protected:
int ActionState;
int ActionsEnabled;
/// Indicates whether the shift key was used during the previous action.
/// This is used to require shift-up before returning to default mode.
bool ShiftKeyUsedForPreviousAction;
int StartActionEventPosition[2];
double StartActionFOV[3];
double VolumeScalarRange[2];
......@@ -191,6 +198,15 @@ protected:
vtkMRMLSliceLogic *SliceLogic;
bool MouseMovedSinceButtonDown;
/// Indicates whether the shift key was used during the previous action.
/// This is used to require shift-up before returning to default mode.
bool ShiftKeyUsedForPreviousAction;
vtkWeakPointer<vtkMRMLDisplayableManagerGroup> DisplayableManagers;
vtkMRMLAbstractDisplayableManager* FocusedDisplayableManager;
private:
vtkSliceViewInteractorStyle(const vtkSliceViewInteractorStyle&); /// Not implemented.
void operator=(const vtkSliceViewInteractorStyle&); /// Not implemented.
......
......@@ -19,6 +19,7 @@
// MRML includes
#include "vtkMRML.h"
#include "vtkMRMLCameraNode.h"
#include "vtkMRMLDisplayableManagerGroup.h"
// VTK includes
#include "vtkObject.h"
......@@ -27,8 +28,9 @@
#include "vtkMRMLDisplayableManagerExport.h"
class vtkMRMLModelDisplayableManager;
class vtkCellPicker;
class vtkMRMLModelDisplayableManager;
class vtkWorldPointPicker;
/// \brief Interactive manipulation of the camera.
///
......@@ -49,23 +51,18 @@ class vtkCellPicker;
/// \sa vtkInteractorStyleJoystickCamera
/// \sa vtkInteractorStyleJoystickActor
class VTK_MRML_DISPLAYABLEMANAGER_EXPORT vtkThreeDViewInteractorStyle :
public vtkInteractorStyle
public vtkInteractorStyle
{
public:
static vtkThreeDViewInteractorStyle *New();
vtkTypeMacro(vtkThreeDViewInteractorStyle,vtkInteractorStyle);
void PrintSelf(ostream& os, vtkIndent indent) VTK_OVERRIDE;
/// Reimplemented for camera orientation
virtual void OnChar() VTK_OVERRIDE;
virtual void OnKeyPress() VTK_OVERRIDE;
virtual void OnKeyRelease() VTK_OVERRIDE;
///
/// Event bindings controlling the effects of pressing mouse buttons
/// or moving the mouse.
virtual void OnMouseMove() VTK_OVERRIDE;
virtual void OnEnter() VTK_OVERRIDE;
virtual void OnLeave() VTK_OVERRIDE;
virtual void OnLeftButtonDown() VTK_OVERRIDE;
virtual void OnLeftButtonUp() VTK_OVERRIDE;
......@@ -76,17 +73,20 @@ public:
virtual void OnMouseWheelForward() VTK_OVERRIDE;
virtual void OnMouseWheelBackward() VTK_OVERRIDE;
/// These methods for the different interactions in different modes
/// are overridden in subclasses to perform the correct motion. Since
/// they are called by OnTimer, they do not have mouse coord parameters
/// (use interactor's GetEventPosition and GetLastEventPosition)
virtual void Rotate() VTK_OVERRIDE;
virtual void Spin() VTK_OVERRIDE;
virtual void Pan() VTK_OVERRIDE;
virtual void Dolly() VTK_OVERRIDE;
virtual void Dolly(double factor);
/// Keyboard functions
virtual void OnChar() VTK_OVERRIDE;
virtual void OnKeyPress() VTK_OVERRIDE;
virtual void OnKeyRelease() VTK_OVERRIDE;
/// These are more esoteric events, but are useful in some cases.
virtual void OnExpose() VTK_OVERRIDE;
virtual void OnConfigure() VTK_OVERRIDE;
void SetDisplayableManagers(vtkMRMLDisplayableManagerGroup* displayableManagers);
/// Give a chance to displayable managers to process the event.
/// Return true if the event is processed.
bool ForwardInteractionEventToDisplayableManagers(unsigned long event);
///
/// Get/Set the CameraNode
......@@ -101,36 +101,45 @@ public:
/// Get/Set the ModelDisplayableManager, for picking
vtkGetObjectMacro(ModelDisplayableManager, vtkMRMLModelDisplayableManager);
virtual void SetModelDisplayableManager(vtkMRMLModelDisplayableManager *modelDisplayableManager);
/// These methods for the different interactions in different modes
/// are overridden in subclasses to perform the correct motion. Since
/// they are called by OnTimer, they do not have mouse coord parameters
/// (use interactor's GetEventPosition and GetLastEventPosition)
virtual void Rotate() VTK_OVERRIDE;
virtual void Spin() VTK_OVERRIDE;
virtual void Pan() VTK_OVERRIDE;
virtual void Dolly() VTK_OVERRIDE;
virtual void Dolly(double factor);
protected:
vtkThreeDViewInteractorStyle();
~vtkThreeDViewInteractorStyle();
bool Pick(int x, int y, double pickPoint[3]);
static void ThreeDViewProcessEvents(vtkObject* object, unsigned long event, void* clientdata, void* calldata);
bool AccuratePick(int x, int y, double pickPoint[3]);
bool QuickPick(int x, int y, double pickPoint[3]);
vtkMRMLCameraNode *CameraNode;
double MotionFactor;
/// Indicates whether the shift key was used during the previous action.
/// This is used to require shift-up before returning to default mode.
bool ShiftKeyUsedForPreviousAction;
/// Keep track of the number of picks so for resetting mouse modes when
/// transient pick or place mode has been selected.
int NumberOfPlaces;
/// The number of "clicks" the transient mouse-modes come loaded with.
/// Currently makes sense to set this to 1 -- but we can change it if appropriate.
int NumberOfTransientPlaces;
///
/// A pointer back to the ModelDisplayableManager, useful for picking
vtkMRMLModelDisplayableManager * ModelDisplayableManager;
/// For jump to slice feature (when mouse is moved while shift key is pressed)
vtkSmartPointer<vtkCellPicker> CellPicker;
vtkSmartPointer<vtkCellPicker> AccuratePicker;
vtkSmartPointer<vtkWorldPointPicker> QuickPicker;
bool MouseMovedSinceButtonDown;
/// Indicates whether the shift key was used during the previous action.
/// This is used to require shift-up before returning to default mode.
bool ShiftKeyUsedForPreviousAction;
vtkWeakPointer<vtkMRMLDisplayableManagerGroup> DisplayableManagers;
vtkMRMLAbstractDisplayableManager* FocusedDisplayableManager;
private:
vtkThreeDViewInteractorStyle(const vtkThreeDViewInteractorStyle&); /// Not implemented.
......
......@@ -1303,7 +1303,8 @@ void vtkMRMLSliceLogic::CreateSliceModel()
this->SliceModelNode->SetDisableModifiedEvent(1);
this->SliceModelNode->SetHideFromEditors(1);
this->SliceModelNode->SetSelectable(0);
// allow point picking (e.g., placing a markups point on the slice node)
this->SliceModelNode->SetSelectable(1);
this->SliceModelNode->SetSaveWithScene(0);
// create plane slice
......
......@@ -156,6 +156,7 @@ void qMRMLSliceViewPrivate::init()
this->LightBoxRendererManagerProxy->SetLightBoxRendererManager(
q->lightBoxRendererManager());
this->initDisplayableManagers();
interactorStyle->SetDisplayableManagers(this->DisplayableManagerGroup);
// Force an initial render to ensure that the render window creates an OpenGL
// context. If operations that require a context--such as hardware
......
......@@ -101,6 +101,7 @@ void qMRMLThreeDViewPrivate::init()
q->setYawDirection(ctkVTKRenderView::YawLeft);
this->initDisplayableManagers();
interactorStyle->SetDisplayableManagers(this->DisplayableManagerGroup);
}
//---------------------------------------------------------------------------
......
......@@ -136,7 +136,7 @@ int main(int argc, char *argv[])
// toggle some settings
if (i == 0)
{
copiedFiducialNode->SetNthMarkupLocked(i, 1);
copiedFiducialNode->SetNthFiducialLocked(i, 1);
copiedFiducialNode->SetNthFiducialSelected(i, 0);
copiedFiducialNode->SetNthFiducialVisibility(i, 0);
}
......
......@@ -91,10 +91,10 @@ public:
/// jump the slice windows to the given coordinate
/// If viewGroup is -1 then all all slice views are updated, otherwise only those views
/// that are in the specified group.
void JumpSlicesToLocation(double x, double y, double z, bool centered, int viewGroup = -1);
void JumpSlicesToLocation(double x, double y, double z, bool centered, int viewGroup = -1, vtkMRMLSliceNode* exclude = NULL);
/// jump the slice windows to the nth markup with the mrml id id
/// \sa JumpSlicesToLocation
void JumpSlicesToNthPointInMarkup(const char *id, int n, bool centered = false, int viewGroup = -1);
void JumpSlicesToNthPointInMarkup(const char *id, int n, bool centered = false, int viewGroup = -1, vtkMRMLSliceNode* exclude = NULL);
/// refocus all of the 3D cameras to the nth markup with the mrml id id
/// \sa FocusCameraOnNthPointInMarkup
void FocusCamerasOnNthPointInMarkup(const char *id, int n);
......@@ -152,23 +152,37 @@ public:
/// utility method to set up a display node from the defaults
void SetDisplayNodeToDefaults(vtkMRMLMarkupsDisplayNode *displayNode);
/// utility method to copy a markup from one list to another, adding it
/// utility method to copy a control point from one list to another, adding it
/// to the end of the new list
/// \sa vtkMRMLMarkupsNode::AddMarkup
/// \sa vtkMRMLMarkupsNode::AddControlPoint
/// Returns true on success, false on failure
bool CopyNthMarkupToNewList(int n, vtkMRMLMarkupsNode *markupsNode,
bool CopyNthControlPointToNewList(int n, vtkMRMLMarkupsNode *markupsNode,
vtkMRMLMarkupsNode *newMarkupsNode);
/// utility method to move a markup from one list to another, trying to
/// Deprecated, use CopyNthControlPointToNewList instead.
bool CopyNthMarkupToNewList(int n, vtkMRMLMarkupsNode *markupsNode,
vtkMRMLMarkupsNode *newMarkupsNode)
{
return this->CopyNthControlPointToNewList(n, markupsNode, newMarkupsNode);
}
/// utility method to move a control point from one list to another, trying to
/// insert it at the given new index. If the new index is larger than the
/// number of markups in the list, adds it to the end. If new index is
/// number of control points in the list, adds it to the end. If new index is
/// smaller than 0, adds it at the beginning. Otherwise inserts at
/// that index.
/// \sa vtkMRMLMarkupsNode::InsertMarkup
/// \sa vtkMRMLMarkupsNode::InsertControlPoint
/// Returns true on success, false on failure
bool MoveNthMarkupToNewListAtIndex(int n, vtkMRMLMarkupsNode *markupsNode,
bool MoveNthControlPointToNewListAtIndex(int n, vtkMRMLMarkupsNode *markupsNode,
vtkMRMLMarkupsNode *newMarkupsNode, int newIndex);
/// Deprecated, use MoveNthControlPointToNewList instead.
bool MoveNthMarkupToNewList(int n, vtkMRMLMarkupsNode *markupsNode,
vtkMRMLMarkupsNode *newMarkupsNode, int newIndex)
{
return this->MoveNthControlPointToNewListAtIndex(n, markupsNode, newMarkupsNode, newIndex);
}
/// Searches the scene for annotation fidicual nodes, collecting a list
/// of annotation hierarchy nodes. Then iterates through those hierarchy nodes
/// and moves the fiducials that are under them into new markups nodes. Leaves
......@@ -197,6 +211,9 @@ public:
/// in the scene
void SetSliceIntersectionsVisibility(bool flag);