[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