今回は入力されたデータを元にして棒グラフと折れ線グラフを表示します。このようなグラフ描画機能は電卓に用意されているものの方が手軽で高機能・高性能です。ですので、実務・授業等において標準機能で十分かもしれません。
 とはいえ標準では用意されていないグラフや、思い通りのグラフを表示したい場合にはPythonで作成した方がよい場合もあります。ここらへんは用途に応じて使い分けてください。

 なお、ここではすでに作成してある線を描画するライブラリを利用します。glib.pyという名前で実行するpyファイルと同じフォルダ/階層においてください。glib.pyの内容は以下のようになっています。

from casioplot import *
def gLine(x1,y1,x2,y2,col):
  x=x1
  y=y1
  sx=1
  sy=1
  dx=x2-x1
  dy=y2-y1
  if dx<0:
    sx=-1
  if dy<0:
    sy=-1
  if dx==0:
    for i in range(abs(dy)):
      set_pixel(int(x),int(y),col)
      y=y+sy
    return
  if dy==0:
    for i in range(abs(dx)):
      set_pixel(int(x),int(y),col)
      x=x+sx
    return
  if abs(dx)>abs(dy):
    d=dy/abs(dx)
    for i in range(abs(dx)):
      set_pixel(int(x),int(y),col)
      x=x+sx
      y=y+d
  else:
    d=dx/abs(dy)
    for i in range(abs(dy)):
      set_pixel(int(x),int(y),col)
      x=x+d
      y=y+sy

棒グラフを描画する

 まずは棒グラフからです。と、その前にユーザーから入力したデータを配列に入れるプログラムを作成します。複雑(?)なプログラムはいきなり作成するのではなく、簡単に動く部分から作っていくとよいでしょう。
 Pythonでの配列は[]を使って初期化します。data=[]とするとdataの配列が初期化されます。
 また、配列に何か追加する場合はappend()を使います。パラメーターに追加したいデータを指定します。
 input()で入力した数値を配列に追加していくプログラムは以下のようになります。なお、何も入力しない場合は、そこで終了とみなします。最後に入力した配列内容を表示します。

data=[]
while True:
  n=input('data=')
  if n=='':
    break 
  data.append(int(n))
print(data)

 これまでと同様にパソコン側でファイルを作成しておき、電卓に転送します。ファイル名はA1.pyとしてあります。実行すると図のようになります。

 次に棒グラフを表示します。まずは、シンプルに配列に入力された値を線で表示します。線を表示するだけなので簡単です。ただし、数学座標系とコンピューターの座標系はY軸方向が逆になっているので、その点には注意してプログラムを作成する必要があります。
 実際のプログラムは以下のようになります。

from glib import *

data=[]
while True:
  n=input('data=')
  if n=='':
    break 
  data.append(int(n))

clear_screen()
for i in range(len(data)):
  x=i*40
  y=int(data[i])
  gLine(x,191,x,191-y,(255,0,0))
show_screen()

 これまでと同様にパソコン側でファイルを作成しておき、電卓に転送します。ファイル名はA2.pyとしてあります。実行すると図のようになります。

より見やすい棒グラフにする

 縦棒1ピクセルの棒グラフは見やすいとはいえません。また、見た目もイマイチです。そこで今度は一般的な棒グラフを表示してみます。とはいえ、fx-CG50のグラフィック描画速度はパソコンと比べると速くはありません。たくさんの棒グラフを描かせると表示までに時間がかかってしまいます。そこで、まず線だけで描かれた四角形を使って表示することにします。
 まず線だけの四角形を描かせるための関数を用意します。ここではrectという名前の関数を定義しています。XY座標と横幅、縦幅と色を指定すると線だけの四角形を描きます。

def rect(x,y,w,h,col):
  gLine(x,y,x+w,y, col)
  gLine(x+w,y,x+w,y+h, col)
  gLine(x,y,x,y+h, col)
  gLine(x,y+h,x+w,y+h, col)

この関数が問題なく動けば、できたも同然です。先ほどの1ピクセルしか表示しない部分をrect関数を呼び出すように変更します。
 実際のプログラムは以下のようになります。

from glib import *

def rect(x,y,w,h,col):
  gLine(x,y,x+w,y, col)
  gLine(x+w,y,x+w,y+h, col)
  gLine(x,y,x,y+h, col)
  gLine(x,y+h,x+w,y+h, col)

data=[]
while True:
  n=input('data=')
  if n=='':
    break 
  data.append(int(n))

