我想在3D中用散点表示函数f(X,Y,Z)=(X²(Y + Z)+Y²(X-Z)+Z²(-X-Y)-21)的结果。欢迎提供有关如何在GNUPLOT中执行此操作的任何建议(每个方向在-100到+100之间)。
我试图在X Y和Z整数处看到“ 0”的位置。 点的大小就是该函数返回的值。
答案 0 :(得分:0)
3个维度的整数值[-100:100]为800万点。如果要为其中的任何一个绘制任何内容,则结果显示将填充到每个像素上,因此无法用作可视化工具。在每个点按大小或颜色进行编码将无济于事。现在,您有兴趣查找的点数可能构成了一个很小的子集,可以将其可视化为gnuplot中的3D散点图,但是您将不得不选择这些点,而不是绘制所有内容。
简单的方法是在x,y,z上循环以计算函数,然后如果值是您想要的(f(x,y,z)== 0?),则写出[x,y ,z]组合成一个文件。 如果找到的点数合理,则可以使用以下命令在gnuplot中可视化。我以[-1:1]之间的随机点为例。
unset border
set xzeroaxis; set yzeroaxis; set zzeroaxis
set tics nomirror axis
set xyplane at 0
splot "zeros" using 1:2:3 with points pt 7 ps 0.4
(pointtype 7是一个实心圆,pointsize 0.4使其变小)
答案 1 :(得分:0)
答案2:除非密度函数在大多数地方为零,否则它将填充固体体积。为了使该体积可视化,您将需要选择特定的点或进行切片或其他操作。合理的选择取决于您的功能结构。 Gnuplot现在提供了几种方法。请参阅以下示例,该示例使用从当前演示集voxel.dem中获取的2D切片。这种方法对平滑密度函数有意义,但对于那些有趣的位是离散点而不是空间区域的函数,可能没有意义。
答案 2 :(得分:0)
谢谢。我稍后会跟进。 我刚刚写了一个脚本,可以填充离散表示 到目前为止,我对matplotlib的了解还不够(我对gnuplot并不熟悉)。 同样:在(X,Y,Z)处表示一个函数“ F(X,Y,Z)-A =结果”,所有函数都为3D整数。结果= 0?点染成黑色。其他颜色。
import matplotlib as mpl
from mpl_toolkits.mplot3d.proj3d import proj_transform
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np
mpl.use('tkagg')
def distance(point, event):
plt.sca(ax) # <------------------ introduce this one !!!!!!!!!!!!!!!!!!!!!!!!!!!
x2, y2, _ = proj_transform(point[0], point[1], point[2], plt.gca().get_proj())
x3, y3 = ax.transData.transform((x2, y2))
return np.sqrt ((x3 - event.x)**2 + (y3 - event.y)**2)
def calcClosestDatapoint(X, event):
distances = [distance(X[i, 0:3], event) for i in range(Sol)]
return np.argmin(distances)
#
def annotatePlot(X, index):
global last_mark, generated_labels
if activated_labelling:
x2, y2, _ = proj_transform(X[index, 0], X[index, 1], X[index, 2], ax.get_proj())
last_mark = plt.annotate(generated_labels[index],
xy = (x2, y2), xytext = (-20, 20), textcoords = 'offset points', ha = 'right', va = 'bottom',
bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))
fig.canvas.draw()
#
def onMouseMotion(event):
global Coord
if activated_labelling:
closestIndex = calcClosestDatapoint(Coord, event)
last_mark.remove()
annotatePlot(Coord, closestIndex)
def show_on(event):
global activated_labelling, last_mark,pid,mid
if activated_labelling == False:
activated_labelling = True
x2, y2, _ = proj_transform(Coord[0,0], Coord[0,1], Coord[0,2], ax.get_proj())
last_mark = plt.annotate("3D measurement on " + generated_labels[0],
xy = (x2, y2), xytext = (-20, 20), textcoords = 'offset points', ha = 'right', va = 'bottom',
bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))
mid = fig.canvas.mpl_connect('motion_notify_event', onMouseMotion)
#
def show_off(event):
global activated_labelling
'''
deactivate the persistent XYZ position labels at the grafic
'''
if activated_labelling:
activated_labelling = False
last_mark.remove()
fig.canvas.draw()
fig.canvas.mpl_disconnect(mid)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
#ax = fig.gca(projection='3d')
activated_labelling = False
Wide = 100
Minimum = -50
ScanLimit = 3 # searching between o and 3; 4 and 5 are no solutions
Search = 45
Coord=[]
values=[]
generated_labels = []
#
XMin = 0
XMax = 0
YMin = 0
YMax = 0
ZMin = 0
ZMax = 0
# count the solutions found in the scan area defined above
Sol=0
for i in range(Wide+1):
for j in range(Wide+1):
for k in range(Wide+1):
########################################################################
########################################################################
####
#### THIS IS THE POLYNOM TO BE REPRESENTED
####
param_dens = ((i+Minimum)**3)+((j+Minimum)**3)+((k+Minimum)**3) -Search
if abs(param_dens) <= abs(ScanLimit):
Coord.append([i+Minimum,j+Minimum,k+Minimum])
if ScanLimit !=0:
values.append([abs(param_dens)])
labelling = "value {}\nin X:{} Y:{} Z:{}".format(Search+param_dens,i+Minimum,j+Minimum,k+Minimum)
generated_labels.append(labelling)
print(labelling+"\n")
# increase the number indicating the solutions found
Sol +=1
# for centering the window
if XMin > i+Minimum:
XMin = i+Minimum
if YMin > j+Minimum:
YMin = j+Minimum
if ZMin > k+Minimum:
ZMin = k+Minimum
if XMax < i+Minimum:
XMax = i+Minimum
if YMax < j+Minimum:
YMax = j+Minimum
if ZMax < k+Minimum:
ZMax = k+Minimum
print('######################################################')
print('## statistics / move this to a parallel search engine?')
print('## search ')
print("## total solution %d for searching center %d" % (Sol,Search))
print("## from %d to %d" % (Search-ScanLimit,Search+ScanLimit))
print("## from %d to %d" % (Minimum,Wide+Minimum))
print('##')
print('#######################################################')
#
values = np.array(values, dtype='int64')
Coord = np.array(Coord, dtype='int64')
#
if ScanLimit !=0:
cmap = plt.cm.jet # define the colormap
# extract all colors from the .jet map
cmaplist = [cmap(i) for i in range(cmap.N)]
# force the first color entry to be black
cmaplist[0] = (0, 0, 0, 1.0)
# create the new map
cmap = mpl.colors.LinearSegmentedColormap.from_list('Custom cmap', cmaplist, cmap.N)
# define the bins and normalize
bounds = np.linspace(0, ScanLimit, ScanLimit+1)
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
# create a second axes for the colorbar
ax2 = fig.add_axes([0.95, 0.1, 0.03, 0.8])
cb = mpl.colorbar.ColorbarBase(ax2, cmap=cmap, norm=norm,
spacing='proportional', ticks=bounds, boundaries=bounds, format='%1i')
#
ax.set_xlim3d(XMin-5, XMax+5)
ax.set_ylim3d(YMin-5, YMax+5)
ax.set_zlim3d(ZMin-5, ZMax+5)
#
ax.set_xlabel('X X')
ax.set_ylabel('Y Y')
ax.set_zlabel('Z Z')
ax.set_aspect(aspect=1)
# extract the scatterplot drawing in a separate function so we ca re-use the code
def draw_scatterplot():
if ScanLimit !=0:
ax.scatter3D(Coord[:,0], Coord[:,1], Coord[:,2], s=20, c=values[:,0], cmap=cmap, norm=norm)
else:
ax.scatter3D(Coord[:,0], Coord[:,1], Coord[:,2], s=20, c='green')
# draw the initial scatterplot
draw_scatterplot()
# create the "on" button, and place it somewhere on the screen
ax_on = plt.axes([0.0, 0.0, 0.1, 0.05])
button_on = Button(ax_on, 'on')
#
ax_off = plt.axes([0.12, 0.0, 0.1, 0.05])
button_off = Button(ax_off, 'off')
#
#ax_off = plt.axes([0.24, 0.0, 0.1, 0.05])
#button_off = Button(ax_off, 'off')
# link the event handler function to the click event on the button
button_on.on_clicked(show_on)
button_off.on_clicked(show_off)
#fig.colorbar(img)
plt.show()