posted by cimple 2013. 8. 24. 13:36
def helloWorld():
    print "hello, world!"


블로그에 위와 같이 가독성좋은 스타일로 소스코드를 업로드하기 위해 이용할 수 있는 대표적인 방법이 SyntaxHighlighter 를 이용하는 방법이다.






설치방법은 검색해보면 다른 블로그에서도 충분히 설명이 잘 되어 있으니 굳이 여기서 다시 구체적으로 설명할 필요는 없을 것 같고,


(좋은 링크  : 'cocosoft' 님의 SyntaxHighlighter 소개글)


정말 간단하게만 설명하겠다.




1. SyntaxHighlighter 홈페이지 > Download 섹션에서 최신버전 다운로드

http://alexgorbatchev.com/SyntaxHighlighter/


2. 압축해제. 다양한 폴더가 나옴


3. scripts, styles 폴더 전체를 블로그에 업로드

(+ Tistory 유저라면 관리 페이지>HTML/CSS 편집>파일 업로드로 한꺼번에 추가 가능)

(+ 물론 필요한 언어팩과 스타일만 설치할수도 있지만, 용량도 몇KB 단위라 얼마 안되고 그냥 아 귀찮아 하는분들을 위해서...)


4. 스킨 HTML 파일 수정 

(+ Tistory 유저라면 skin.html 수정페이지에서 수정)

(+ SyntaxHighlighter 스타일은 header 부분에 추가. 볼드체 부분을 다른 스타일로 수정가능)

<link rel="stylesheet" type="text/css" href="./images/shCoreDefault.css">

(+ 사용할 언어팩 지정은 body 에서 수정. 물론 필요한 것만 추가해도 됨.)

<script type="text/javascript" src="./images/shCore.js"></script>

<script type="text/javascript" src="./images/shAutoloader.js"></script>

<script type="text/javascript" src="./images/shBrushAppleScript.js"></script>

<script type="text/javascript" src="./images/shBrushAS3.js"></script>

<script type="text/javascript" src="./images/shBrushBash.js"></script>

<script type="text/javascript" src="./images/shBrushColdFusion.js"></script>

<script type="text/javascript" src="./images/shBrushCpp.js"></script>

<script type="text/javascript" src="./images/shBrushCSharp.js"></script>

<script type="text/javascript" src="./images/shBrushCss.js"></script>

<script type="text/javascript" src="./images/shBrushDelphi.js"></script>

<script type="text/javascript" src="./images/shBrushDiff.js"></script>

<script type="text/javascript" src="./images/shBrushErlang.js"></script>

<script type="text/javascript" src="./images/shBrushGroovy.js"></script>

<script type="text/javascript" src="./images/shBrushJava.js"></script>

<script type="text/javascript" src="./images/shBrushJavaFX.js"></script>

<script type="text/javascript" src="./images/shBrushJScript.js"></script>

<script type="text/javascript" src="./images/shBrushObjC.js"></script>

<script type="text/javascript" src="./images/shBrushPerl.js"></script>

<script type="text/javascript" src="./images/shBrushPhp.js"></script>

<script type="text/javascript" src="./images/shBrushPlain.js"></script>

<script type="text/javascript" src="./images/shBrushPowerShell.js"></script>

<script type="text/javascript" src="./images/shBrushPython.js"></script>

<script type="text/javascript" src="./images/shBrushRuby.js"></script>

<script type="text/javascript" src="./images/shBrushSass.js"></script>

<script type="text/javascript" src="./images/shBrushScala.js"></script>

<script type="text/javascript" src="./images/shBrushSql.js"></script>

<script type="text/javascript" src="./images/shBrushVb.js"></script>

<script type="text/javascript" src="./images/shBrushXml.js"></script>

<script type="text/javascript" src="./images/shLegacy.js"></script>

<script type="text/javascript">

    SyntaxHighlighter.all();

</script>


5. 이제 사용하면 되는데 <pre> 를 사용하는 방법과 <script> 를 사용하는 방법이 있음.

<pre class = "brush: (언어)"> 