clear_screen()
for i in range(len(data)):
  x=i*40
  y=int(data[i])
  rect(x,191-y,30,y,(255,0,0))
show_screen()

 これまでと同様にパソコン側でファイルを作成しておき、電卓に転送します。ファイル名はA3.pyとしてあります。実行すると図のようになります。

 次にグリッドを表示してみます。グリッド=目盛りがないとわかりにくいでしょう。今回はグリッドには数値などを表示しませんが、sraw_string()を使えば数値や文字を表示できます。
 グリッドを表示するためにgird関数を定義します。縦横に直線を指定された等間隔で表示するだけです。

def grid(step,col):
  gLine(0,191,384,191,col)
  for x in range(0,384,step):
    gLine(x,0,x,191,col)
  for y in range(0,192,step):
    gLine(0,192-y,383,192-y,col)

 実線ではなく点線にしたい場合はset_pixel()で点を描画した方がよいでしょう。
 実際のプログラムは以下のようになります。

from glib import *

def rect(x,y,w,h,col):
  gLine(x,y,x+w,y, col)
  gLine(x+w,y,x+w,y+h, col)
  gLine(x,y,x,y+h, col)
  gLine(x,y+h,x+w,y+h, col)

def grid(step,col):
  gLine(0,191,384,191,col)
  for x in range(0,384,step):
    gLine(x,0,x,191,col)
  for y in range(0,192,step):
    gLine(0,192-y,383,192-y,col)

data=[]
while True:
  n=input('data=')
  if n=='':
    break 
  data.append(int(n))

clear_screen()
grid(50,(0,0,0))
for i in range(len(data)):
  x=i*40
  y=int(data[i])
  rect(x,191-y,30,y,(255,0,0))
show_screen()

 これまでと同様にパソコン側でファイルを作成しておき、電卓に転送します。ファイル名はA4.pyとしてあります。実行すると図のようになります。

アニメーションさせながら棒グラフを表示

 単純に棒グラフを表示するだけでは電卓に入っているグラフ機能と変わりません。そこで、今度は棒グラフをアニメーションさせながら表示してみます。
 実際のところアニメーションさせながら棒グラフを表示するにはrect関数を以下のように変更します。棒グラフを下から上まで線を表示していくだけです。

def rect(x,y,w,h,col):
  for i in range(h):
    gLine(x,y+h-i,x+w,y+h-i, col)
    show_screen()

 実際のプログラムは以下のようになります。より棒グラフっぽくなり見やすくなりました。

from glib import *

def rect(x,y,w,h,col):
  for i in range(h):
    gLine(x,y+h-i,x+w,y+h-i, col)
    show_screen()

def grid(step,col):
  gLine(0,191,384,191,col)
  for x in range(0,384,step):
    gLine(x,0,x,191,col)
  for y in range(0,192,step):
    gLine(0,192-y,383,192-y,col)

data=[]
while True:
  n=input('data=')
  if n=='':
    break 
  data.append(int(n))

clear_screen()
grid(50,(0,0,0))
for i in range(len(data)):
  x=i*40
  y=int(data[i])
  rect(x,191-y,30,y,(255,0,0))
show_screen()

 これまでと同様にパソコン側でファイルを作成しておき、電卓に転送します。ファイル名はA5.pyとしてあります。実行すると図のようになります。

折れ線グラフ

 次に折れ線グラフを表示してみます。これは単純に配列内にあるグラフデータから求められる座標を線で結ぶ(描画する)だけです。折れ線グラフを表示するにはいくつかの方法がありますが、ここでは古い座標点と新しい座標点をパラメーターとして指定しています。
 実際のプログラムは以下のようになります。

from glib import *

def grid(step,col):
  gLine(0,191,384,191,col)
  for x in range(0,384,step):
    gLine(x,0,x,191,col)
  for y in range(0,192,step):
    gLine(0,192-y,383,192-y,col)

data=[]
while True:
  n=input('data=')
  if n=='':
    break 
  data.append(int(n))

clear_screen()
grid(50,(0,0,0))
xx=0
yy=int(data[0])
for i in range(len(data)):
  x=i*40
  y=int(data[i])
  gLine(xx,yy,x,y,(255,0,0))
  xx=x
  yy=y
show_screen()

 これまでと同様にパソコン側でファイルを作成しておき、電卓に転送します。ファイル名はA6.pyとしてあります。実行すると図のようになります。

