[Logo] 나무그리기

Posted by DamienRice 내가 만든 것/생각, 글 : 2008. 2. 11. 23:15

이번에는 나무를 그려본다. 자연에서 나무가 가지를 뻗는것도 일정한 패턴을 가지고 있다고 한다. back이라는 명령이 있을까 하여 대충 써봤는데 뒤로가기도 있었네 (당연한거겠지만..-_-)

그리고 이번에는 코드에 indentation을 주어 이해가 쉽도록 했다. 한줄에 모두 적는것보다는 특정한 모양을 그리는 부분에 해당하는 부분을 같은 indentation을 주니 자연스레 코드도 점진적으로 코드를 작성하게 되었다. 일단, 나무가지가 왼쪽으로만 뻗는다고 가정했을때의 모양과 코드

사용자 삽입 이미지

왼쪽으로만 가지치는 나무 (drawtree 300 2)



to drawtree :l :n
    if :n=0 [fd :l back :l stop]

    fd :l back :l

    fd :l/3
        lt 45 drawtree 3/5*:l :n-1 rt 45
    back :l/3
end


fd :l/3 ... back :/3  사이에 가지를 치는 코드를 추가하면 왼쪽으로 약간 긴 가지 한번을 치고 오를쪽으로 약간 짧은 가지를 한번 치는 나무가 된다.

사용자 삽입 이미지

왼쪽으로 약간길게, 오른쪽으로 조금 짧게 가지치는 나무 (drawtree 300 2)


to drawtree :l :n
    if :n=0 [fd :l back :l stop]

    fd :l back :l

    fd :l/3
        lt 45 drawtree 3/5*:l :n-1 rt 45
            fd :l/5
                rt 45 drawtree 2/5*:l :n-1 lt 45
            back :l/5
    back :l/3
end


방금 추가된 코드와 같은 레벨에서 코드를 또 추가하면 같은 방향으로 가지를 두번 치는 나무가 된다. 그런데,, 그림이 그다지 이쁘지는 않네..-_-a

사용자 삽입 이미지

왼쪽으로 한번, 오른쪽으로 두번 가지치는 나무 (drawtree 300 2)



to drawtree :l :n
    if :n=0 [fd :l back :l stop]

    fd :l back :l

    fd :l/3
        lt 45 drawtree 3/5*:l :n-1 rt 45
            fd :l/5
                rt 45 drawtree 2/5*:l :n-1 lt 45
            back :l/5
            fd :l*3/5
                rt 45 drawtree 2/5*:l :n-1 lt 45
            back :l*3/5
    back :l/3
end


역시 난 미적 감각이 너무 떨어진다...-_-;;

  
사용자 삽입 이미지

코흐곡선



자연에는 황금비도 존재하지만 프랙탈도 존재한다. 아무리 확대해도 결국은 자기 자신인 프랙탈. 어쩌면 나의 내면과도 일맥상통하는듯..

코드:
to koch :l :n
    if :n=0 [fd :l stop]
    koch :l/3 :n-1 lt 60 koch :l/3 :n-1 rt 120 koch :l/3 :n-1 lt 60 koch :l/3 :n-1
end

이를 확장하면 코흐의 눈송이도 그릴 수 있다. 코흐의 눈송이는 코흐의 곡선을 이어붙인 것이다.

사용자 삽입 이미지

코흐의 눈송이는 코흐 곡선을 한 번 그리고 120도 우로회전, 다시 그리고 우로 120도 회전 또 한번 그리면 된다.

repeat 3 [koch 300 6 rt 120]

프로시저를 두 개로 나눠서 kogh_snowflake가 코흐곡선을 세 번 그리는걸로 처리하면 되려나..? 책에서는 어떻게 했을지 궁금하군. 그리고 내 코드는 recursion을 사용하는데, n이 커질수록 속도가 매우 느려지는 단점이 있다. iteration을 사용해서도 구현할 수 있을 것 같은데.


  