... source code...

</pre>


<script type="syntaxhighlighter" class="brush: (언어)">

...source code...

</script>


둘다 장단점이 있는데 그건 원래 홈페이지 Document 참고.

posted by cimple 2013. 8. 19. 16:03

API 나 라이브러리 등을 보면 자주 보이는 것이 Virtual 함수를 통한 상속이다. 그냥 그런가보다 하고 쓸 수도 있지만, 정확한 개념을 알면서 사용하는 것이 좋다.


기본적으로 기억해야 할 개념은 Virtual 함수는, 객체지향 프로그래밍의 철학중 하나인 '함수의 다형성(polymorphism)' 을 위해 존재한다는 것이다.


'함수의 다형성'은 다시 한문장으로 정리하면 "동일한 명령에 대해서, 서로 다른 객체가 서로 다르게 수행한다" 라고 할 수 있다.


이는 이렇게 쉽게 설명할 수 있다. '도형' 이라는 부모 클래스를 가지고 있고, '삼각형', '사각형', '원' 이라는 자녀 클래스를 가지고 있을 때, 자녀 클래스에 모두 필요한 draw() 라는 함수를 구현한다고 하자.  같은 명령이지만, 각 객체가 다른 일을 하는, 다형성이 적용될 수 있는 좋은 사례이다. 


이 경우에 물론 각각 자녀 클래스의 인스턴스를 만들어 일을 수행할 수도 있지만, 부모인 '도형' 인스턴스를 자녀 클래스의 포인터 인스턴스로 만들수 있다.


Figure *fig1 = new Triangle;

Figure *fig2 = new Square;

Figure *fig3 = new Circle;


이렇게 만들면, Figure 라는 클래스 하나로 각각의 자녀 클래스들이 하는 일들 specific 하게 수행하는 인스턴스들을 만들어낼 수 있다. 좀 더 코드가 깔끔해지고 가독성이 분명해질 것으로 보인다. 이런 작업이 '함수의 다형성' 을 이용한 프로그래밍이다.


이럴 경우, draw() 라는 함수는 원래 Figure 라는 클래스에 무언가 형태를 가지고 있고, 실제로 실행될 때에는 Triangle, Square, Circle 안에 들어있는 draw() 함수에 맞게 각각 실행되어야 할 것이다. 이를 위해서 Figure 클래스 내부에


class Figure {

public:

virtual bool draw() = 0;

};


이런 식으로 virtual 키워드를 이요한 가상함수를 만들고, 각 자녀 클래스들은


class Triangle : public Figure {

public:

bool draw(){

...draw triangle...

}

};


각자 가지고 있는 draw() 함수로 일을 하게 되는 것이다. 이렇게 각각의 자녀 클래스 인스턴스에 맞게 함수가 실행되는 것을 '동적 바인딩' 이라고 한다.


위에서 예를 들은 virtual 함수는 정말로 아무런 일도 하지 않는 '순수 가상함수' 이다. 이런 순수 가상 함수를 가지고 있는 클래스는 '추상 클래스' 로서, 독자적으로 인스턴스를 생성할 수 없고, 딱 이러한 다형성을 목적으로 존재하는 클래스이다. 


참고링크 : '새-치킨-독수리' 예를 통하여 알기쉽게 Virtual 함수의 쓰임새를 설명해주신 좋은 링크

