date: 2019-04-02 10:24:00
VTK Java项目构建和运行
准备工作
本文的运行环境是Ubuntu。在自己建立的VTK build的文件夹(这里名称为VTK-bin,见前文),找到vtk.jar
,这里在VTK-bin/lib
下。
新建工程
使用JetBrains的IDEA新建一个工程,将样例代码(见附录A)添加到工程中的src
中,
添加vtk.jar
将make
之后生成的VTK-bin/lib
路径下的vtk.jar
路径添加到Project Structure->Modules->Dependencies中。
添加库
Ubuntu中.so文件相当于windows下的.dll动态链接库文件,
将make
之后生成的VTK-bin/lib
路径加入到环境变量中,
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/[你自己的路径]/VTK-bin/lib
在IDEA中,File->Project Structure->Libraries(或者Ctrl+Shift+Alt+s),
编译运行
正常的结果如下:
若出现类似vtkxxxx not loaded
,如下图所示,原因在于make之后的库文件没有配置正确,导致程序无法调用。若vtk.jar
文件配置错误,则程序本身语法上会报错(本文中没有出现这种情况)。
程序不报错,但是一些vtk开头的库无法加载,
java.lang.UnsatisfiedLinkError: no vtkFiltersPointsJava in java.library.path
提示有类似上面的错误,
怀疑是java.library.path中缺少链接库。Ubuntu中.so文件相当于windows下的.dll动态链接库文件,将make
之后生成的VTK-bin/lib
路径加入到环境变量中,
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/xxxx/VTK-bin/lib
在IDEA中,File->Project Structure->Libraries(或者Ctrl+Shift+Alt+s),将上面的路径添加进来,重新编译,成功运行。
注意
- 在添加Library路径之前已经将
vtk.jar
路径添加到Project Structure->Modules->Dependencies中。 - 有Windows下的文章说讲生成的
.dll
文件复制到JAVA_HOME/bin
下[3],在Ubuntu下尝试类似做法,行不通。 - IDEA中使用
File->Create->Project from Existing Files
,创建工程不生成src
文件夹,按照相同的配置可能出错。
参考
[1] VTK Java Wrappinghttps://vtk.org/Wiki/VTK/Java_Wrapping#Linux
[2] Java加载dll或so库文件的路径 java.library.path.https://blog.csdn.net/daylight_1/article/details/70199452
[3] vtk-8.01的java版本环境配置.https://blog.csdn.net/sinat_23619409/article/details/85106858
参考
[1] https://www.particleincell.com/2011/vtk-java-visualization/
附录
附录A. 一个vtk java样例程序
来源
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JToggleButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import vtk.vtkNativeLibrary;
import vtk.vtkPanel;
import vtk.vtkActor;
import vtk.vtkSphere;
import vtk.vtkSphereSource;
import vtk.vtkSampleFunction;
import vtk.vtkContourFilter;
import vtk.vtkPlane;
import vtk.vtkCutter;
import vtk.vtkLookupTable;
import vtk.vtkPolyDataMapper;
/* ************************************************************
* Demo applications showcasing how to use VTK with Java
*
* Based on SimpleVTK.java example distributed with VTK
*
* For more information see:
* http://www.particleincell.com/2011/vtk-java-visualization
*
* Information about VTK can be found at:
* http://vtk.org/
*
* ***********************************************************/
public class DemoJavaVTK extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private vtkPanel renWin;
private vtkActor cutActor;
private vtkActor isoActor;
private JPanel buttons;
private JToggleButton slicesButton;
private JToggleButton isoButton;
private JButton exitButton;
/* Load VTK shared librarires (.dll) on startup, print message if not found */
static
{
if (!vtkNativeLibrary.LoadAllNativeLibraries())
{
for (vtkNativeLibrary lib : vtkNativeLibrary.values())
{
if (!lib.IsLoaded())
System.out.println(lib.GetLibraryName() + " not loaded");
}
System.out.println("Make sure the search path is correct: ");
System.out.println(System.getProperty("java.library.path"));
}
vtkNativeLibrary.DisableOutputWindow(null);
}
/* Constructor - generates visualization pipeline and adds actors*/
public DemoJavaVTK()
{
super(new BorderLayout()); /* large center and small border areas*/
double radius = 0.8; /*sphere radius*/
/**** 1) INPUT DATA: Sphere Implicit Function ****/
vtkSphere sphere = new vtkSphere();
sphere.SetRadius(radius);
vtkSampleFunction sample = new vtkSampleFunction();
sample.SetSampleDimensions(50,50,50);
sample.SetImplicitFunction(sphere);
/**** 2) PIPELINE 1: Isosurface Actor ****/
/* contour filter - will generate isosurfaces from 3D data*/
vtkContourFilter contour = new vtkContourFilter();
contour.SetInputConnection(sample.GetOutputPort());
contour.GenerateValues(3,0,1);
/* mapper, translates polygonal representation to graphics primitives */
vtkPolyDataMapper isoMapper = new vtkPolyDataMapper();
isoMapper.SetInputConnection(contour.GetOutputPort());
/*isosurface actor*/
isoActor = new vtkActor();
isoActor.SetMapper(isoMapper);
/**** 3) PIPELINE 2: Cutting Plane Actor ****/
/* define a plane in x-y plane and passing through the origin*/
vtkPlane plane = new vtkPlane();
plane.SetOrigin(0,0,0);
plane.SetNormal(0,0,1);
/* cutter, basically interpolates source data onto the plane */
vtkCutter planeCut = new vtkCutter();
planeCut.SetInputConnection(sample.GetOutputPort());
planeCut.SetCutFunction(plane);
/*this will actually create 3 planes at the subspace where the implicit
* function evaluates to -0.7, 0, 0.7 (0 would be original plane). In
* our case this will create three x-y planes passing through
* z=-0.7, z=0, and z=+0.7*/
planeCut.GenerateValues(3,-0.7,0.7);
/* look up table, we want to reduce number of values to get discrete bands */
vtkLookupTable lut = new vtkLookupTable();
lut.SetNumberOfTableValues(5);
/* mapper, using our custom LUT */
vtkPolyDataMapper cutMapper = new vtkPolyDataMapper();
cutMapper.SetInputConnection(planeCut.GetOutputPort());
cutMapper.SetLookupTable(lut);
/* cutting plane actor, looks much better with flat shading */
cutActor = new vtkActor();
cutActor.SetMapper(cutMapper);
cutActor.GetProperty().SetInterpolationToFlat();
/**** 4) PIPELINE 3: Surface Geometry Actor ****/
/* create polygonal representation of a sphere */
vtkSphereSource surf = new vtkSphereSource();
surf.SetRadius(radius);
/* another mapper*/
vtkPolyDataMapper surfMapper = new vtkPolyDataMapper();
surfMapper.SetInputConnection(surf.GetOutputPort());
/* surface geometry actor, turn on edges and apply flat shading*/
vtkActor surfActor = new vtkActor();
surfActor.SetMapper(surfMapper);
surfActor.GetProperty().EdgeVisibilityOn();
surfActor.GetProperty().SetEdgeColor(0.2,0.2,0.2);
surfActor.GetProperty().SetInterpolationToFlat();
/**** 5) RENDER WINDOW ****/
/* vtkPanel - this is the interface between Java and VTK */
renWin = new vtkPanel();
/* add the surface geometry plus the isosurface */
renWin.GetRenderer().AddActor(surfActor);
renWin.GetRenderer().AddActor(isoActor);
/* the default zoom is whacky, zoom out to see the whole domain */
renWin.GetRenderer().GetActiveCamera().Dolly(0.2);
renWin.GetRenderer().SetBackground(1, 1, 1);
/**** 6) CREATE PANEL FOR BUTTONS ****/
buttons = new JPanel();
buttons.setLayout(new GridLayout(1,0));
/* isosurface button, clicked by default */
isoButton = new JToggleButton("Isosurfaces",true);
isoButton.addActionListener(this);
/* cutting planes button */
slicesButton = new JToggleButton("Slices");
slicesButton.addActionListener(this);
/* exit button */
exitButton = new JButton("Exit");
exitButton.addActionListener(this);
/* add buttons to the panel */
buttons.add(isoButton);
buttons.add(slicesButton);
buttons.add(exitButton);
/**** 7) POPULATE MAIN PANEL ****/
add(renWin, BorderLayout.CENTER);
add(buttons, BorderLayout.SOUTH);
}
/* ActionListener that responds to button clicks
* Toggling iso/slices buttons results in addition or removal
* of the corresponding actor */
public void actionPerformed(ActionEvent e)
{
/*cutting planes button, add or remove cutActor */
if (e.getSource().equals(slicesButton))
{
if (slicesButton.isSelected())
renWin.GetRenderer().AddActor(cutActor);
else
renWin.GetRenderer().RemoveActor(cutActor);
renWin.Render();
}
/*isosurface button, add or remove isoActor */
else if (e.getSource().equals(isoButton))
{
if (isoButton.isSelected())
renWin.GetRenderer().AddActor(isoActor);
else
renWin.GetRenderer().RemoveActor(isoActor);
renWin.Render();
}
/*exit button, end application */
else if (e.getSource().equals(exitButton))
{
System.exit(0);
}
}
/* main, creates a new JFrame and populates it with the DemoJavaVTK panel */
public static void main(String s[])
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new JFrame("Java and VTK Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(new DemoJavaVTK(), BorderLayout.CENTER);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}