[Logo] 등각나선

Posted by DamienRice 내가 만든 것/생각, 글 : 2008. 2. 7. 22:29

사용자 삽입 이미지

달팽이집 모양이다..





to mycurl :l :n
    repeat 90 [fd :l*3.14/180 lt 1]
    if :n=0 [stop]
    mycurl :l/1.618 :n-1
end

황금비가 자연에 많이 있다는데, 지금도 가끔씩 보는 달팽이집에도 황금비가 있구나. 근데 로고에는 원 그리기는 있는데,, 부채꼴 그리기는 없나보다. -_-a


  

[Logo] 정 N각별.. 다음단계

Posted by DamienRice 내가 만든 것/생각, 글 : 2008. 1. 31. 22:49
사용자 삽입 이미지

to myjung :l :n
    repeat :n [fd :l rt 120 fd :l lt (180*(:n-2)/:n)-60]
    rt 60
    repeat :n [fd :l rt 360/:n]
end

코드가 좀 지저분하긴 하네..


기존에 그린 정 N 각별의 내부 다각형을 선으로 이으니 별이 반듯한 모양이 아니고 휘어보인다. 이미 책에서도 나온 내용. 이를 반듯하게 하기 위해서는 어떤 생각을 해보아야 할까? 일단 각 귀퉁이에 있는 삼각형은 정삼각형이면 안되겠군..

코드를 약간 일반화하니 찌그러지지 않는 N각별이 나온다.

to myjung :l :n
    repeat :n [fd :l rt 2*(180-180*(:n-2)/:n) fd :l lt (180-180*(:n-2)/:n)]
end

사용자 삽입 이미지
리팩토링이 좀 필요한듯?

먼저, rt 이후의 값을 보자. 이 식은 위의 코드에서는 2*(180-180*(:n-2)/:n) 라고 적었는데, 괄호를 풀면 360-360*(n-2)/n 이 된다. 여기서 제 1항의 상수 360도는 필요없는 값이다. 제자리에서 360도를 돌면 역시 제자리이니까. 그러면 상수항 360은 제거가 되고 남은 항은 -360*(n-2)/n 인데 이를 풀어보면 (720/n) - 360 인데 여기서도 마찬가지로 360은 의미없는 값이 되어 결국 이런 복잡한 수식의 값은 720/n인 셈이다.

lt후의 식은 180-180*(:n-2)/:n 인데 이도 간략화가 가능하다. 우선 식을 풀면, 180 - (180n-360)/n 이 되고 이는 180-180 + 360/n, 즉 360/n 이 된다. 간략화한 식을 적용한 코드는 다음과 같다.

to myjung :l :n
    repeat :n [fd :l rt 720/:n fd :l lt 360/:n]
end

코드가 훨씬 깔끔하고 명료해졌다. ㅋㅋ

  

[Logo] 정 N각 별 그리기

Posted by DamienRice 내가 만든 것/생각, 글 : 2008. 1. 29. 23:35

N각별

뾰족 튀어나온 부분의 길이가 30인 정 28각별




예전에 생각했던 아이디어를 일반화해 보았다. N이 커질수록 둥그런 모양이 된다. n각형의 내각의 합이 180*(n-2)임을 적용하니 공식이 간단해졌다.

코드
to myjung :l :n
    repeat :n [fd :l rt 120 fd :l lt (180*(:n-2)/:n)-60]
end

영재들은 어떤 방법을 사용했을지 궁금한데..?

  

간단한 생각을 어렵게

Posted by DamienRice 내가 만든 것/생각, 글 : 2008. 1. 27. 20:13

최근 머리가 좋아지는 Logo 프로그래밍이라는 책을 읽고있다. 이 책은 Logo라는 언어에 대한 입문서라고 말할 수 있는데, 이 언어는 어린이들이 사용할 수 있을 만큼 쉽고, 창발적인 사고를 할 수 있도록 도와준다. 현재 미국, 유럽, 일본의 영재교육에 사용되는 것으로 알고있다.