(http://pacs.tistory.com/19)


참고링크 : 위에서 설명한 도형 예제로 다형성과 Virtual 함수의 쓰임새에 대해서 설명해 주신 링크

(http://yagi815.tistory.com/220)


참고링크 : 왜 소멸자는 Virtual 로 만들어야만 하는가, 에 대한 링크. 

(http://www.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tutorial&no=91)


간략하게만 설명하면, 위의 다형성 예제에서 생각했을 때, 부모 클래스의 소멸자를 Virtual 로 생성하지 않으면, 위의 예제처럼 자녀 클래스의 포인터로 생성했다면? 소멸자가 불려졌을 때? 자녀 클래스의 소멸자를 호출할 수가 없다. 그래서 Virtual 함수로 소멸자를 생성하면 자녀클래스->부모클래스 순으로 안전하게 소멸자가 호출된다.



posted by cimple 2013. 3. 5. 00:08

Python Module 사용법을 자꾸 망각해서(;;) 몇가지 내용을 메모해둔다. 나중에 정리해야겠다.



1. Python Module 을 import 하기 위해서


하나의 파일에 파이썬 스크립트를 작성하면, 이 스크립트를 모듈로 import 할 수 있다.

이를 위해서는 먼저 해당 파일이 Python path 안에 들어있거나, 

해당 파일이 위치한 경로를 Python path 에 등록해 주어야 한다.



import sys 

# sys 모듈을 먼저 import 한다.


print sys.path    

# 현재 Python path 확인이 가능하다


if "C:/Users/cimple/Documents/GitHub/autoRig" not in sys.path :

    sys.path.append("C:/Users/cimple/Documents/GitHub/autoRig")

# 내가 등록하고 싶은 path 가 이미 python path 에 등록되어있는지 확인하고 등록한다. 이 과정이 없으면 같은 path 를 계속해서 등록한다.


import autoRig

reload(autoRig)

# 내가 원하는 module 을 import 한다. 그런데 load 이후 한번 reload 를 해주어야 수정된 결과가 바로 업데이트된다. 아니면 수정을 하더라도 처음 import 된 모듈을 그대로 사용한다.

posted by cimple 2012. 1. 11. 22:14

환경 변수에 등록된 각각의 폴더에, 같은 실행 파일이 있으면 어떻게 될까?

파이썬 프로그래밍을 하다 보면 버전별로 다른 라이브러를 제공하는 경우가 있기 때문에 다른 버전의 파이썬을 설치할 일이 생긴다.

이 때, 환경 변수에 각각의 파이썬 폴더를 등록시켜 놓았을 경우.

C:\Python26;
C:\Python27; 

와 같이 2개 버전의 환경변수를 모두 등록시켜 놓았다면, 이 때 실행파일 python.exe 은 어떤 파이썬 폴더를 실행시키게 될까?

답은 환경 변수에 '먼저 써놓은' 파이썬 폴더의 실행파일을 실행하게 된다.



C:\Python26;C:\Python27;  

이렇게 해 두면 Python 2.6 버전의 실행파일을 먼저 실행하게 된다는 것이다.





그렇다면, 특정 버전의 파이썬을 실행시키고 싶다면 어떻게 해야 할까?

각각의 폴더 안에 있는 파이썬 실행 파일을 python26.exe, python27.exe 하는 식으로 복사해서 하나 더 넣어둔다.

그리고 실행을 할 때

python26   myscript.py
python27   myscript.py

이런 식으로 하면 각각 다른 버전으로 실행시킬 수 있을 것이다.




ThEnd. 
posted by cimple 2011. 1. 13. 19:03

Useful Commands 라는 것이 참 분류하기 애매모호하지만, 간단한 기능인데 찾으려면 시간이 걸리는 기능들을 모아 보려고 합니다. 지속적으로 업데이트 될 것입니다.




1. 특정 object 의 절대적 위치 얻기

특정 object 의 공간상에서 절대적 위치를 얻고 싶은데, attribute 에서 얻는 것은 한계가 있습니다.
xform 명령을 사용하면 공간 상에서 절대적 위치 정보를 얻어낼 수 있습니다.

ex) mc.xform('joint18',q=True, translation=True, worldSpace=True)




2. Point 의 절대적 위치 얻기

마야에서 사용되는 포인트들 (Vertex, CV...) 등의 위치 정보는 따로 얻어낼 수 있는 커맨드가 있습니다.
pointPosition 명령을 사용하면 됩니다.

ex) mc.pointPosition('vertexName')




3. 특정 object 의 parents, child 얻기

특정 object 에 hierarchical 하게 연결된 object 의 parents 와 child 를 얻고 싶을 때에는
mc.listRelatives 를 사용하면 된다.

ex) mc.listRelatives('object', c=True)   //  child 를 얻어올 수 있다.




