如何使用GNUPLOT表示3D函数的散点

时间:2019-05-05 19:59:25

标签: gnuplot scatter3d

我想在3D中用散点表示函数f(X,Y,Z)=(X²(Y + Z)+Y²(X-Z)+Z²(-X-Y)-21)的结果。欢迎提供有关如何在GNUPLOT中执行此操作的任何建议(每个方向在-100到+100之间)。

我试图在X Y和Z整数处看到“ 0”的位置。 点的大小就是该函数返回的值。

3 个答案:

答案 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使其变小)

enter image description here

答案 1 :(得分:0)

答案2:除非密度函数在大多数地方为零,否则它将填充固体体积。为了使该体积可视化,您将需要选择特定的点或进行切片或其他操作。合理的选择取决于您的功能结构。 Gnuplot现在提供了几种方法。请参阅以下示例,该示例使用从当前演示集voxel.dem中获取的2D切片。这种方法对平滑密度函数有意义,但对于那些有趣的位是离散点而不是空间区域的函数,可能没有意义。

enter image description here

答案 2 :(得分:0)

enter image description here谢谢。我稍后会跟进。 我刚刚写了一个脚本,可以填充离散表示 到目前为止,我对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()