マウスで線を引く(Pythonでリストのリストのアイテムの値を変える)
OpenGLで絵を描く練習をいろいろとやっている。
GLUTによる「手抜き」OpenGL入門を読みながら、サンプルコードをPythonコードに変換している。今回は、マウスで画面に線を引くサンプルコードを変換した。
ここで、マウスでドラッグする始点と終点をpointというリストに入れているのだが、リストのリスト(2次元配列ですね)が予期せぬ挙動を示したので少しコード変換に手間取った。問題だった点は最後に書く。最初は、今回のOpenGLを使ったPythonコード。
PyOpenGLを使ったコード
from OpenGL.GL import * from OpenGL.GLUT import * MAXPOINTS = 100 point = [[0, 0]]*MAXPOINTS #リストの初期化 pointnum = 0 def display(): glClear(GL_COLOR_BUFFER_BIT) if pointnum > 1: glColor3d(0.0, 0.0, 0.0) glBegin(GL_LINES) for i in range(pointnum): glVertex2iv(point[i]) glEnd() glFlush() def mouse(button, state, x, y): global point global pointnum if button == GLUT_LEFT_BUTTON: point[pointnum] = [x,y] # point[pointnum][0] = x # 最初はこう書いた。これだと動かない # point[pointnum][1] = y # 最初はこう書いた。これだと動かない if state == GLUT_UP: glColor3d(0.0, 0.0, 0.0) glBegin(GL_LINES) glVertex2iv(point[pointnum-1]) glVertex2iv(point[pointnum]) glEnd() glFlush() if pointnum < MAXPOINTS-1: pointnum += 1 else: pass def resize(w, h): glViewport(0, 0, w, h) glLoadIdentity() glOrtho(-0.5, float(w)-0.5, float(h)-0.5, -0.5, -1.0, 1.0) def init(): glClearColor(1.0, 1.0, 1.0, 1.0) glutInitWindowPosition(100, 100) glutInitWindowSize(320, 240) glutInit(sys.argv) glutInitDisplayMode(GLUT_RGBA) glutCreateWindow("sample") glutDisplayFunc(display) glutReshapeFunc(resize) glutMouseFunc(mouse) init() glutMainLoop()
リストのリストの扱いで手間取ったところ
コードの中でコメントしたように、変数pointをリストのリストとして使っている。
リストのリストの簡単なテストをしてみる。
>>> list1 = [[0,1], [2,3]] >>> list1 [[0, 1], [2, 3]] >>> list1[0][1] 1 >>> list1[0][1] = 6 >>> list1 [[0, 6], [2, 3]] >>>
リストのリストのアイテムに値を代入した。これは期待通り。次に初期化してから値を変えてみる。このとき予期せぬ挙動...。
>>> list2 = [[0, 0]]*2 <--初期化(2次元配列の初期化) >>> list2 [[0, 0], [0, 0]] >>> list2[0][1] 0 >>> list2[0][1] = 5 <--代入した >>> list2 [[0, 5], [0, 5]] <--え?!なんで全部のアイテムが変わるの? >>> list2[0] = [2,3] <--これはOK。問題なし >>> list2 [[2, 3], [0, 5]] >>>
こんなふうになるとは、今まで知らなかった。初期化の方法が原因なのだろうが、どういう理屈かな。要素の数が多いときには便利な初期化方法なのだが。