4. Nurbs curve 의 CV 개수 알아내기

nurbs curve 의 cv 개수는 curve 의 degree + spans 와 같다.
즉 ,

num_cv = mc.getAttr('curve1.degree') + mc.getAttr('curve1.spans')

이렇게 구할 수 있다.


5. Blendshape Node 만 있을 때 Target Shape 들의 노드 이름 알아내기
(이 커맨드들은 설영호(seolyeongho@kaist.ac.kr), 서재우(goongsang@kaist.ac.kr) 학생에 의해 작성되었음을 알립니다)

방법 1.
listAttr -sn blendShape13.weight[0];

방법 2.
string $blendShapes = "blendShape13";
string $names[] = `listAttr -m ($blendShapes + ".w")`;

방법 3.
string $temp[] = `aliasAttr -q blendShape13`;
print $temp

방법 4.
blendShape -q -t



6. 현재 선택한 object 의 list  받아오기

mc.ls(sl=True)


7. Pivot 옮기기

move 명령어로 옮겨줄 수 있다. 그런데 scalePivot 과 rotatePivot 을 옮겨주어야 한다. translatePivot 은 없고, rotatePivot 을 따라가는 것으로 보인다.

mc.move(0, 0, 0, 'object.rotatePivot', 'object.scalePivot')



8. 파일 Import

mc.file("D:/maya/projects/default/scenes/Woman_Rigging_Template_07.mb", i=True)



9. Hierarchy 모두 선택

mc.SelectHierarchy()


10. Keyable 한 Attribute 얻기

keyable = mc.listAttr("ctrlName", k=True)

이 외에도 listAttr 은 특정한 attribute 를 얻어내는 데 다양한 flag 들을 가지고 있다.

attribute 가 scalar 인지 정도는 알 수 있지만, int/float 등을 알 수는 없는 듯 하다.


11. Scene 안에 있는 모든 Nurbs curve 얻어내기

crvList = mc.listRelatives(mc.ls(typ="nurbsCurve"), p=True)


여기에서 mc.ls(typ="nurbsCurve") 가 scene 안에 있는 모든 nurbsCurve 를 선택한다. 그런데 이 명령어를 사용하면 shapeNode 를 선택하게 된다. 

이 때 listRelatives 커맨드는 선택한 오브젝트의 child 나 parent 를 선택할 수 있게 해준다. p=True 옵션을 주면 각각 shapeNode 의 parent 인 transform node 를 선택하고, 우리가 원하던 씬 안에 존재하는 모든 nurbs curve의 transform node 들의 리스트를 반환해준다.


12. Polygon 관련 정보는 polyEvaluate

Mesh Polygon 의 Vertex 갯수 등 Polygon 관련 정보를 얻고 싶다면 polyEvaluate 명령을 사용한다.


vtxNum = mc.polyEvaluate('meshName', v=True)




ThEnd.




posted by cimple 2010. 11. 15. 23:31

Maya 에서 스크립트를 작성하다 보면 무한 루프에 빠지는 경우가 있다.

for 문이나 while 문 (특히 while 이놈!) 을 잘못 쓰면 무한 루프에 빠져 버리는 경우가 있는데,

ctrl+break 가 통하는 것도 아니고 esc 를 아무리 연타해도 안 되고, 마야가 먹통이 되어 버려서 결국에는 작업관리자를 켜야만 하는 처지에 놓이게 된다.

이 때, 반복문 내에 무한루프를 방지할 수 있는 간단한 장치를 마련할 수 있는데, 방법이 조금 독특하다.

'외부 파일을 이용' 하는 방법이다. 


사용 방법은 다음과 같다.




1. 위에 첨부된 파일(BREAKMEL.bat) 를 받아서, 소중한 곳에 잘 간직해둔다.
2. 마야에서 MEL scripting 을 하면서, 무한루프가 의심되는 반복문 안에 다음 구문을 넣어준다.