Logo를 이용하여 코드를 작성하면 거북이(?)가 정의된 코드에 따라 화면에서 이동을 하게되고 그 궤적이 화면에 남게된다. 난 현재 기본적인 단계로 직진 및 회전하는 명령만 사용할 수 있다.

간단한 도형 - 사각형, 원, 삼각형등을 그리는 것은 아주 쉽다. 단지 '직진 100픽셀, 90도 우로회전'을 4번 반복하는 것이 사각형이고, 각도와 횟수만 바꿔주면 삼각형이 될 수도, 원이 될 수도 있기 때문이다. 내가 간단한 것을 복잡하게 생각하고 있었다는 것을 깨닫게 된 도형은 별이다. (변명을 하자면, 난 한 쪽 스크린에는 영화를 재생해놓고 다른쪽 스크린에서 코드를 작성하고 있었다는 것이다)

어쨋든, 내가 그린 별은 다음과 같다.

사용자 삽입 이미지
이때 사용한 코드는 repeat 5 [fd 100 rt 144 fd 100 lt 72] 이다. 해석하면 대괄호안의 명령문을 다섯 번 실행하는 것인데, 괄호안의 명령은 100만큼 앞으로 가서 오른쪽으로 144도 회전하고 다시 100만큼 앞으로 가서 왼쪽으로 72도 회전하는 것이다. 즉, 별의 꼭지점을 다섯개 그리라는 의미와 같다.

처음에 이 방법을 생각하게 된 기초는 정오각형에 삼각형을 하나씩 붙이려고 했던 것이 별과 같은 모양이라는 생각이었다. 허나 정오각형의 내각을 잘못 계산하는 바람에 (원래는 108도인데 120도로 생각하고 있었다) 계속 이상한 모양이 나오는 것이었다. 결국에는 각도를 제대로 알아내고 그려냈지만... 거북이의 입장에서 보면 거북이가 이동한 경로는 다음과 같다.

사용자 삽입 이미지
허나 책의 저자는 어떻게 했을까 하고 책장을 넘기는 순간, 더 간단하고 일반적인 방법이 있음을 알았다.

사용자 삽입 이미지
물론 내가 그린 모양과 책에서 그린 모양은 다르다 (내가 그린 별에는 내부에 있는 정오각형의 경계선이 없다) 그러나 둘다 사람이 보기에 '별'에 해당하므로 굳이 구분지을 필요는 없다. 이 별을 그리는 코드 repeat 5 [fd 200 rt 720/5] 이다. 이 방법은 거북이가 작은 삼각형을 그리는 것이 아니고 다음과 같이 별의 꼭지점과 꼭지점 사이를 바로 그린다.

사용자 삽입 이미지


공식에 있는 720은 거북이가 회전하는 각도의 총합이다. 이는 5각별이 아닌 경우에도 마찬가지인데, 이를 이용하면 n각별을 그리는 코드를 도출할 수 있다.

to nstar :n :length
   repeat :n [fd :length rt 720/:n]
end

시도해보지는 않았지만 내가 시도한 방법으로 n각별을 그리는 방법을 찾을 수는 있을 것 같다. 그러나 코드를 읽는 사람도 매번 n각형에 따른 별의 꼭지점 각도를 계산해야 하는등 직관성이 많이 떨어진다는 한계가 있다.

이와 같은 경우가 아니더라도 간단한 해결책을 두고 복잡한 경우만을 생각하고 쉬운 방법을 보지못해서 시간을 낭비하고 다른사람의 효율도 떨어뜨리는 경우는 많을 것이라 생각된다. 협력작업(나의 경우에 있어서는 Pair Programming)이 얼마나 중요한지 오늘 한번의 경험을 또 하게 되었다.







  
 «이전 1  다음»