gnuplotで複数の線種・点種を用いて等高線を描く

# 何をするのか
gnuplotの `contour` と `table` を利用して, 異なる値に対する等高線は異なる線種・点種で描く.
例えば, 下図は半径1の半球(の一部)を, z座標について等高線を描いたものを示している.
![contour_rev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278627/bd68c2d5-6717-a974-e69f-9698d7fde8ae.png)
この記事を読めば, このように **白黒で印刷したときにも何を示しているのか一目瞭然な等高線** を描けるようになる.

# なぜやるのか(=いつ使うのか)
等高線を白黒で表現するため. 例えば, 等高線を含む論文を白黒で印刷して提出しなければならない場合, 等高線をカラーで区別することは当然期待できないので, 白黒でも判別がつくようにしなくてはならない. そこで, 異なる値に対する等高線は異なる線種・点種にしてこれを達成することを考える.

## 普通にcontour使うのじゃだめなのか
標準(?)の `contour`を使うと何が起こるかを下図に示す.

- 点で描く場合: 判別がつかない.

```text:default_plot_with_points.gp
set xrange [0:1]
set yrange [0:1]

set isosamples 50,50

set view map
set contour
unset surface

set cntrparam levels increment 0,0.1,0.9

splot sqrt(1 - x**2 - y**2) title "Default contour" w p

```

- 結果

![contour.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278627/8bb7a509-cc9c-c084-bf1e-5f2dd54fd4b2.png)

- 線で描く場合: 途中から同じ線種が使われてしまう.

```text:default_plot_with_lines.gp
set xrange [0:1]
set yrange [0:1]

set isosamples 50,50

set view map
set contour
unset surface

set cntrparam levels increment 0,0.1,0.9

splot sqrt(1 - x**2 - y**2) title "Default contour" w l

```

- 結果

![contour2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278627/fb74a84f-eec8-aa61-c80c-93224a9e2f46.png)

いずれの場合も, `contour` をそのまま使うことには問題があると考えられる.

# どうやるのか
Ans: 一旦 `table` を経由して, `plot` で各index毎にプロットする.

- tableに書き出す

```text:table_output.gp
set xrange [0:1]
set yrange [0:1]

set isosamples 50,50

set view map
set contour
unset surface

set cntrparam levels increment 0,0.1,0.9
set table "contour.txt"
splot sqrt(1 - x**2 -y**2)
unset table
```

これで以下のような出力が得られる:

```text:contour.txt

#Surface 0 of 1 surfaces

#Curve title: "sqrt(1 - x**2 - y**2)"


#Contour 0, label:,,,0.9
0.435871,0,0.9 
...
0,0.435755,0.9 


#Contour 1, label:,,,0.8
0.599968,0,0.8 
...
0,0.59987,0.8 


#Contour 2, label:,,,0.7
0.0707071,0.710546,0.7 
0.0606061,0.711498,0.7 
...

...


#Contour 8, label:,,,0.1
...
```

(筆者の環境は `set datafile separator ','` を設定しているので出力ファイルもcsv形式になるように整形している.)

- `plot` する

```text:plot_from_table.gp
plot for [i=1:9] "contour.txt" u 1:2 index i-1 pt i title columnheader(5)
```

これで最初のような等高線が得られる.

# 参考文献
[テーブルデータの出力](http://takeno.iee.niit.ac.jp/~foo/gp-jman/data/20170823/gnuplot-ja-div/node333.html)
[データファイルの数値のプロット](http://heim.ifi.uio.no/inf3330/scripting/doc/gnuplot/Kawano/datafile2.html)
[labeling 2d contour plot from table in gnuplot
](https://stackoverflow.com/questions/57061753/labeling-2d-contour-plot-from-table-in-gnuplot)

```text:help_contour
`set contour` enables contour drawing for surfaces.  This option is available
 for `splot` only.  It requires grid data, see `grid_data` for more details.
 If contours are desired from non-grid data, `set dgrid3d` can be used to
 create an appropriate grid.

 Syntax:
       set contour {base | surface | both}
       unset contour
       show contour

 The three options specify where to draw the contours: `base` draws the
 contours on the grid base where the x/ytics are placed, `surface` draws the
 contours on the surfaces themselves, and `both` draws the contours on both
 the base and the surface.  If no option is provided, the default is `base`.

 See also `set cntrparam` for the parameters that affect the drawing of
 contours, and `set cntrlabel` for control of labeling of the contours.

 The surface can be switched off (see `unset surface`), giving a contour-only
 graph.  Though it is possible to use `set size` to enlarge the plot to fill
 the screen, more control over the output format can be obtained by writing
 the contour information to a datablock, and rereading it as a 2D datafile plot:

       unset surface
       set contour
       set cntrparam ...
       set table $datablock
       splot ...
       unset table
       # contour info now in $datablock
       set term <whatever>
       plot $datablock

 In order to draw contours, the data should be organized as "grid data".  In
 such a file all the points for a single y-isoline are listed, then all the
 points for the next y-isoline, and so on.  A single blank line (a line
 containing no characters other than blank spaces and a carriage return and/or
 a line feed) separates one y-isoline from the next.
 See also `splot datafile`.

 See also
 contours demo (contours.dem)
 and
 contours with user defined levels demo (discrete.dem).
```