我找不到一个选项来让gnuplot自动设置多边形对象的深度顺序。我唯一找到的方法是预先以正确的顺序定义对象。然后gnuplot会在前一个对象的上方绘制每个对象,从而得到预期的结果。
在删除
front
说明符后,使用您的示例多边形,这种方法会改变原始图片,如下所示:
![enter image description here](https://istack.dev59.com/GHHoH.webp)
转化为这个(删除 front
后):
![enter image description here](https://istack.dev59.com/cETo1.webp)
到了这一个(排序后):
![enter image description here](https://istack.dev59.com/eRGcQ.webp)
我认为第三张图片是你想要的。
我使用了一个Python脚本来对多边形进行排序,基本上做了以下几点:
- 从文件“poly_raw.dat”中读取所有多边形。该文件必须以
set object x polygon from
行开头。
- 像gnuplot一样使用
set view theta, phi
,将多边形绕x和z轴旋转(暂时只用于排序)。
- 根据新的y轴对多边形进行排序。这应该是垂直于屏幕的轴。
- 更新gnuplot对象ID,即
set object x polygon
中的x
。
- 打印排序后的多边形数据,包括
set object
行。
请注意,此方法仅适用于静态图片。如果您想要交互式旋转图片,则无法使用此方法。
还要注意,如果该方法对于您的完整数据文件不起作用,则可能是我搞乱了旋转矩阵或轴分配 :)
我附上了Python脚本、绘图文件和数据文件“plot_raw.dat”和“plot_sorted.dat”供参考。
from math import cos, sin, pi
from re import sub, match, findall
class Polygon:
def __init__(self):
self.firstLine = ""
self.points = []
self.lastLine = ""
def __str__(self):
pointStrings = [",".join(map(str,point)) for point in self.points]
s = ""
s += self.firstLine
s += " to \\\n".join(pointStrings)
s += "\n"
s += self.lastLine
return s
def readObjectFromFile(self, f, firstObjectLine):
self.firstLine = firstObjectLine
line = f.readline()
while not match("set",line):
coordinates = findall("[\d.]+", line)
coordinates = tuple(float(x) for x in coordinates)
self.points.append(coordinates)
line = f.readline()
self.lastLine = line
return self
def meanAfterRotation(self, theta, phi):
cx = 0.0
cy = 0.0
cz = 0.0
theta = theta*pi/180.0
phi = phi*pi/180.0
for point in self.points:
x,y,z = point
x,y,z = (x, y*cos(theta) - z*sin(theta), y*sin(theta) + z*cos(theta))
x,y,z = (x*cos(phi) - y*sin(phi), x*sin(phi) + y*cos(phi), z)
cx, cy, cz = (cx + x, cy + y, cz + z)
n = len(self.points)
return (cx/n, cy/n, cz/n)
def setPosition(self, posIndex):
self.firstLine = sub("(\d+)", str(posIndex), self.firstLine, 1)
self.lastLine = sub("(\d+)", str(posIndex), self.lastLine, 1)
polygons = []
with open("poly_raw.dat") as f:
line = f.readline()
while line:
if line.strip() != "":
polygons.append(Polygon().readObjectFromFile(f,line))
line = f.readline()
polygons.sort(key = lambda x: x.meanAfterRotation(60,30)[1], reverse = True)
pos = 1
for p in polygons:
p.setPosition(pos)
pos += 1
for p in polygons:
print(p)
gnuplot脚本:
set style line 1 linecolor rgbcolor "#777777" linewidth 1
set style increment user
set palette file "-"
0.00000 0.23137 0.22353 0.64314
0.17990 0.47843 0.34510 0.71765
0.32010 0.34902 0.17647 0.55686
0.43990 0.40784 0.10980 0.36471
0.59010 0.46275 0.09020 0.16863
0.78000 0.86667 0.41569 0.24314
0.92990 0.92549 0.66667 0.33725
1.00000 0.97647 0.91765 0.82745
e
set cbrange [50:150]
set cbtics 25
set format cb "%.0f W/m²"
unset xtics
unset ytics
unset ztics
unset border
set colorbox
kzoom=1.0
phi=30.0
theta=60.0
set xyplane 0
set view equal xyz
set view theta,phi,kzoom
load "poly_sorted.dat"
set terminal png
set output "sorted.png"
splot "-" with lines notitle ls 1, NaN notitle palette
2.0 0.0 0.0
2.0 2.0 0.0
4.0 2.0 0.0
4.0 0.0 0.0
2.0 0.0 0.0
0.0 0.0 0.0
0.0 2.0 0.0
2.0 2.0 0.0
2.0 0.0 0.0
0.0 0.0 0.0
e
移除 front
标识后的未排序多边形数据:
set object 1 polygon from \
2.0,0.0,3.0 to \
3.0,0.0,3.5 to \
3.0,2.0,3.5 to \
2.0,2.0,3.0 to \
2.0,0.0,3.0
set object 1 fill solid 0.9 border lw 2 fc palette cb 128.1315
set object 2 polygon from \
4.0,0.0,3.0 to \
4.0,2.0,3.0 to \
3.0,2.0,3.5 to \
3.0,0.0,3.5 to \
4.0,0.0,3.0
set object 2 fill solid 0.9 border lw 2 fc palette cb 128.62192
set object 3 polygon from \
2.0,0.0,0.0 to \
4.0,0.0,0.0 to \
4.0,0.0,3.0 to \
3.0,0.0,3.5 to \
2.0,0.0,3.0 to \
2.0,0.0,0.0
set object 3 fill solid 0.9 border lw 2 fc palette cb 100.545204
set object 4 polygon from \
4.0,0.0,0.0 to \
4.0,2.0,0.0 to \
4.0,2.0,3.0 to \
4.0,0.0,3.0 to \
4.0,0.0,0.0
set object 4 fill solid 0.9 border lw 2 fc palette cb 85.58082
set object 5 polygon from \
4.0,2.0,0.0 to \
2.0,2.0,0.0 to \
2.0,2.0,3.0 to \
3.0,2.0,3.5 to \
4.0,2.0,3.0 to \
4.0,2.0,0.0
set object 5 fill solid 0.9 border lw 2 fc palette cb 55.88219
set object 6 polygon from \
2.0,2.0,0.0 to \
2.0,0.0,0.0 to \
2.0,0.0,3.0 to \
2.0,2.0,0.0
set object 6 fill solid 0.9 border lw 2 fc palette cb 85.25754
set object 7 polygon from \
2.0,2.0,0.0 to \
2.0,0.0,3.0 to \
2.0,2.0,3.0 to \
2.0,2.0,0.0
set object 7 fill solid 0.9 border lw 2 fc palette cb 85.25754
set object 8 polygon from \
0.0,0.0,3.0 to \
1.0,0.0,3.5 to \
1.0,2.0,3.5 to \
0.0,2.0,3.0 to \
0.0,0.0,3.0
set object 8 fill solid 0.9 border lw 2 fc palette cb 128.1315
set object 9 polygon from \
2.0,0.0,3.0 to \
2.0,2.0,3.0 to \
1.0,2.0,3.5 to \
1.0,0.0,3.5 to \
2.0,0.0,3.0
set object 9 fill solid 0.9 border lw 2 fc palette cb 128.62192
set object 10 polygon from \
0.0,0.0,0.0 to \
2.0,0.0,0.0 to \
2.0,0.0,3.0 to \
1.0,0.0,3.5 to \
0.0,0.0,3.0 to \
0.0,0.0,0.0
set object 10 fill solid 0.9 border lw 2 fc palette cb 100.545204
set object 11 polygon from \
2.0,0.0,0.0 to \
2.0,2.0,0.0 to \
2.0,2.0,3.0 to \
2.0,0.0,3.0 to \
2.0,0.0,0.0
set object 11 fill solid 0.9 border lw 2 fc palette cb 85.58082
set object 12 polygon from \
2.0,2.0,0.0 to \
0.0,2.0,0.0 to \
0.0,2.0,3.0 to \
1.0,2.0,3.5 to \
2.0,2.0,3.0 to \
2.0,2.0,0.0
set object 12 fill solid 0.9 border lw 2 fc palette cb 55.88219
set object 13 polygon from \
0.0,2.0,0.0 to \
0.0,0.0,0.0 to \
0.0,0.0,3.0 to \
0.0,2.0,0.0
set object 13 fill solid 0.9 border lw 2 fc palette cb 85.25754
set object 14 polygon from \
0.0,2.0,0.0 to \
0.0,0.0,3.0 to \
0.0,2.0,3.0 to \
0.0,2.0,0.0
set object 14 fill solid 0.9 border lw 2 fc palette cb 85.25754
在运行
python poly.py > poly_sorted.dat
之后,数据将被排序。
set object 1 polygon from \
4.0,0.0,0.0 to \
4.0,2.0,0.0 to \
4.0,2.0,3.0 to \
4.0,0.0,3.0 to \
4.0,0.0,0.0
set object 1 fill solid 0.9 border lw 2 fc palette cb 85.58082
set object 2 polygon from \
4.0,2.0,0.0 to \
2.0,2.0,0.0 to \
2.0,2.0,3.0 to \
3.0,2.0,3.5 to \
4.0,2.0,3.0 to \
4.0,2.0,0.0
set object 2 fill solid 0.9 border lw 2 fc palette cb 55.88219
set object 3 polygon from \
2.0,2.0,0.0 to \
2.0,0.0,0.0 to \
2.0,0.0,3.0 to \
2.0,2.0,0.0
set object 3 fill solid 0.9 border lw 2 fc palette cb 85.25754
set object 4 polygon from \
2.0,2.0,0.0 to \
2.0,0.0,3.0 to \
2.0,2.0,3.0 to \
2.0,2.0,0.0
set object 4 fill solid 0.9 border lw 2 fc palette cb 85.25754
set object 5 polygon from \
2.0,0.0,0.0 to \
2.0,2.0,0.0 to \
2.0,2.0,3.0 to \
2.0,0.0,3.0 to \
2.0,0.0,0.0
set object 5 fill solid 0.9 border lw 2 fc palette cb 85.58082
set object 6 polygon from \
2.0,2.0,0.0 to \
0.0,2.0,0.0 to \
0.0,2.0,3.0 to \
1.0,2.0,3.5 to \
2.0,2.0,3.0 to \
2.0,2.0,0.0
set object 6 fill solid 0.9 border lw 2 fc palette cb 55.88219
set object 7 polygon from \
2.0,0.0,0.0 to \
4.0,0.0,0.0 to \
4.0,0.0,3.0 to \
3.0,0.0,3.5 to \
2.0,0.0,3.0 to \
2.0,0.0,0.0
set object 7 fill solid 0.9 border lw 2 fc palette cb 100.545204
set object 8 polygon from \
0.0,2.0,0.0 to \
0.0,0.0,0.0 to \
0.0,0.0,3.0 to \
0.0,2.0,0.0
set object 8 fill solid 0.9 border lw 2 fc palette cb 85.25754
set object 9 polygon from \
4.0,0.0,3.0 to \
4.0,2.0,3.0 to \
3.0,2.0,3.5 to \
3.0,0.0,3.5 to \
4.0,0.0,3.0
set object 9 fill solid 0.9 border lw 2 fc palette cb 128.62192
set object 10 polygon from \
0.0,2.0,0.0 to \
0.0,0.0,3.0 to \
0.0,2.0,3.0 to \
0.0,2.0,0.0
set object 10 fill solid 0.9 border lw 2 fc palette cb 85.25754
set object 11 polygon from \
0.0,0.0,0.0 to \
2.0,0.0,0.0 to \
2.0,0.0,3.0 to \
1.0,0.0,3.5 to \
0.0,0.0,3.0 to \
0.0,0.0,0.0
set object 11 fill solid 0.9 border lw 2 fc palette cb 100.545204
set object 12 polygon from \
2.0,0.0,3.0 to \
3.0,0.0,3.5 to \
3.0,2.0,3.5 to \
2.0,2.0,3.0 to \
2.0,0.0,3.0
set object 12 fill solid 0.9 border lw 2 fc palette cb 128.1315
set object 13 polygon from \
2.0,0.0,3.0 to \
2.0,2.0,3.0 to \
1.0,2.0,3.5 to \
1.0,0.0,3.5 to \
2.0,0.0,3.0
set object 13 fill solid 0.9 border lw 2 fc palette cb 128.62192
set object 14 polygon from \
0.0,0.0,3.0 to \
1.0,0.0,3.5 to \
1.0,2.0,3.5 to \
0.0,2.0,3.0 to \
0.0,0.0,3.0
set object 14 fill solid 0.9 border lw 2 fc palette cb 128.1315
gnuplot 5.4 的变化
似乎脚本在 gnuplot 5.4.1 版本和 4.6 版本之间产生了不同的输出:
以下是一些解决方法:
黑色的建筑似乎是由于set object ...
命令中的border lw 2
部分引起的。如果我移除所有的border lw 2
,颜色就会回来。
不幸的是,现在多边形的边框仍然是黑色的。可以通过不完全删除border lw 2
部分,而是将其替换为border lc palette cb 128.62192
来改变这种情况,其中128.62192
与fc palette cb 128.62192
部分中的数字相同。
现在,完整的set object ...
行如下:
set object 2 fill solid 0.9 border lc palette cb 128.62192 fc palette cb 128.62192
最后,在我的测试中,图形没有居中显示。我通过在splot
命令之前添加以下内容来解决此问题:
set origin -0.2, -0.3
set size 1.2, 1.2