曲線を表示

 ここまでは直線で表示しましたが、場合によっては曲線を使いたい場合もあります。曲線にはスプライン曲線やベジェ曲線など様々な種類があります。ここでは簡単な3次ベジェ曲線のプログラムを作成してみます。ベジェ曲線についてはWikiなどに詳しく書かれています。

https://ja.wikipedia.org/wiki/ベジェ曲線

 コンピューター上で曲線を描く場合、1ピクセルごと正しく計算して処理する方がよい場合と近似曲線で十分な場合があります。ここでは正確に点を表示するのではなく近似させる方法を使います。ベジェ曲線の場合、4つの点を半分に分割するのを繰り返すだけです。分割数が細かいほど滑らかな曲線になります。
 以下のプログラムで、この分割数を決めるのはt=tt*0.05の部分です。この数値を変えることで分割数が変わります。fx-CG50では処理速度が速くないため、この分割数を調整した方がよいかもしれません。
 実際のプログラムは以下のようになります。

from glib import *

def bezier(x1,y1,x2,y2,x3,y3,x4,y4,col):
  sx=x1
  sy=y1
  for tt in range(0,20):
    t=tt*0.05
    b1=(1-t)*(1-t)*(1-t)
    b2=3*t*((1-t)*(1-t))
    b3=3*(t*t)*(1-t)
    b4=t*t*t
    x=b1*x1+b2*x2+b3*x3+b4*x4
    y=b1*y1+b2*y2+b3*y3+b4*y4
    gLine(sx,sy,x,y,col)
    sx=x
    sy=y

clear_screen()
bezier(0,0, 45,80, 190,192, 384,53,(255,0,0))
show_screen()

 これまでと同様にパソコン側でファイルを作成しておき、電卓に転送します。ファイル名はB1.pyとしてあります。実行すると赤い3次ベジェ曲線が描かれます。

 最後にベジェ曲線を利用したスクリーンセーバーのプログラムを載せておきます。前回の線のスクリーンセーバーと作りは同じです。制御する座標点が2つから4つになっているので、その分プログラムが長くなっています。

from random import *
from glib import *

def bezier(x1,y1,x2,y2,x3,y3,x4,y4,col):
  sx=x1
  sy=y1
  for tt in range(0,20):
    t=tt*0.05
    b1=(1-t)*(1-t)*(1-t)
    b2=3*t*((1-t)*(1-t))
    b3=3*(t*t)*(1-t)
    b4=t*t*t
    x=b1*x1+b2*x2+b3*x3+b4*x4
    y=b1*y1+b2*y2+b3*y3+b4*y4
    gLine(sx,sy,x,y,col)
    sx=x
    sy=y

x1=0
y1=0
x2=40
y2=80
x3=170
y3=190
x4=380
y4=50
dx1=1
dy1=1
dx2=-1
dy2=-1
dx3=1
dy3=-1
dx4=-1
dy4=1

while True:
  x1=x1+dx1
  y1=y1+dy1
  x2=x2+dx2
  y2=y2+dy2
  x3=x3+dx3
  y3=y3+dy3
  x4=x4+dx4
  y4=y4+dy4
  if x1<0 or x1>383:
    dx1=-dx1
  if y1<0 or y1>191:
    dy1=-dy1
  if x2<0 or x2>383:
    dx2=-dx2
  if y2<0 or y2>191:
    dy2=-dy2
  if x3<0 or x3>383:
    dx3=-dx3
  if y3<0 or y3>191:
    dy3=-dy3
  if x4<0 or x4>383:
    dx4=-dx4
  if y2<0 or y2>191:
    dy4=-dy4
  clear_screen()
  bezier(x1,y1,x2,y2,x3,y3,x4,y4,(255,0,0))
  show_screen()

 これまでと同様にパソコン側でファイルを作成しておき、電卓に転送します。ファイル名はB2.pyとしてあります。実行すると赤い3次ベジェ曲線がうねうね動きます。

 ベジェ曲線などのプログラムはグラフィックライブラリのpyファイルにまとめておけば使い勝手もよくなるでしょう。自前のグラフィックスライブラリを作ってみるとよい勉強になるでしょう。

著者 仲村三郎
日本のお家芸である小型化を体現したのが古き良き時代のポケットコンピューター(略してポケコンと呼ばれていました)。関数電卓はポケットコンピューターとは違いますが、今ではPythonでプログラミングできるまでに進化。進化した関数電卓を使って楽しもうではありませんか。