[vtkusers] faster vtkFXCanvas class created, can not use file copy.

nagao saichi nagao-saichi at jcom.home.ne.jp
Tue May 23 21:52:54 EDT 2017


public class vtkFXCanvas extends StackPane {
	//
  // -----------------------------------------------------------------
  // Load VTK library and print which library was not properly loaded
  static {
      if (!vtkNativeLibrary.LoadAllNativeLibraries()) {
          for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {
              if (!lib.IsLoaded()) {
                  System.out.println(lib.GetLibraryName() + " not loaded");
              }
          }
      }
      vtkNativeLibrary.DisableOutputWindow(null);
  }

  // -----------------------------------------------------------------
	/**
	 * vtkのレンダリングを行うパネル
	 */
  private vtkCanvas canvas3D = new vtkCanvas();
	/**
   * vtkCanvasのイメージをFXのImageViewにコピーする方法は、ファイルを介して
   * 行うのが、簡単で早いみたい。一旦イメージファイルに保存して、ファイルから
   * FXのImageViewに表示する。
   */
//  vtkPNGWriter writer = new vtkPNGWriter();
//	File tempFile = new File("__temp__.png");
//	String uri = tempFile.toURI().toString();
	/**
	 * StackPaneに実装するノード、SwingNodeは、vtkCanvasをのせるために
	 * 使用する。
	 */
  SwingNode swingNode = new SwingNode();
  /**
   * vtkCanvasのレンダリングされたイメージを表示するために、ImageView
   * を使用する。
   */
  ImageView imageNode = new ImageView();

