Control point modified event is not fired

Hi,

I think I’ve found a bug:

lineNode = slicer.mrmlScene.CreateNodeByClass("vtkMRMLMarkupsLineNode")
slicer.mrmlScene.AddNode(lineNode)
slicer.modules.markups.logic().AddNewDisplayNodeForMarkupsNode(lineNode)
lineNode.SetName("myLineNode")

observerTag = lineNode.AddObserver(
    slicer.vtkMRMLMarkupsNode.PointModifiedEvent,
    lambda arg1,arg2: print("Point modified")
)

# does print
lineNode.AddControlPoint(vtk.vtkVector3d(0,0,0))
# does print
lineNode.AddControlPoint(vtk.vtkVector3d(50,50,50))

for i in range(lineNode.GetNumberOfControlPoints()):
    # doesn't print but it should
    lineNode.RemoveNthControlPoint(0) 

Maybe I’m doing something wrong, please explain

Best wishes,
Mauro

We try to invoke a PointModifiedEvent whenever it is possible to reduce the number of events that modules have to observe. However, in case of deleting a point it would not be clear if the point id refers to the point that was removed or to the point that was moved to the removed point’s position. Instead, vtkMRMLMarkupsNode::PointAboutToBeRemovedEvent and vtkMRMLMarkupsNode::PointRemovedEvent events are invoked with the removed point’s index.

I can see that this behavior may seem inconsistent and it may be inconvenient that you need to observe an additional event, so let me know if you think it would help you if different events were invoked. It would not be a problem at all to invoke a PointModifiedEvent with the removed point’s index if that would greatly simplify your code.

1 Like

I tried doing something like:

observerTag = lineNode.AddObserver(
    slicer.vtkMRMLMarkupsNode.PointModifiedEvent | slicer.vtkMRMLMarkupsNode.PointRemovedEvent,
    lambda arg1,arg2: print("Point modified")
)

But it did not work.
I don’t mind another observer for the moment

The result of slicer.vtkMRMLMarkupsNode.PointModifiedEvent | slicer.vtkMRMLMarkupsNode.PointRemovedEvent operation is some number that probably does not correspond to any event ID. You need to add and remove each observer separately.

1 Like

how to access control point index in invoked function.

Below is the python snippet,is it right way?

pointListNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLMarkupsFiducialNode"
        )
pointListNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointAboutToBeRemovedEvent,on_point_to_be_removed)
def on_point_to_be_removed(caller,event):
        markupsNode = caller
        sliceView = markupsNode.GetAttribute("Markups.MovingInSliceView")
        movingMarkupIndex = markupsNode.GetDisplayNode().GetActiveControlPoint()
        print(movingMarkupIndex)
        label=markupsNode.GetNthControlPointLabel(movingMarkupIndex)

Output:
-1
GUI used to remove the control point.

I want to access label of control point to be removed.
Thank you.

I don’t have any working example but I think you need to define the callback function like this:

@vtk.calldata_type(vtk.VTK_INT)
def onPointAboutToBeRemoved(self, caller, eventId, callData):

The callData will be the point index. self obviously is only needed if the callback is a member function.