import os
if os.path.exists("c:/breakMel") : break
3. 만약 스크립팅을 하다가 무한 루프에 빠지면, 첨부된 파일을 실행하기만 하면 반복문이 종료될 것이다.



간단한 예제는 다음과 같다.



위와 같은 구문을 스크립트 에디터에서 실행하면, 아마 지구가 멸망할 때까지 1을 찍어댈 것이다.
이 때, 첨부된 BREAKMEL.bat 를 실행시키기만 하면 무한루프를 중지시킨다.
이 때 임시로 생성되는 파일은 자동으로 삭제되니 신경쓰지 않아도 된다.




이 방식의 원리는 다음과 같다.

1. 반복문이 계속 돌면서, 컴퓨터 내부에 특정 파일이 존재하는지 계속 검사를 한다.
2. 만약 무한루프에 빠지면, 그 특정 파일을 생성시킴으로써 반복문을 종료시킬 수 있다.


여기에서 '컴퓨터 내부를 계속 검사한다' 라는 부분이 상당히 찜찜하게 느껴질 것이다.
하지만, 이 방식을 처음 제시한 저자에 따르면 거의 퍼포먼스의 저하가 없다고 한다.

첨부파일인 BREAKMEL.bat 는 뭐 복잡한 구조를 가지고 있는 것이 아니라, 다음이 전부이다.


즉, c:\ 에 breakMel 이라는 가상의 파일을 하나 만들고, 아무 키나 누르면 그걸 지운다는 거다.


재밌는 방식이고, 꽤나 괜찮은 아이디어이다.
하지만 퍼포먼스의 저하가 '전무' 하다는 것은 사실 믿을 수 없다;; 약간 궁여지책처럼 느껴지기도 하고, 의심이 많이 가는 반복문에서만 사용하는 것이 좋을 것 같다.



아이디어는 다음 블로그 포스팅에서 참고하였다.

http://www.naughtynathan.co.uk/?p=59



ThEnd.

posted by cimple 2010. 8. 28. 04:35

프로그래밍을 하다 보면 황당한 경우를 만날 때가 있다. 그 중에 가장 당황스러울 때가, 헤더 파일들을 include 할 때, 특정 순서에 따라서 오류가 나고 안 나고가 결정될 때가 있을 때이다. 다시 말해서

#include <headerfileA.h>
#include <headerfileB.h>

이렇게 include 하면 문제가 없는데,

#include <headerfileB.h>
#include <headerfileA.h>


이렇게 include 하면 문제가 생기는 경우 말이다.

사실 이러한 경우가 발생하는 문제는 상당히 다양하다. 헤더 파일이 헤더 파일을 서로 서로 include 하는 좀 난잡한 구조로 코딩을 한다면 이런 문제가 발생할 가능성이 높다. 때문에 능력있는 프로그래머라면 각 헤더 파일이 의미하는 바와, 그 관계를 잘 설정해 놓고 코딩해야 할 것이다.

하지만 굉장히 난감한 경우도 있는데, 외부 라이브러리를 사용했을 때이다. 외부 라이브러리를 include 했는데 특정 순서에 따라서 컴파일이 되고 안 되고 한다면 정말 해결하기 어려운 노릇이다.

그 중에서 이번에 OpenMesh 를 활용한 Maya 프로그래밍을 하면서 겪었던 일.





#include <OpenMesh/Core/System/config.hh>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/Traits.hh>
#include <OpenMesh/Core/Mesh/Attributes.hh>

#include <maya/MPxNode.h>
#include <maya/MTypeId.h>




Maya Node 를 만들 때 헤더 파일에 위와 같이 라이브러리 헤더 파일들을 include 했더니, 무수한 에러가 발생하였다.

그래서 OpenMesh 관련 헤더파일들을 cpp 파일에서 include 했더니, 에러는 사라졌다. 하지만, 노드 헤더 파일에서 노드 클래스를 구성할 때, OpenMesh 의 객체를 사용해야 하므로 무조건 노드 헤더파일 안에서 OpenMesh 관련 헤더파일들을 include 해야 하는 상황이었다.