  private Timer repaintimer;
  /**
   * 再描画時間間隔、イメージのコピーの時間により調整される。
   */
  private int repaintInterval = 100;
	/**
   * イメージの設定フラグ
   */
  private int setimageflag = -1;
  /**
   * コンストラクタ
   */
  public vtkFXCanvas() {
    EventHandler<MouseEvent>mHandler0 = ( event ) -> mousePressed(event);
    EventHandler<MouseEvent>mHandler1 = ( event ) -> mouseDragged(event);
    EventHandler<MouseEvent>mHandler2 = ( event ) -> mouseReleased(event);
    EventHandler<ScrollEvent>mHandler3 = ( event ) ->
mouseWheelMoved(event);
    EventHandler<MouseEvent>mHandler4 = ( event ) -> mouseMoved(event);
    EventHandler<MouseEvent>mHandler5 = ( event ) -> mouseEntered(event);
    EventHandler<MouseEvent>mHandler6 = ( event ) -> mouseExited(event);

    EventHandler<KeyEvent>kHandler0 = ( event ) -> keyTyped(event);
//    EventHandler<KeyEvent>kHandler1 = ( event ) -> keyPressed(event);
//    EventHandler<KeyEvent>kHandler2 = ( event ) -> keyReleased(event);

    imageNode.addEventHandler(MouseEvent.MOUSE_PRESSED ,  mHandler0	);
    imageNode.addEventHandler(MouseEvent.MOUSE_DRAGGED ,  mHandler1	);
    imageNode.addEventHandler(MouseEvent.MOUSE_RELEASED ,  mHandler2	);
    imageNode.addEventHandler(ScrollEvent.SCROLL ,  mHandler3	);
    imageNode.addEventHandler(MouseEvent.MOUSE_MOVED ,  mHandler4	);
    imageNode.addEventHandler(MouseEvent.MOUSE_ENTERED ,  mHandler5	);
    imageNode.addEventHandler(MouseEvent.MOUSE_EXITED ,  mHandler6	);
    /*
     * キーイベントは、swingNodeにキーフォーカスがあると、
     * vtkCanvasに送られる。
     * swingNode exists keyfocus , keyevent sends to vtkCanvas
     */
//    imageNode.addEventHandler(KeyEvent.KEY_TYPED ,  kHandler1	);
//    imageNode.addEventHandler(KeyEvent.KEY_PRESSED ,  kHandler0	);
//    imageNode.addEventHandler(KeyEvent.KEY_RELEASED ,  kHandler2	);
    // only for setimage method execute at key type.
    swingNode.addEventHandler(KeyEvent.KEY_TYPED ,  kHandler0	);

    getChildren().add(swingNode);
    getChildren().add(imageNode);
    // can not see , but must be true
    swingNode.setVisible(true);
    imageNode.setFocusTraversable(false);
    swingNode.setFocusTraversable(true);
    imageNode.setVisible(true);
  	imageNode.autosize();
//    imageNode.requestFocus();

    JPanel jcomp = new JPanel();
    jcomp.setLayout(new BorderLayout());
    jcomp.add(canvas3D, BorderLayout.CENTER);
    swingNode.setContent(jcomp);
    /*
     * 以下の行を入れないと、小さくしたときリサイズしない。
     * 最小のサイズが、起動した時のサイズになっている。
     * if below line does not insert , then smaller resize is bad.
     */
    setMinSize(1, 1);
 }
  /**
   * マウスの押下イベント処理メソッド
   * @param e FXのマウスイベントオブジェクト
   */
  private void mousePressed(MouseEvent e) {
  	setimageflag = 1;
  	canvas3D.mousePressed(toSwingEvent(e));
  }
  /**
   * マウスのドラッグイベント処理メソッド
   * @param e FXのマウスイベントオブジェクト
   */
  private void mouseDragged(MouseEvent e) {
  	setimageflag = 2;
  	canvas3D.mouseDragged(toSwingEvent(e));
  }
  /**
   * マウスのリリースイベント処理メソッド
   * @param e FXのマウスイベントオブジェクト
   */
  private void mouseReleased(MouseEvent e) {
  	setimageflag = 4;
  	canvas3D.mouseReleased(toSwingEvent(e));
  }
  /**
   * マウスの出域イベント処理メソッド
   * @param e FXのマウスイベントオブジェクト
   */
  private void mouseEntered(MouseEvent e) {
  	setimageflag = 8;
  	canvas3D.mouseEntered(toSwingEvent(e));
  }
  /**
   * マウスの入域イベント処理メソッド
   * @param e FXのマウスイベントオブジェクト
   */
  private void mouseExited(MouseEvent e) {
  	setimageflag = 16;
  	canvas3D.mouseExited(toSwingEvent(e));
  }
  /**
   * マウスのムーブイベント処理メソッド
   * @param e FXのマウスイベントオブジェクト
   */
  private void mouseMoved(MouseEvent e) {
  	// not repaint on mouse Move
  	setimageflag = 0;
  	canvas3D.mouseMoved(toSwingEvent(e));
  }
  /**
   * マウスのスクロールイベント処理メソッド
   * @param e FXのマウスイベントオブジェクト
   */
  private void mouseWheelMoved(ScrollEvent e) {
  	int modifiers = 0;
  	int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL;
  	int scrollAmount = e.getTouchCount();
  	int wheelRotation = (int)e.getDeltaY();
  	//  System.out.println("wheelRotation="+wheelRotation);
  	if(e.isShiftDown()) modifiers+= java.awt.event.InputEvent.SHIFT_MASK;
  	if(e.isAltDown()) modifiers+= java.awt.event.InputEvent.ALT_MASK;
  	if(e.isControlDown()) modifiers+= java.awt.event.InputEvent.CTRL_MASK;

  	MouseWheelEvent mwe = new MouseWheelEvent(canvas3D,
MouseWheelEvent.WHEEL_UNIT_SCROLL,
  			System.currentTimeMillis(),
  			modifiers, (int)e.getX(), (int)e.getY(), e.getTouchCount(),
  			false, scrollType, scrollAmount, wheelRotation);

  	setimageflag = 64;
  	canvas3D.mouseWheelMoved(mwe);
  }
  /**
   * FXのマウスイベントオブジェクトをSwingのマウスイベントオブジェクトに変換する。
   * @param e FXのマウスイベントオブジェクト
   * @return Swingのマウスイベントオブジェクト
   */
  private java.awt.event.MouseEvent toSwingEvent(MouseEvent e) {
  	int modifiers = 0;
  	int button = 0;
  	if(e.isShiftDown()) modifiers+= java.awt.event.InputEvent.SHIFT_MASK;
  	if(e.isAltDown()) modifiers+= java.awt.event.InputEvent.ALT_MASK;
  	if(e.isControlDown()) modifiers+= java.awt.event.InputEvent.CTRL_MASK;
  	if(e.getButton() == MouseButton.PRIMARY) modifiers +=
java.awt.event.InputEvent.BUTTON1_MASK;
  	if(e.getButton() == MouseButton.MIDDLE) modifiers +=
java.awt.event.InputEvent.BUTTON2_MASK;
  	if(e.getButton() == MouseButton.SECONDARY) modifiers +=
java.awt.event.InputEvent.BUTTON3_MASK;

  	if(e.getButton() == MouseButton.PRIMARY) button = 0;
  	if(e.getButton() == MouseButton.MIDDLE) button = 1;
  	if(e.getButton() == MouseButton.SECONDARY) button = 2;
//  	System.out.println("button="+button+", modifiers="+modifiers+",
setimageflag="+setimageflag);
//  	System.out.println("X="+e.getX()+", Y="+e.getY()+",
getClickCount="+e.getClickCount());

  	java.awt.event.MouseEvent event = new java.awt.event.MouseEvent(canvas3D,
  			button,  System.currentTimeMillis(), modifiers,
  			(int)e.getX(), (int)e.getY(), e.getClickCount(), false);
  	return event;
  }
  /**
   * キータイプイベント処理メソッド
   * @param e FXのキーイベント
   */
  private void keyTyped(KeyEvent e) {
  	setimageflag = 128;
  	canvas3D.keyTyped(toSwingEvent(e));
  }
  /**
   * キー押下イベント処理メソッド
   * @param e FXのキーイベント
   */
  private void keyPressed(KeyEvent e) {
  	setimageflag = 256;
  	canvas3D.keyPressed(toSwingEvent(e));
  }
  /**
   * キーリリースイベント処理メソッド
   * @param e FXのキーイベント
   */
  private void keyReleased(KeyEvent e) {
  	setimageflag = 512;
  	canvas3D.keyReleased(toSwingEvent(e));
  }
  /**
   * FXのキーベントオブジェクトをSwingのキーイベントオブジェクトに変換する。
   * @param e FXのキーイベントオブジェクト
   * @return Swingのキーイベントオブジェクト
   */
  private java.awt.event.KeyEvent toSwingEvent(KeyEvent e) {
  	int id = 0;
  	long when = System.currentTimeMillis();
  	int modifiers = 0;
  	if(e.isShiftDown()) modifiers+= java.awt.event.InputEvent.SHIFT_MASK;
  	if(e.isControlDown()) modifiers+= java.awt.event.InputEvent.CTRL_MASK;
  	if(e.isAltDown()) modifiers+= java.awt.event.InputEvent.ALT_MASK;

  	char keychar = e.getCharacter().charAt(0);
  	int keycode = Integer.valueOf(keychar);
//  	System.out.println("keyChar="+keychar+", keyCode="+keycode+",
setimageflag="+setimageflag);

  	java.awt.event.KeyEvent event = new java.awt.event.KeyEvent(canvas3D,
  			id, when, modifiers, keycode, keychar);
  	return event;
  }
  /**
   * vtkCanvasのイメージを、FXのImageViewにコピーする。ファイル渡しで
   * コピーする。
   */
  public synchronized void setImage() {
  	long st = System.currentTimeMillis();

    vtkWindowToImageFilter w2if = new vtkWindowToImageFilter();
    canvas3D.lock();
    /**
     * 以下の行を入力すると、Widgetの操作が正常に行うことができる。
     * insert below line , then Widget controll is fine.
     */
    canvas3D.getRenderWindowInteractor().SetEnableRender(false);
    w2if.SetInput(canvas3D.GetRenderWindow());
    w2if.Update();
    canvas3D.unlock();
/* not used
  	writer.SetInput(w2if.GetOutput());
    writer.SetFileName(tempFile.getPath());
    writer.Write();
    javafx.scene.image.Image img = new javafx.scene.image.Image(uri);
  	imageNode.setImage(img);
*/
    // faster than file copy method!
 		imageNode.setImage(createWritableImage(w2if.GetOutput()));

 		long en = System.currentTimeMillis();
  	long diff = en-st+10;
  	if(repaintInterval < diff) {
//  		System.out.println("Copy imege time="+(diff-10)+" msec");
  		repaintInterval = (int)diff;
  	} else {
    	repaintimer.setDelay(repaintInterval-=5);
//  		System.out.println("repaint interval ="+repaintInterval);
  	}
//  	System.out.println("setimageflag="+setimageflag);
  }
  /**
   * vtkImageDataから、javafxのWritableImageクラスを作成する。
   * このクラスほうが、早い。faster than file read.
   *
   * @param image vtkImageDataクラス
   * @return WritableImageクラス
   */
  public WritableImage createWritableImage(vtkImageData image) {
  	int w = canvas3D.getWidth();
  	int h = canvas3D.getHeight();
/*
    int dim[] = image.GetDimensions();
    System.out.println("dim1="+dim[0]+", dim2="+dim[1]+", dim3="+dim[2]);

    System.out.println("Number of points: " +image.GetNumberOfPoints());
    System.out.println("Number of cells:  " +image.GetNumberOfCells());

    System.out.println("width: " +w);
    System.out.println("height:" +h);
    System.out.println("compornent="+image.GetNumberOfScalarComponents());
*/
  	// 白紙イメージを作成, empty image created.
  	WritableImage   wImg = new WritableImage(w, h);
  	// ピクセル処理
  	PixelWriter  writer  = wImg.getPixelWriter();
  	vtkFieldData field =  image.GetPointData();
  	vtkUnsignedCharArray array =  (vtkUnsignedCharArray)field.GetArray(0);
//  	System.out.println("num array ="+field.GetNumberOfArrays());
//  	System.out.println("num comp  ="+field.GetNumberOfComponents());

  	PixelFormat<ByteBuffer> form = PixelFormat.getByteRgbInstance();

  	writer.setPixels(0, 0, w, h, form, array.GetJavaArray(), 0, w*3);

  	return wImg;

  }
  /**
   * サイズの変更可能。
   */
  public boolean isResizable() {
  	return true;
  }
  /**
   * 描画領域の大きさを設定する。
   * @param width 幅
   * @param height 高さ
   */
  public void setSize(int width, int height) {
  	canvas3D.setSize(width, height);
  }
  /**
   * 描画領域のSwingオブジェクトを取得する。
   * @return vtkCanvas
   */
  public vtkCanvas getCanvas3D() {
  	return canvas3D;
  }
  /**
   * 再描画タイマーオブジェクトの取得
   * @return タイマーオブジェクト
   */
  public Timer getRepaintimer() {
		return repaintimer;
	}
  /**
   * 表示アクターの追加
   * @param actor 表示するアクター
   */
  public void addActor(vtkActor actor) {
  	canvas3D.GetRenderer().AddActor(actor);
  }
  /**
   * イメージノードの大きさをシーンに合わせます。タイマーを作成し
   * 起動します。このメソッドは、シーンを作成した後に実行します。
   * <p>
   * This method execute after scene created.
   * </p>
   */
  public void renderStart() {
  	imageNode.fitWidthProperty().bind(widthProperty());
  	imageNode.fitHeightProperty().bind(heightProperty());
    /*
     * イメージコピータイマーの定義
     */
    repaintimer = new Timer(repaintInterval, new ActionListener() {
    	@Override
    	public void actionPerformed(ActionEvent e) {
    		if(setimageflag == -1) {
    			setImage();
    			setimageflag = 1;
    			canvas3D.GetRenderer().ResetCamera();
    		} else if(setimageflag > 0) {
    			setImage();
    			setimageflag = 0;
      		SwingUtilities.invokeLater(() -> {
      			canvas3D.repaint();
//      			System.out.println("repaint");
      			});
    		}
    	}
    });
    repaintimer.setInitialDelay(800);
    repaintimer.start();

  }
  /**
   * 終了処理、タイマーの停止とイメージファイルの消去
   */
  public void finalize() {
  	try {
			super.finalize();
			repaintimer.stop();
//			tempFile.delete();
			setimageflag = -1;
		} catch (Throwable e) {
			e.printStackTrace();
		}
  }
}




--
View this message in context: http://vtk.1045678.n5.nabble.com/VTK-and-JavaFX-tp5728083p5743376.html
Sent from the VTK - Users mailing list archive at Nabble.com.


More information about the vtkusers mailing list