gnuplot在Java环境下的应用研究
gnuplot是一个常用的可在Linux, OS/2, MS Windows, OSX, VMS等多种平台下运行的便携的命令行形式的绘图工具。本文以绘制一个3D图象为示例,重点在探索如何在Java环境下应用gnuplot。详细的gnuplot的使用方法在我强烈推荐的参考中可以了解到。
下载安装
下载安装gnuplot(http://www.gnuplot.info/)后,可以在“开始”的“所有程序”这看到如下目录,个个都还挺有用。本文以版本5.0为例。
- gnuplot既提供了console版本,也提供自己的GUI,以GUI起步会比较容易有个大致的印象。
- Demo目录下放有官方提供的所有示例,正如官方提示的,通过
gnuplot> load "all.dem"
可以看到效果。另外官方网站上也有Web版(http://www.gnuplot.info/screenshots/index.html#demos)可供浏览。 - gnuplot Documentaion和gnuplot Help内容是一样的,Help查询起来更方便,另外
gnuplot>? plot
可直接索引到Help下的plot条目,非常好用! - gnuplot FAQ是一些常见问题解答。如果我的英文浏览速度和中文浏览速度一样快,我一定会把它看完。
- gnuplot Quick Reference是快速查询手册,还不错。
- gnuplot on the Web可以打开官网。Uninstall你懂的。
一个3D示例
- 确认在官方demo目录下有一个数据文件
gnu-valley
1
2
3
4
5
6
7
8
9
10
11
12
13
14
150 0 10
0 1 10
0 2 10
1 0 10
1 1 5
1 2 10
2 0 10
2 1 1
2 2 10
3 0 10
3 1 0
3 2 10
注意到,这里第一列为0、1、2、3之间各空了一行。如果没有这些空行,with line会将各数据点按顺序连成一条线。
- 编辑脚本
test.dem
1
2
3
4
5
6
7
8
9
10
11
12
13
14clear # 清除画面
reset # 清空设置
set terminal postscript landscape color enhanced # 设置输出终端为postscript,横向,彩色,enhanced模式(可使用/Symbol)
set output "test.eps" # 输出文件为test.eps
set isosamples 10 # 设置绘图函数表面的等值线网格,越大网格越密,用splot sin(x)可以感觉出来
set grid # 显示xy平面的辅助格线
set xlabel "{/Symbol a}" # 设置x轴文字,打开enhanced模式后可输出部分特殊字符
set ylabel "{/Symbol b}"
set zlabel "Accuracy" offset 8,7 # 向上偏移8,向右偏移7
set view 60,30,1,1 # 设置视角,旋转x轴、z轴,缩放所有轴、z轴
set hidden3d # 不透明,正反面以颜色区分
# set hidden3d offset 0 # 版本5一些需要此句修复hidden3d的linecolor无效的bug,版本5不需要,可见http://sourceforge.net/p/gnuplot/bugs/1475/
# set zrange [0:10] # 设置z轴范围
splot "gnu-valley" with line linecolor 6 notitle # 以line的形式画出3D图,蓝色对应3,无标题
说明:set view的第二个参数是绕z轴顺时针旋转的度数,遵循右手坐标系,旋转示意图如下。
- 执行脚本
gnuplot> load "test.dem"
,得到方便LaTex使用的test.eps
如下
JavaPlot
JavaPlot(http://javaplot.panayotis.com/)是对gnuplot的Java实现库。比之官网,在JavaPlot-0.5.0\demo\src\demo.java提供了更多的例子。
对上面3D示例的模仿(不完全):1
2
3
4
5
6
7
8
9JavaPlot p=new JavaPlot(true);
JavaPlot.getDebugger().setLevel(Debug.VERBOSE);
File file=new File("E:/gnuplot/demo/gnu-valley");
FileDataSet data=new FileDataSet(file);
DataSetPlot s=new DataSetPlot(data);
p.addPlot(s);
PlotStyle stl = ((AbstractPlot) p.getPlots().get(0)).getPlotStyle();
stl.setStyle(Style.LINES);
p.plot();
在Console中输出得到:
Start of plot commands
splot ‘-‘ title ‘Datafile 1’ with lines
0 0 10
0 1 10
0 2 10
e
quit
End of plot commands
exec(D:\Program Files\gnuplot\bin\wgnuplot.exe C:\Users\ADMINI~1\AppData\Local\Temp\gnuplot_8364360726152295267.dat -persist )
Start of error stream
End of error stream
通过显示Debug信息,发现就是转换生成了个临时的gnuplot脚本,然后再执行。问题是JavaPlot错误地把空行当成了文件的结尾,导致不能得到期望的绘图。另一个gnuplot的Java实现 https://github.com/mleoking/JavaGnuplotHybrid 也是基于这样的转换的,并且修复了空行的问题。gnuplot的英文、中文资料都很多,但是JavaPlot、JavaGnuplotHybrid这样的开源库资料示例想当少,遇到问题不方便解决。
因此我认为那些干脆库不要用,省得还要去了解那些库中的方法对应哪些gnuplot命令,而由自己来实现
- Java程序直接生成脚本再通过dos命令执行脚本,类似
exec(wgnuplot.exe test.dat)
; - Java程序直接执行dos命令,对上面3D示例的命令:
1
gnuplot --persist -e "clear; reset; set terminal postscript landscape color enhanced; set output 'test.eps'; set isosamples 10; set grid; set xlabel '{/Symbol a}'; set ylabel '{/Symbol b}'; set zlabel 'Accuracy' offset 8,7; set view 60,30,1,1; set hidden3d; splot 'gnu-valley' with line linecolor 6 notitle"
注意,-e后跟的命令一定要以” “包住,则原命令中” “的部分要改为’ ‘。