빼도 박도 도망가도 못하는 상황이었는데 수백개씩 뜨는 에러메시지 중 다음과 같은 메시지가 눈에 띄었다.




1>c:\program files\openmesh-2.0-rc3\openmesh-2.0-rc3\src\openmesh\core\geometry\vectort_inc.hh(430) : warning C4003: 'max' 매크로의 실제 매개 변수가 부족합니다.
1>c:\program files\openmesh-2.0-rc3\openmesh-2.0-rc3\src\openmesh\core\geometry\vectort_inc.hh(438) : warning C4003: 'min' 매크로의 실제 매개 변수가 부족합니다.
1>c:\program files\openmesh-2.0-rc3\openmesh-2.0-rc3\src\openmesh\core\geometry\vectort_inc.hh(469) : warning C4003: 'min' 매크로의 실제 매개 변수가 부족합니다.
1>c:\program files\openmesh-2.0-rc3\openmesh-2.0-rc3\src\openmesh\core\geometry\vectort_inc.hh(474) : warning C4003: 'max' 매크로의 실제 매개 변수가 부족합니다.
.
.
.


무언가 min, max 를 OpenMesh 에서 사용하는데, 이것이 충돌을 일으키는 것 같았다. 그래서 구글을 좀 뒤져서, 다음과 같은 좋은 정보들을 찾았다.


include 순서 오류에 대한 질문/답변글

min/max 매크로로 인한 오류 해결 방법


즉, Miscrosoft 가 min, max 같은 단어들을 '매크로' 로 등록해 둔 것이 문제라는 것이다. 사실 짧은 프로그래밍 경력과 실력으로 그 의미와 문제점을 명확히 알아듣기가 어렵다.

해결책은 위의 링크에도 소개되었듯이 다음과 같이 헤더파일 상단에 삽입하면 된다.



#define NOMINMAX
#ifdef max
 #undef max
#endif
#ifdef min
 #undef min
#endif




...하나 하나 알아가는게 쉽지만은 않다.


ThEnd.
posted by cimple 2010. 8. 17. 14:29

Python Script 로 처음 구현해 본 Fibonacci 수열이다.

List 를 사용해서 손쉽게 구현할 수 있었다.



fibonacci = [1, 1]
max_range = 7;

for i in range(0, max_range-2, 1):
   a1 = fibonacci[i];
   a2 = fibonacci[i+1];
   fibonacci.append(a1+a2);

print fibonacci



그리고 이 Fibonacci 수열을 이용해서 구를 extrude 시키는 기능을 구현해 보았다.


코드는 다음과 같다.





numFace = 0;

for i in range (0, len(fibonacci), 1): 
   mc.select(cl = True); 
   for j in range(0, fibonacci[i], 1):
      mc.select("pSphere1.f[%d]" % numFace, add=True)
      numFace = numFace+1   
   mc.polyExtrudeFacet(ltz = 0.1*fibonacci[i]);


그런데 이 때, 2번째 for 문의 range 를 1로 시작하는 실수를 했더니 계속해서 문제가 발생했다.
즉, 이런 형태의 for 문이 만들어지면

for i in range (1, 1, 1)

for 문은 아무런 기능을 하지 못하고, 만약 그 안에서 특정 기능을 수행해야 할 경우 error 를 발생시키게 된다.

좌우지간 위의 코드를 실행하면 다음과 같은 결과를 얻는다.








그리고 다음은 피보나치 수열을 11번 항까지, 그리고 extrude 에 keepFacesTogether = 0 을 주고 실행한 모습.




별 거 아니지만 재밌다.


ThEnd.

posted by cimple 2010. 8. 13. 16:03

(어쩐지 좀 두서없는 포스팅같기는 한데;; 그리고 요즘 R 프로그래밍을 함께 공부하고 있는데 Python 과 문법이 유사하다는 생각을 무척 많이 하고 있다.)


1. Python 의 List 생성.

Python 의  List 는 데이터를 저장하는데 훌륭한 자료구조를 제공해주고 있다.
일단 Python List 에 데이터를 저장하기 위해서는 다음과 같이 저장한다.


