2018年3月17日 星期六

繪製等位線的方法:Gnuplot

作者:王一哲
日期:2018/3/17




前言


這是之前測試成功,用 Gnuplot 畫出等位線的方法,雖然可以做出我想要的效果,但是我不太確定其中部分指令的功能,還需要再多測試一下。 目前試過兩種作法:

  1. 用 Gnuplot 指令計算每個位置的電位並畫圖
  2. 用 C 語言寫一支小程式計算每個位置的電位,將資料存成文字檔,再用 Gnuplot 讀取文字檔的資料畫圖




方法1成果




方法2成果



使用版本為 Gnuplot 5.2 patchlevel 2,下載頁面為 https://sourceforge.net/projects/gnuplot/files/gnuplot/5.2.2/






方法1:用 Gnuplot 指令


reset    # 清除所有設定

# 設定輸出格式, wxt: 顯示於視窗, png: 存成 png 圖檔
#set terminal wxt
set terminal png size 600,450
set output "electric_potential.png"

# 設定靜電力常數, 點電荷電量及位置
k = 8.988E9
x1 = -0.1
y1 = 0
q1 = 1E-8
x2 = 0.1
y2 = 0
q2 = -1E-8

# 設定計算距離r, 電位V的函式
r(x,y) = sqrt(x*x+y*y)
V1(x,y)= k*q1/r(x-x1,y-y1)
V2(x,y)= k*q2/r(x-x2,y-y2)
V(x,y) = V1(x,y)+V2(x,y)

# 設定x, y軸繪圖範圍
set xrange [-0.2:0.2]
set yrange [-0.1:0.1]

# 設定x,y取點數
set isosamples 80,80

# 設定座標軸標籤, 為了使z軸標籤不會和數字重疊, 加上 offset 移動位置
set xlabel "x(m)"
set ylabel "y(m)"
set zlabel "V(volt)" offset -2

set grid    # 設定底部的格線
set pm3d    # 著色
set hidden3d    # 隱藏3d曲線上的線條
# 設定數值對應的顏色, rainbow (blue-green-yellow-red)
set palette rgb 33,13,10
#set view map    # 由正上方向下看
#set contour base    # 於底部畫出等高線
#set cntrparam levels 20    # 等高線數量為20
splot V(x,y)



將以上的文字複製、貼上到文字編輯器中,存成 electric_potential_data_plot.plt,開啟 Gnuplot,切換到存於這個檔案的資料夾,輸入並執行

load 'electric_potential_data_plot.plt'

這個方法的好處在於只要用到 Gnuplot,不需要用到其它的軟體。




方法2:用 Gnuplot 讀取資料檔


reset    # 清除所有設定

# 設定輸出格式, wxt: 顯示於視窗, png: 存成 png 圖檔
#set terminal wxt
set terminal png size 600,450
set output "electric_potential_data_plot.png"

# 設定座標軸標籤, 為了使z軸標籤不會和數字重疊, 加上 offset 移動位置
set xlabel "x(m)"
set ylabel "y(m)"
set zlabel "V(volt)" offset -2

set grid    # 設定底部的格線
set pm3d    # 著色
set hidden3d    # 隱藏3d曲線上的線條
set dgrid3d 100,100 qnorm 3    # 將讀取的資料切為100*100格並使數值平滑
# 設定數值對應的顏色, rainbow (blue-green-yellow-red)
set palette rgb 33,13,10
#set view map    # 由正上方向下看
#set contour base    # 於底部畫出等高線
#set cntrparam levels 20    # 等高線數量為20
# 讀取資料檔, 使用1, 2, 3欄資料作為x, y, z數值, 將數值連線
splot "electric_potential_data.txt" using 1:2:3 with lines



這是用來產生資料的程式

/* 產生繪製等電位線用的數值資料 
   作者: 王一哲 Yi-Zhe Wang
   日期: 2018/3/13                       */

#include <stdio.h>
#include <math.h>
#include <stdlib.h> 

// 定義計算電位的運算式 
double potential(double x, double y, double q1, double x1, double y1, double q2, double x2, double y2) {
    double k = 8.988*pow(10, 9);
    return k*(q1/sqrt(pow((x-x1), 2) + pow((y-y1), 2)) + q2/sqrt(pow((x-x2), 2) + pow((y-y2), 2)));
}
 
int main(void){
//定義繪圖範圍及分割數量 
    double xmin, xmax, dx, ymin, ymax, dy, num;
    xmin = -2.0;
    xmax = +2.0;
    ymin = -2.0;
    ymax = +2.0;
    num = 100.0;
    dx = (xmax - xmin) / num;
    dy = (ymax - ymin) / num;

//定義點電荷電量及位置 
    double q1, x1, y1, q2, x2, y2;
    q1 = +2.0*pow(10, -8);
    x1 = -1.0;
    y1 = 0.0;
    q2 = -1.0*pow(10, -8);
    x2 = +1.0;
    y2 = 0.0;

//建立計算結果的輸出檔案, 寫入欄位標題 
    FILE *fPtr;
    fPtr = fopen("electric_potential_data.txt", "w");
    if (!fPtr){
        printf("檔案建立失敗\n");
        exit(1);
    } else {
        fprintf(fPtr, "x(m) \t y(m) \t V(volt) \n");
    }

//自動改變(x, y)計算電位並寫入輸出檔
    int i, j;
    double x, y, result; 

    for(i = 0; i <= (int)num; i++) {
        for(j = 0; j <= (int)num; j++) {
            x = xmin + dx*(double)i;
            y = ymin + dy*(double)j;
            if((x!=x1 && y!=y1) || (x!=x2 && y!=y2)) {
                result = potential(x, y, q1, x1, y1, q2, x2, y2);
                fprintf(fPtr, "%f \t %f \t %f \n", x, y, result);
            }
        }
    }

    fclose(fPtr);
    return 0;
}



資料檔名稱為 electric_potential_data.txt,格式如下

x(m)            y(m)            V(volt)
-2.000000       -2.000000       55.462889
-2.000000       -1.960000       56.614089
-2.000000       -1.920000       57.802880
-2.000000       -1.880000       59.030634
-2.000000       -1.840000       60.298756
-2.000000       -1.800000       61.608685
-2.000000       -1.760000       62.961885 



如果學會這個方法,以後就可以用指令將大量的數據丟進 Gnuplot 畫圖,也是有好處的。



結語


實在是太久沒用 Gnuplot,指令都快忘光了,正好複習一下。以後如果需要畫類似的圖,就可以拿這個檔案去修改,速度會快很多。



HackMD 版本連結:https://hackmd.io/@yizhewang/H1Ohp0i3L

沒有留言:

張貼留言