Kitware / vtk-js

Visualization Toolkit for the Web
https://kitware.github.io/vtk-js/
BSD 3-Clause "New" or "Revised" License
1.21k stars 370 forks source link

Display vtkLineWidget error when click same postion[Bug] #3096

Open julin927 opened 1 month ago

julin927 commented 1 month ago

Bug description

js+vue2.0+"@kitware/vtk.js": "^25.14.0" , After loading the medical VTK model using VTK.JS, add VTkLineWidget to the model. Click on the blood vessel position with the mouse to create VTkLineWidget. Click on the blood vessel position again and move the mouse to display VTkLineWidget; Now there is a problem: if the second mouse click position is the same as the first mouse click position, VTK will report an exception, causing the VTkLineWidget to not be visible on the interface. How can I solve this problem? The VTK exception is as follows:

Steps to reproduce

1.load and show .vtk in screen 2.click the mouse and create vtkLineWidget 3.click the mouse and move the mouse to display vtkLineWidget 4.the vtkLineWidget not show in screen ,you can see the error in the browser eveloper

Detailed Behavior

No response

Expected Behavior

The vtkLineWidget can diaplay nomal when click same postion

Environment

julin927 commented 1 month ago

add error info: iterableToArray.js:2 Uncaught TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator)) at ht (iterableToArray.js:2:40) at vt (toConsumableArray.js:6:36) at XU.e.placeHandle (behavior.js:195:36) at XU.e.handleLeftButtonPress (behavior.js:228:17) at Object. (InteractorObserver.js:59:46) at i (macros.js:1002:31) at Object.A [as invokeLeftButtonPress] (macros.js:1011:18) at qA.forEach.e. [as leftButtonPressEvent] (RenderWindowInteractor.js:872:33) at e.handleMouseDown (RenderWindowInteractor.js:368:19) at e.handlePointerDown (RenderWindowInteractor.js:295:19)

julin927 commented 1 month ago

add error info: iterableToArray.js:2 Uncaught TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator)) at ht (iterableToArray.js:2:40) at vt (toConsumableArray.js:6:36) at XU.e.placeHandle (behavior.js:195:36) at XU.e.handleLeftButtonPress (behavior.js:228:17) at Object. (InteractorObserver.js:59:46) at i (macros.js:1002:31) at Object.A [as invokeLeftButtonPress] (macros.js:1011:18) at qA.forEach.e. [as leftButtonPressEvent] (RenderWindowInteractor.js:872:33) at e.handleMouseDown (RenderWindowInteractor.js:368:19) at e.handlePointerDown (RenderWindowInteractor.js:295:19)

floryst commented 1 month ago

Does this happen with the latest v31 version of vtk.js?

julin927 commented 1 month ago

Yes,I tested on the latest version and reproduced this issue.

julin927 commented 1 month ago

I test it on [31.0.3] (2024-07-23).I reprodeced it:behavior.js:138 Uncaught TypeError: t.widgetState.getMoveHandle(...).getOrigin(...) is not iterable (cannot read property null) at e.placeHandle (behavior.js:138:12) at e.handleLeftButtonPress (behavior.js:165:17) at Object. (InteractorObserver.js:62:39) at Object.A [as invokeLeftButtonPress] (macros2.js:888:33) at e. [as leftButtonPressEvent] (RenderWindowInteractor.js:835:26) at Ls.e.handleMouseDown (RenderWindowInteractor.js:370:19) at Ls.e.handlePointerDown (RenderWindowInteractor.js:308:19)

floryst commented 3 weeks ago

How are you using the line widget? Can you reproduce it with the online example, or is it based on how you are using it?

julin927 commented 3 weeks ago

https://github.com/user-attachments/assets/1e351941-f461-472c-92cc-ed16cbe567f2

Please check the video! I will attach the code later.

julin927 commented 3 weeks ago

