3次元構造格子のサーフェイスメッシュ及びコンターのplotlyによる可視化

# 背景
3次元構造格子(i, j, k)の各格子点でのx, y, zの座標及び関数fの値が分かっているとき, k = 一定断面のメッシュとfの値を可視化したいと思いました。Three.jsを使う方法とplotly.jsを使う方法を検討したところ、plotlyを使う方法が簡単でしたので、ご紹介します。

[![Imgur](https://i.imgur.com/Z4nf7zg.png)](https://qiita.com/Toyoharu-Nishikawa/items/044d53974c42bc635f0f)


plotly.jsのダウンロードはこちらからどうぞ
https://plot.ly/javascript/getting-started/

# 問題
問題を設定すると次のようになります。

曲面上のi番目, j番目の要素のx, y, z座標及びその座標での値fが分かっていいるとき、それらのメッシュと値のコンターを表示する。

```math
x = x(i, j), y = y(i, j), z = z(i, j) \\
f = f(i, j) \\
(i = 0,1,2, ... , imax) \\
(j = 0,1,2, ... , jmax) \\
```
 
# 方法
```javascript

//(1)データを用意
const imax = 10
const jmax = 10

const listX = [...Array(jmax)].map(k=>[...Array(imax)].map((k,index)=>index))
const listY = [...Array(jmax)].map((k,index)=>[...Array(imax)].map(k=>index))
const listZ = [...Array(jmax)].map((k,index1)=>[...Array(imax)].map((k,index2)=>(index1+index2)/2))
const listF = [...Array(jmax)].map((k,index1)=>[...Array(imax)].map((k,index2)=>index1+index2))

//(2)メッシュ用描画のための配列x,y,zを作成
const x=[]
const y=[]
const z=[]

for(let j=0;j<jmax;j++){
  for(let i=0;i<imax;i++){
    x.push(listX[j][i]) 
    y.push(listY[j][i]) 
    z.push(listZ[j][i]) 
  }
  x.push(null)
  y.push(null)
  z.push(null)
}
for(let i=0;i<imax;i++){
  for(let j=0;j<jmax;j++){
    x.push(listX[j][i]) 
    y.push(listY[j][i]) 
    z.push(listZ[j][i]) 
  }
  x.push(null)
  y.push(null)
  z.push(null)
}

//(3)メッシュ描画設定
const trace1 = {
  x: x,
  y: y,
  z: z,
  line: {
    color: 'black', 
    width: 1,
  }, 
  mode: 'lines', 
  type: 'scatter3d'
};

//(4)サーフェイスコンター描画設定
const trace2 = {
  x: listX,
  y: listY,
  z: listZ,
  surfacecolor: listF,
  colorbar:{
    title:"temp",
  },
  //cmin:0,
  //cmax:5,
  colorscale:"Jet",
  type: 'surface',

};

//(5)2つの設定をまとめてdataに入れる.
const data = [trace1,trace2];

//(6)レイアウトの設定
const layout = {
  height: 500, 
  width: 500,
  scene: {
    /*aspectratio: {
      x: 1, 
      y: 1, 
      z: 1,
    },*/ 
    xaxis: {
      backgroundcolor: 'rgb(230, 230,230)', 
      gridcolor: 'rgb(255, 255, 255)', 
      showbackground: true, 
      zerolinecolor: 'rgb(255, 255, 255)'
    }, 
    yaxis: {
      backgroundcolor: 'rgb(230, 230,230)', 
      gridcolor: 'rgb(255, 255, 255)', 
      showbackground: true, 
      zerolinecolor: 'rgb(255, 255, 255)'
    }, 
    zaxis: {
      backgroundcolor: 'rgb(230, 230,230)', 
      gridcolor: 'rgb(255, 255, 255)', 
      showbackground: true, 
      zerolinecolor: 'rgb(255, 255, 255)'
    }
  }, 
 title: '3D colored surface', 
};

//(7)plotlyで描画
Plotly.plot('draw',data,layout,{
    editable: true,
    scrollZoom: true,
    showLink: false,
    displaylogo: false,
    modeBarButtonsToRemove: ['sendDataToCloud']
});
```

(1) データを用意
構造格子(i, j)に対応するx, y, zの座標データと関数値fを用意します。
ただし、格子点(i, j)のx座標はx[j][i]で参照します。

(2) メッシュ用描画のための配列x,y,zを作成
メッシュをラインで表示するための配列を作ります。
plotlyのscatter3Dはnullが現れるまでpolyline(多直線)を描いてくれるので, nullを途中に入れながら、座標を一次元配列に変換します。まず、横のラインを入れた後に縦のラインを入れます。

(3) メッシュ描画設定
メッシュを描くための設定を書きます。x, y, zには(2)の1次元配列を入れると多直線をたくさん書いてメッシュにしてくれます。modeはlinesにして、typeはscatter3Dにします。

(4) サーフェイスコンター描画設定
サーフェイスコンターを描くための設定を書きます。 x, y, zには(1)で用意したデータをそのまま入れればよいです。関数値はsurfacecolorに入れることで、関数値fのコンターを描くことができます。colorscale:"Jet"にすると値の高低が直感とあう自然な色具合になります。

(5) 2つの設定をまとめてdataに入れる
(3)と(4)をdataに入れます。

(6)レイアウトの設定
グラフ領域の幅や高さ、背景の色やグリッドの色を指定します。

(7) plotlyで描画
plotlyで描画します。Plot.plotの最初の引数は描画する領域のDOM要素のidもしくは、要素のオブジェクトを入れます。

# サンプル
![Imgur](https://i.imgur.com/OW22nA5.png)

![Imgur](https://i.imgur.com/D25UdJs.png)

![Imgur](https://i.imgur.com/q8nolMS.png)

![Imgur](https://i.imgur.com/TUvh4fL.png)


これらのサンプルは上記コードを[jsnote](https://toyoharu-nishikawa.github.io/jsnote/)に張り付けて、listZの値を書き換えて作りました。
[![Imgur](https://i.imgur.com/HstpPha.png)](https://toyoharu-nishikawa.github.io/jsnote/#drawCheckBox=1)