myFirstList = ["red", 21.00, 1]


myFirstList 라는 list 이름을 정해주고, 대괄호 [] 로 묶어주면 그 안에 원하는 data 를 넣어주면 된다. 이 때 data 의 type 이 위의 예제처럼 달라도 상관이 없다.

MEL 에서는 이것이 불가능했지만, python list 에서는 가능하고, 심지어 list 도 list 안에 들어가기 때문에 간편하게 데이터를 관리할 수 있다.


list 에 있는 데이터에 접근하기 위해서는 c 의 배열에 접근하는 방법과 비슷하게 접근하면 된다.

myFirstList[0];

위에는 "red" 가 들어있게 된다.



재미있는 것은, maya 에서 현재 내가 선택하고 있는 object 를 list 안에 등록할 수 있다.
다음과 같이 등록하면 된다.

import maya.cmds as mc;
listObject = mc.ls(sl=True);

MEL 커맨드로 ls -sl 을 하면 현재 내가 선택하고 있는 object 를 반환하는 기능을 이용한 것이다.
print 해 보면 다음과 같이 나온다.

print listObject;

[u'pSphere1', u'pCube1']


pSphere1 을 먼저 선택하고, pCube1 을 다음에 선택한 다음 list 에 등록하면 위와 같이 들어간다.

u가 붙은 이유는 잘 알수 없으나, 실제로 값을 빼 보면 u 는 빠져있고 pSphere1 만 나온다.






2. List 의 크기 받아오기

언제나 자료의 크기를 아는 것은 중요하다. Python Script 에서는 len() 이라는 함수를 사용한다.

len(custom_list);

이것으로 사용자가 생성한 list 의 크기를 알 수 있다.







3. List 의 data 에 iterative 하게 접근하기

List 의 data 에 대하여 iterative 하게 접근할 수 있다. 이는 for 문으로 가능한데, Python Script 에서 for  문은 다음과 같은 형태를 가진다.


for i in range(start, end, increment)


그리고 Python Script 의 for 문은 조금 독특한 문법을 가지고 있는데, for 문 다음에 콤마 (:) 로 시작해서 들여쓰기로 해당 scope 를 표시한다. 즉


for i in range(0, 5, 1) :
          print i
print "done"



위와 같은 코드가 있을 때, i 는 1, 2, 3, 4, 5 로 반복문을 돌면서 찍히겠지만 "done" 은 한 번만 찍힌다.


for i in range(0, 5, 1) :
          print i
          print "done"


위와 같은 경우는 done 도 5번 찍히는 것이다.

이 반복문을 이용해서 list 안에 있는 data 들에 접근하기 위해서는



for i in range(0, len(custom_list), 1):
          print(custion_list[i])




이렇게 하면 list 에 있는 요소들에 순차적으로 간편하게 접근할 수 있다.







ThEnd.




p.s. 다음 링크로 가면 파이썬의 기본 데이터 유형인 사전, 리스트, 터플에 대해서 소개하고 있다.

http://coreapython.hosting.paran.com/dive/chap03.html#d0e5887
 
posted by cimple 2010. 8. 13. 14:08

C 로부터 시작해서 C++ 로 파일 입출력을 수행하는 방법은 여러 가지가 있다.

하지만 이번 포스팅에서는 이번에 Maya Programming 을 하면서 내가 직접 수행했던 파일 입출력을 정리해두고자 한다.



일단 기본적으로 C++ 에서 파일 입출력을 위해서 include 해야 할 파일은

#include <fstream>

이다.

그런데 마야 프로그래밍을 할 때에 이런 식으로 기본 C++ 파일 입출력을 수행하면 코드 내에서 명령어를 찾을 수 없다는 메시지가 계속해서 뜬다. ㅡ_ㅡ;;;

(namespace 만 제대로 처리해주면 위의 문제(?) 를 해결할 수 있습니다.
std::ifstream  fin;
이런 식으로 사용해주면 된다는 것이지요.
아니면 만사형통 using namespace std; 를 써도 되지만 물론 비추이지요.)