step 1:add listener for click :document.body.addEventListener("click", this.bodyClick, false); step 2: do action when receive click event: bodyClick(e) { console.log("bodyClick",e); const position = { x: e.clientX, y: e.clientY, z: 0.0, }; // console.log(position); this.markRenderer(position); },

temp.markRenderer = function (pos) { console.log("接收点击事件"); let myCanvas = document.getElementsByTagName("canvas")[0]; const myCanvaswidth = myCanvas.offsetWidth; const width = myCanvas.width; const myCanvasHeight = myCanvas.offsetHeight; const height = myCanvas.height; const point = [ (pos.x / myCanvaswidth) width, // (pos.y / myCanvasHeight) height, // pos.x, ((myCanvasHeight - pos.y) / myCanvasHeight) * height, 0.0, ];

      // console.log(this.getMyDate(Date.now()),"获取点开始");
        // const picker = vtkCellPicker.newInstance();

        // picker.setPickFromList(3);
        // picker.setTolerance(0.005);
        // picker.initializePickList();
        // picker.addPickList(calculater.modelActor);
        // picker.pick(point, renderer);
        // var pickedPoints = picker.getPickedPositions();
        // console.log("pickedPoints:", pickedPoints);
        // var pickPoint = pickedPoints[0];
        // console.log("pickPoint:", pickPoint);
        // console.log(this.getMyDate(Date.now()),"获取点结束");

                  // 执行拾取操作
      // const picker = vtkCellPicker.newInstance();
      // picker.pick(point, renderer);

      // // // 获取拾取结果
      // console.log(this.getMyDate(Date.now()),'获取拾取结果');
      // const actor = picker.getActors()[0];
      // var data = {data: 0, cell: null,point:null};
      // if (actor) {
      //   console.log(this.getMyDate(Date.now()),'点击了模型!');
      //   console.log(this.getMyDate(Date.now()),"计算ffr开始");
      //   data = calculater.CalDiamByScreePoint(renderer, point,this.showObb);
      //   console.log("拾取结果","picker.getCellId():", picker.getCellId());
      //   console.log(this.getMyDate(Date.now()),"计算ffr结束");
      // } else {
      //   console.log(this.getMyDate(Date.now()),'点击了背景!');
      //   return;
      // }
      console.log(this.getMyDate(Date.now()),"计算ffr开始");
      const data = calculater.CalDiamByScreePoint(renderer, point,this.showObb);
      console.log(this.getMyDate(Date.now()),"计算ffr结束");
      // data.cell = 11;
      console.log(`markRenderer,data.cell: `,data.cell);
      // console.log(`markRenderer,this.widget: `,this.widget);
      if (data.cell != null){
        // if(this.widget != null){
        //   widgetManager.releaseFocus(this.widget);
        // }
        var pickPoint = data.point;

        if(pickPoint != null && pickPoint.length < 1){
          this.lineWidgetFlag = false;
          return;
        }
        console.log(`markRenderer,pickPoint: `,pickPoint);
        const point2 = [
          pickPoint[0]+3,
          pickPoint[1]-3,
          pickPoint[2],
        ];
        //vtkLineWidget
        console.log('markRenderer,new vtkLineWidget');

        if(this.lineWidgetFlag == true){
          //lineHandle.setText(""+data.cell);
          console.log('markRenderer,防止重建 vtkLineWidget');
          return;
        }
        this.lineWidget = vtkLineWidget.newInstance();
        let lineHandle = this.curLineHandle = this.widgetManager.addWidget(this.lineWidget);//,ViewTypes.SLICE); 
        let widgetState = lineHandle.getWidgetState();
        const subState = lineHandle.getWidgetState().getPositionOnLine();
        subState.setPosOnLine(1.00);
        lineHandle.setText(""+data.cell);
        widgetState.setLineThickness(1);
        widgetState.getMoveHandle().setVisible(true)
        widgetState.getMoveHandle().setScale1(14);
        widgetState.getHandle1().setShape("sphere")
        widgetState.getHandle2().setShape("sphere") 
        widgetState.getHandle1().setScale1(12);
        widgetState.getHandle2().setScale1(12);
        widgetState.getHandle1().setVisible(false);
        widgetState.getHandle2().setVisible(false);
        widgetState.getMoveHandle().setColor(0.3);
        this.lineWidgetFlag = true;
        // lineHandle.updateHandleVisibility(1);

        // lineHandle.
        // widgetState.onModified(() => {
        //   console.log("vtkLineWidget 改变:");
        //   const subState = lineHandle.getWidgetState().getPositionOnLine();
        //   subState.setPosOnLine(1.0);
        //   lineHandle.setText(""+data.cell);
        //   // renderWindow.render();
        // });
        this.lineWidget.getManipulator().setUserOrigin(pickPoint);
        this.widgetManager.grabFocus(this.lineWidget);
        lineHandle.onStartInteractionEvent(() => {
          const index = this.widgetManager.getWidgets().findIndex((cwidget) => {
            if (DeepEqual(lineHandle.getWidgetState(), cwidget.getWidgetState()))
              return 1;
            return 0;
          });
          console.log("onStartInteractionEvent,index:",index);
          this.lineWidget = this.widgetManager.getWidgets()[index];
        });
        // lineHandle.onStartInteractionEvent(() => {
        //   const index = widgetManager.getWidgets().findIndex((cwidget) => {
        //     return 1;
        //   });
        //   lineHandle.getWidgetState().getHandle1().setColor(color);
        //   lineHandle.getWidgetState().getHandle2().setColor(color);
        //   lineHandle.setUseActiveColor(false);
        //   lineHandle.getWidgetState().getMoveHandle().setColor(0.3);
        // });
        // this.setupSVG2(renderer,lineHandle,pickPoint,point2);
        // lineHandle.onEndInteractionEvent(() => {
        //   console.log("onEndInteractionEvent");
        // });
        renderWindow.render();
        lineHandle.getInteractor().render();

        // render();
      }else{
        console.log("无效点击!:");
        // if(this.lineWidgetFlag == true){
        //   this.curLineHandle.setText(""+data.cell);
        // }
        this.lineWidgetFlag = false;
        // if(this.lineWidget != null){
        //   this.widgetManager.releaseFocus(this.lineWidget);
        // }
      }

      return;
      // });
    };