지오지브라와 파이썬의 만남 - Part 2

지오지브라5 베타버전을 기준으로 파이썬 스크립팅에 대해 알아보겠습니다.

자이썬

먼저 알아둬야 할 사실은 지오지브라가 자바 기반의 앱이고, 파이썬 지원을 위해 자이썬(Jython)을 사용하고 있다는 점입니다. 현재 자이썬은 2.7 베타가 나와있기는 하지만 일반적으로 사용되는 버전은 2.5이고, 지오지브라5 베타버전도 자이썬 2.5를 사용하고 있습니다. 이런 배경 때문에 대략 파이썬 2.5의 기능들만 허락된다는 점을 염두에 두셔야 합니다. 지오지브라5의 정식버전이 나올 때 자이썬 2.7이 지원된다면 좋겠지만, 지금은 단지 희망일 뿐입니다.

파이썬 창

지오지브라5 베타에는 보기 > Python 메뉴가 추가되어 있습니다. 선택하면 파이썬 코드를 입력할 수 있는 창이 생깁니다. 각각 Interactive, Script, Events 세 개의 탭이 제공됩니다. 제 작업 스타일 때문에, Events 탭은 그리 쓸모가 없습니다. 오늘은 Interactive 탭에만 집중합시다. Script 탭은 다음에 다루겠습니다.

Interactive 탭은 대화형 모드를 제공합니다. 탭을 선택하면 하단에 입력 창이 보이는데, 프롬프트는 없지만 파이썬의 대화형 모드와 유사하게 동작합니다. 여러 줄로 구성된 코드도 입력할 수 있습니다.

Script 탭에는 코드를 편집할 수 있는 창 하나만 제공됩니다. 이 곳에 저장된 코드는 파일이 로드 될 때 실행됩니다.

제가 사용하고 있는 맥 버전의 경우 파이썬 창의 우측 상단에 “새로운 창에서 화면 보이기” 버튼이 제공됩니다. 이 버튼을 클릭해서 별도의 창으로 분리시켜서 사용하는 것이 좋습니다. 이렇게 하면 기본 윈도우에서는 보이지 않던 파이썬 창 전용의 메뉴가 나타납니다. 이 메뉴들 중에는 Script 탭에 기록된 코드를 실행하거나, 실행중인 인터프리터에 인터럽트를 보내는 등의 꼭 필요한 기능들이 포함되어 있습니다.

Interactive 탭을 사용하여 코드를 입력해봅시다.

작도

먼저 원점 O 를 찍습니다.

geo.O = (0,0)

지오지브라와 파이썬은 독립된 이름공간을 유지합니다. 지오지브라의 수학적 능력을 사용하는 것이 목적이므로, 지오지브라의 이름공간을 읽거나 조작할 수 있는 방법이 필요합니다. 이 기능을 제공하는 것이 미리 정의된 geo 객체입니다. geo.O 는 지오지브라 객체 O 를 지칭하고, 파이썬의 튜플은 지오지브라의 점에 대응합니다. 다른 표현법도 제공합니다. 다음 세 개의 문장은 모두 같은 뜻입니다.

geo.O = (0,0)
$O = (0,0)
$['O'] = (0,0)

취향대로 사용해도 좋지만, 저는 geo 를 사용하는 방식 한가지만 사용하겠습니다.

한 가지 주의할 점은 미리 정의되지 않은 지오지브라 객체를 참조하면 오류가 발생하지 않고 None 이 온다는 점입니다. 세가지 방식 중 어떤 것을 사용해도 오류는 발생하지 않습니다. 그러니 오타를 내지 않도록 조심하는 수밖에 없습니다.

이제 O 를 중심으로 하고, 반지름 10인 원 A를 그립니다.

geo.A = Circle(geo.O, 10)

Circle 역시 미리 정의된 객체로 지오지브라의 원 객체를 만들어냅니다. 이런 식으로 여러 가지 객체들이 정의되어 있습니다. 명령 행에서 dir() 해보면 몇 가지 더 볼 수 있습니다.

이제 원 위의 점 P 를 정의하겠습니다.

import math
geo.T = 6 * math.pi
ggbApplet.evalCommand('t := Slider[0,T,0.05]')
ggbApplet.evalCommand('P := Rotate[(10,0),t,O]')

모든 지오지브라 객체가 파이썬에서 제공되는 것은 아닙니다. 이럴 때는 GGBScript 를 실행해서 원하는 객체를 만들 수 있습니다. geo 객체가 지오지브라의 객체들에 접근할 수 있는 방법을 제공한다면, ggbApplet 객체는 API 를 제공합니다. 이 중 가장 유용한 메쏘드가 ggbApplet.evalCommand() 인데, 인자로 전달되는 GGBScript 를 실행하고 성공여부를 돌려줍니다.

라디안으로 0과 $6pi$ 사이의 값을 갖는 슬라이더 t 를 만듭니다. 기하 창 위에 마우스로 움직일 수 있는 슬라이더가 생기는 것을 확인할 수 있습니다.

P 는 점 (10,0) 을 원점을 중심으로 t 만큼 회전시켜 만듭니다. 점 P 의 위치는 t 와 연결되어 있기 때문에, 슬라이더를 움직이면 점 P 도 함께 움직입니다.

이 제 원 A 의 둘레를 굴러가는 반지름 3인 원 B 와 그 위의 점 Q 를 정의합니다.

ray = Ray(geo.O, geo.P)
c1 = Circle(geo.P, 3)
dummy, geo.O_B = Intersect(c1, ray)
geo.B = Circle(geo.O_B, 3)
ggbApplet.evalCommand('Q := Rotate[P,10/3*t,O_B]')

ray 는 점 O 에서 출발해서, 점 P 를 지나는 반직선입니다. 점 P 를 중심으로 원을 그린 후, ray 와의 교점을 구하면, 외접원의 중심 O_B 를 구할 수 있습니다. 이 점을 중심으로 원을 그리고, 그 원 위의 점 Q 를 정의합니다. 점 Q 는 점 P 와 같이 출발하지만 외접원 위에서 움직입니다.

지금 저희가 그린 점 Q 의 자취는 에피사이클로이드(Epicycloid)라고 하는 도형의 일종입니다. 이제 마지막 쇼를 준비합니다.

for x in (ray, c1, geo.O_B, dummy): x.visible = False
ggbApplet.evalCommand('l = Locus[Q,t]')
ggbApplet.setAnimating('t', True)
ggbApplet.setAnimationSpeed('t', 0.1)
ggbApplet.startAnimation()

그리 중요하지 않은 객체들을 보이지 않게 처리하고, 점 Q 의 자취를 Locus 명령으로 그립니다. t 가 저절로 바뀌도록 주문하면 데모가 시작됩니다. 외접원이 굴러가면서, 그 위의 점 Q 가 에피사이클로이드 곡선 위를 움직이는 모습을 감상하실 수 있습니다. 기하 창에 이런 그림이 나와야 합니다.

Epicycloid

Epicycloid

다음에는 좀 더 시각적으로 개선된 데모를 만들면서, 이벤트 처리와 Script 탭을 다루도록 하겠습니다.