마야 프로그래밍에서 파일 입출력을 하기 위해서는

#include <maya/MFStream.h>

를 include 해서 사용하도록 한다.

처음에 include 하는 부분만 다르지, 객체를 생성해서 파일 입출력을 수행하는 코드 부분은 같다.



1. 파일 출력

파일을 출력하는 방법은 간단하다. 다음의 과정을 거치면 된다.

1. 파일을 출력하기 위한 ofstream 객체를 만든다.
2. 파일을 연다.
3. 파일에 쓴다.
4. 파일을 닫는다.


예제는 다음과 같다.

ofstream fout;
fout.open("filename.dat");
fout << "Hello, World!" << endl;
fout.close();

객체를 만들 때 바로 파일에 연결해도 된다.

ofstream fout("filename.dat");





2. 파일 입력

파일을 입력하기 위해서는 다음의 과정을 거치면 된다.

1. 파일을 입력받기 위한 ifstream 객체를 만든다.
2. 파일을 연다.
3. 파일을 읽는다.
4. 파일을 닫는다.


예제는 다음과 같다.

ifstream fin;
fin.open("filename.dat");
int variable;
fin >> variable;
fin.close();


이 때, ifstream 으로 파일을 한 번 읽으면 파일에 공백으로 띄워져 있는 데이터 하나를 읽게 된다.
예를 들어 파일이

15   4   9   6
7    3   5   4

대충 이런 식으로 되어 있다면, fin 을 한 번 하면 15를 variable 에 저장한다.
파일을 처음부터 끝까지 읽고 싶다면 while 문을 사용하면 된다.
fstream 에서는 파일의 끝일 경우 함수가 0을 리턴하므로 파일의 끝까지 입력받을 수 있다.

int sum_variable;
while( fin>> variable)
{
sum_variable += variable;
}

이런 식으로 간단하게 사용할 수 있다.






3. 파일 입/출력시 파일의 경로 문제

파일을 입/출력받을 때 파일의 경로가 어디에 있는가는 좀 복잡하면서도 까다로운 문제이다.

아마도 절대경로 / 상대경로 등으로 파일의 입력 위치를 지정해 줄 수도 있을 것이다.




그런데 작업을 하면서 한가지 의아한 상황이 발생했는데

파일을 출력할 때에 처음에는 Visual Studio project  폴더의 debug 폴더 안으로 파일이 출력되다가,

갑자기 MAYA scene 파일이 있는 곳에 파일이 출력되는 것이다;


파일을 입력할 때도 마찬가지로

Visual Studio project 폴더 안에 넣어 놓으면 파일을 찾지 못하고,

MAYA scene 파일 안에 있어야 파일을 입력받았다.

Visual Studio 의 링크설정 등에는 분명히 output 경로를 debug 폴더 안으로 출력하도록 되어 있을 텐데, 이건 좀 요상한 일.





4. 여러 개의 파일 입력

여러 개의 파일 입력을 받는 과정에서 약간의 문제가 생겼다.

ifstream 객체 fin 을 하나 만들어서 받고 -> close -> 다시 받고

하면 될 줄 알았는데, 처음에는 받아지는데 다음에 받지 못하는 경우가 생겼다.

이러한 경우가 생겼을 때 .clear() 함수를 통해서 해결할 수 있었다.

즉,

std::ifstream fin;
fin.open("a.txt");
fin.close();
fin.clear();
fin.open("b.txt");
fin.close();

이런 식으로 해야 a.txt 읽고 -> b.txt 읽고, 이런 식으로 작업이 가능하다.




5. 파일을 line 단위로 입력

파일을 line 단위로 입력받아야 할 때가 있는데, 파일 전체의 길이가 너무 길 때이다.

2번처럼 파일의 처음부터 끝까지 한번에 입력받을 경우, 파일의 길이가 너무 길면 vector 같은 저장 공간에 한번에 저장할 수가 없게 된다.

때문에 line 별로 입력받아야 할 필요가 생기는데, 코드는 다음과 같다.






ThEnd.