我想制作凸包图形,为 Gnuplot 提供连接图形表面的顶点。
我一直在测试,但我没有任何明确的方法来做到这一点。
我可以用这个脚本绘制点:
set encoding iso_8859_1
set terminal postscript eps enhanced color size 4.0in,4.0in #"Helvetica" 16
set output "RG1.eps"
set view 50,220
unset colorbox
splot "convex1.dat" with lines notitle ,\
"convex1.dat" u 1:2:3 with points palette pointsize 3 pointtype 7
其中凸1.dat包含这些点
0 0 0
0 0 0.285957
0 0.285957 0.285957
0 0.3812378724 0.1906189362
0 0.571914 0
0.1906761276 0.3812378724 0.1906189362
0.285957 0.285957 0.285957
0.571914 0 0
0.571914 0 0.285957
这个脚本的表示是:
我可以在 Mathematica 环境中用这些点制作凸包,并创建我正在寻找的图形类型:
问题是:如何使用 Gnuplot 制作凸包,如 Mathematica 图形,以及如何使用透明度来比较具有相同轴的两个凸包来制作图形?
Gnuplot 主要是结构化数值数据的渲染器;它并不是一个数学处理系统,也不是一个几何数据的渲染器。
pm3d
的 splot
样式允许您绘制任意多边形集合,但它不会删除隐藏的表面,更不用说基于多个多边形相交的复杂渲染了。事实上,文档本身说:
Gnuplot 不是计算填充交集的虚拟现实工具 多边形网格。
对于这类事情,您需要使用实际的数学处理包(例如 Mathematica!),它可以输出为矢量格式,然后直接使用它,而不是通过 Gnuplot。
也许您甚至可以仅使用 gnuplot-only 来完成它,但是,可能相当麻烦、冗长且缓慢。 因此,这里建议如何在外部帮助下完成此操作:QHull
数据:
SO50699586.dat
(OP的数据)
0 0 0
0 0 0.285957
0 0.285957 0.285957
0 0.3812378724 0.1906189362
0 0.571914 0
0.1906761276 0.3812378724 0.1906189362
0.285957 0.285957 0.285957
0.571914 0 0
0.571914 0 0.285957
对于程序
qhull
,您需要以下输入格式:
3 # dimension 3D
9 # number or following x,y,z points
x0 y0 z1
x1 y1 z1
...
x8 y8 y8
命令
qhull -G input
的输出将具有以下格式:
{appearance {+edge -evert linewidth 2} LIST # | qhull -G
{ OFF 3 1 1 # f1
0.5719 0 -3.967e-15
0 0.5719 -3.967e-15
0 0 -3.967e-15
3 0 1 2 0.5 0.5 0 1.0 }
{ OFF 4 1 1 # f2
0.5719 -3.967e-15 0.286
0.5719 -3.967e-15 0
0 -3.967e-15 0
0 -3.967e-15 0.286
4 0 1 2 3 0.5 0 0.5 1.0 }
{ OFF 4 1 1 # f5
0.286 0.286 0.286
2.805e-15 0.5719 0
0.5719 2.805e-15 0
0.5719 2.805e-15 0.286
4 0 1 2 3 0.8536 0.8536 0.5 1.0 }
{ OFF 3 1 1 # f11
0.286 0.286 0.286
0 0.286 0.286
0 0.5719 2.805e-15
3 0 1 2 0.5 0.8536 0.8536 1.0 }
{ OFF 4 1 1 # f3
-3.967e-15 0.5719 0
-3.967e-15 0.286 0.286
-3.967e-15 0 0.286
-3.967e-15 0 0
4 0 1 2 3 0 0.5 0.5 1.0 }
{ OFF 4 1 1 # f10
0 0.286 0.286
0.286 0.286 0.286
0.5719 0 0.286
0 0 0.286
4 0 1 2 3 0.5 0.5 1 1.0 }
}
不幸的是,这种格式不适合用 gnuplot 直接绘图。也许有更适合 gnuplot 的输出格式。 所以,你需要:
{
开头的其他行中提取第一个数字,该数字表示后续面的顶点数(主要是 3 或 4),但不要将该行添加到表格中$Data
因此数据块
$Data
看起来像这样:
0.5719 0 -3.967e-15
0 0.5719 -3.967e-15
0 0 -3.967e-15
0.5719 -3.967e-15 0.286
0.5719 -3.967e-15 0
0 -3.967e-15 0
0 -3.967e-15 0.286
0.286 0.286 0.286
2.805e-15 0.5719 0
0.5719 2.805e-15 0
0.5719 2.805e-15 0.286
0.286 0.286 0.286
0 0.286 0.286
0 0.5719 2.805e-15
-3.967e-15 0.5719 0
-3.967e-15 0.286 0.286
-3.967e-15 0 0.286
-3.967e-15 0 0
0 0.286 0.286
0.286 0.286 0.286
0.5719 0 0.286
0 0 0.286
这些是需要用 gnuplot 绘制的多边形。 gnuplot>=5.4.0(2020 年 7 月)的绘图风格为
with polygons
。也许还有通过 with pm3d
的 gnuplot 5.2 解决方案。
船体的计算速度相当快。约1000点在约2秒内完成。
脚本:(适用于 gnuplot>=5.4.0,2020 年 7 月)
### plot convex 3D-hull (with external help: QHull)
reset session
FILE = "SO50699586.dat"
HULL_IN = FILE[1:strlen(FILE)-3].'qhin' # qhull input
HULL_OUT = FILE[1:strlen(FILE)-3].'hull' # qhull output
stats FILE u 0 nooutput # extract number of points
set table HULL_IN
plot '+' every ::::1 u (int($0)?STATS_records:3) w table, \
FILE u 1:2:3 w table
unset table
# run qhull
system(qhull -G <'.HULL_IN.' >'.HULL_OUT)
set table $Data
plot HULL_OUT skip 1 u (strcol(1) eq '{' ? (p=$3,c=0,'') : \
(c=c+1,c<=p?sprintf("%g %g %g",$1,$2,$3):'')) w table
unset table
set view equal xyz
set view 60,210, 1.3
set pm3d depth
set pm3d border lc "black" lw 0.5
set key noautotitle
set xyplane relative 0
splot for [i=0:*] $Data index i u 1:2:3 w polygons fc rgb int(0x1000000*rand(0)*0.5+0x777777)
### end of script
结果:
脚本:(用于在球体上生成 1000 个随机点。然后运行上面的脚本)
# create some random points (on a sphere surface)
FILE = "SO50699586.dat"
set table FILE
set sample 1000
plot '+' u (a=rand(0)*2*pi,b=rand(0)*pi,cos(a)*sin(b)):(sin(a)*sin(b)):(cos(b)) w table
unset table
结果:(在 <2 seconds on my 8 year old laptop)