上一次实现了基于vtk的petrel地质模型的三维显示,调用的是C#的接口,后来开始研究基于vtk的三维地震数据的显示,有很多文献发表了读取地震数据然后借助vtk进行显示的方法。从vtk8.0开始,添加了直接读取segy格式的的地震数据,不需要自己编写segy的读写模块。
不过vtk官方最新的开源C#版本一直是vtk5.6版本,新版本需要收费,而其它语言接口的版本不收费,要采用vtk8.0或最新的8.2版本,必须采用C++、Python或java版本。鉴于java和C#很相似,因此选择了java接口的vtk。
从vtk官方下载了最新的vtk8.2版本,按照官方说明用cmake和visual stuio 2017进行编译,得到了java语言版本的vtk库,包括一个jar文件和216个dll文件,并把它上传到到了github上,分享给懒得编译的小伙伴。https://github.com/yanfeng1022/javaVTK.git
用新版本的vtk读取和显示三维地震数据非常简单,只要指定segy文件的名字,把读取结果转化为vtkStructuredGrid, vtkImageData,或vtkUnstructuredGrid,就可以按照相应的格式显示了。具体代码如下:
private void drawSegy3D(String filename) {
//read segy file and assign to vtkStructuredGrid
vtkSegYReader segYReader = new vtkSegYReader();
System.out.println(filename);
segYReader.SetFileName(filename);
vtkImageData segyImage = segYReader.GetImageDataOutput();
vtkStructuredGrid segyGrid = segYReader.GetStructuredGridOutput();
vtkStructuredPoints points = segYReader.GetStructuredPointsOutput();
segYReader.Update();
try {
int[] dim = new int[3];
dim = segyGrid.GetDimensions();
int nk=dim[2];
int nj=dim[1];
int ni=dim[0];
System.out.println("nk="+ nk+" nj="+ nj+" ni="+ni);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
//create a mapper
vtkDataSetMapper mapper = new vtkDataSetMapper();
mapper.SetInputData(segyGrid);
double[] scalarRange=segyGrid.GetScalarRange();
for(int i=0;i<scalarRange.length;i++)
System.out.println(scalarRange[i]+"\t");
mapper.SetScalarRange(scalarRange[0], scalarRange[1]);
//create the actor
vtkActor actor = new vtkActor();
actor.SetMapper(mapper);
actor.GetProperty().SetDiffuseColor(1, 1, 0);
//actor.GetProperty().SetOpacity(0.3);
vtkTransform transform = new vtkTransform();
transform.Scale(1, 1, 5);
actor.SetUserTransform(transform);
vtkRenderer render = new vtkRenderer();
vtkRenderWindow renWin = new vtkRenderWindow();
//设置交互样式
vtkRenderWindowInteractor renwinIn = new vtkRenderWindowInteractor();
renwinIn.SetRenderWindow(renWin);
renWin.AddRenderer(render);
render.SetBackground(1, 1, 1); //飙泪ue(0,0,1),red(1,0,0)
render.AddActor(actor);
//设置坐标轴
vtkAxesActor axesActor = new vtkAxesActor();
vtkOrientationMarkerWidget widget = new vtkOrientationMarkerWidget();
widget.SetOutlineColor(0.1, 0.1, 0.1);
widget.SetOrientationMarker(axesActor);
widget.SetInteractor(renwinIn);
widget.SetEnabled(1);
widget.InteractiveOn();
//可视化输出
render.ResetCamera();
renWin.Render();
renwinIn.Start();
}
具体显示结果如下,可以很方便地旋转和缩放,读取速度也挺快。