AutoLISP 강좌 [7]


1. 입문(I) - AutoLISP의 기본 개념
2. 입문(II) - 사용자 정의 함수 제작
3. 입문(III) - 그 밖의 기본 기능들
4. 응용(I) - Entity와 Selection-Set
5. 응용(II) - Symbol table과 Device 제어
6. 응용(III) - Dialogue box 제어
7. 활용예제


7. 활용예제

이번호에는 앞서 배운 내용들을 다시 정리하는 의미에서 몇가지 내용을 종합한 예제하나를 소개할까 한다. 단계적으로 문제를 해결해 나가면서 동시에 이제까지 배운내용들을 정리해 보도록 하겠다. 이제부터 완성해갈 프로그램은 X, Y 비율이 다르게 INSERT된 BLOCK이나 MINSERT된 BLOCK을 EXPLODE 해주는 기능을 갖게된다. 먼저, 그 기능을 어떻게 구현할 수 있을지에 대해 생각해보자.

7.1 기본 설계

다음과 같은 순서로 작업을 세분화할 수 있다.

1) 기존의 EXPLODE 명령으로 분리되지 않는 X, Y 스케일이 다르게 INSERT된 BLOCK 선택한다.
2) 선택된 BLOCK의 엔티티 정보, 즉 BLOCK의 이름과 X, Y 스케일등을 얻어낸다.
3) BLOCK의 이름을 통해 SYMBOL TABLE을 검색하여 BLOCK 정의 엔티티의 이름을 얻는다.
4) 그 엔티티를 시작으로하여 각각의 BLOCK 정의 엔티티의 정보를 얻는다.
5) 엔티티의 좌표점을 BLOCK의 X, Y 스케일를 이용하여 좌표변환한 후 다시 그려준다.
6) MINSERT된 경우에는 BLOCK 한개에 해당하는 엔티티들을 모두 EXPLODE한 후에 그 엔티티들을 모두 행, 열의 개수만큼 배열하면 된다.

그리고, 이번 예제 프로그램에서는 당연히 기본적인 EXPLODE 명령의 기능을 수행하며, BLOCK 정의 엔티티들중 3DFACE, INSERT, LINE, POINT, POLYLINE, SOLID, TRACE에 대해서만 제한적으로 사용될 수 있다. 곡선을 포함하는 엔티티들은 엔티티 형태가 바뀌거나 여러개의 직선구간으로 분리해야하는등 몇가지 어려움이 있음으로 구현하지 않겠다. 그러나, 구현이 전혀 불가능한 것은 아니니 직접 제작해 보기 바란다.

7.2 상세 설계

1) 엔티티 종류에 따른 EXPLODE 수행 (ent-explode)

원래 EXPLODE 명령은 엔티티들중 DIMENSION, INSERT, POLYLINE에 대해 작업을 수행할 수 있다. 따라서, DIMENSION, POLYLINE에 대해서는 원래 명령을 그대로 사용하기로 하고 INSERT에 대해서만 새로운 처리 과정을 수행하도록 한다. 엔티티의 형태를 얻는 방법은 아래 예를 참조바랍니다.

Command: LINE
From point: 0,0
To point: 2,2
To point:
Command: (cdr (assoc 0 (entget (car (entsel)))))
Select object: 1,1
"LINE"

2) 블럭에 대한 EXPLODE 수행 (exp-insert)

블럭의 X, Y scale과 열, 행의 수, LAYER 이름을 구한다. 이 경우에도 위와 마찬가지로 X, Y, scale이 모두 같고, MINSERT 된 것이 아니면 원래 EXPLODE 명령을 그래도 사용하게 된다. 그런 경우가 아니면, 나머지 추가적인 BLOCK에 관한 정보를 구한다.

Command: BLOCK
Block name (or ?): TEST
Insertion base point: 0,0
Select objects: L
1 found
Select objects:
Command: MINSERT
Block name (or ?): TEST
Insertion point: 0,0
X scale factor <1>/Corner/XYZ: 2
Y scale factor (default=X): 3
Rotation <0>: 15
Number of rows (---) <1>: 4
Number of columns (|||) <1>: 5
Unit cell or distance between rows (---): 6
Distance between columns (|||): 8
Command: (entget (car (entsel)))
Select object: 0,0
((-1 , <Entity name: 60000044>)
 (0 . "INSERT")
 (8 . "0")
 (2 . "TEST") <= 블럭 이름
 (10 0.0 0.0 0.0) <= 삽입 위치
 (41 . 2.0) <= X scale
 (42 . 3.0) <= Y scale
 (50 . 0.261799) <= 회전각
 (43 . 2.0) <= Z scale
 (70 . 5) <= 열의 수
 (71 . 4) <= 행의 수
 (44 . 8.0) <= 열 간격
 (45 . 6.0) <= 행 간격
 (210 0.0 0.0 1.0))
Command: (tblsearch "BLOCK" "TEST")
((0 . "BLOCK")
 (2 . "TEST") <= 블럭 이름
 (70 . 64) <= 블럭이 사용이라는 뜻의 형태 flag
 (10 0.0 0.0 0.0) <= 삽입 위치
 (-2 . <Entity name: 400009e5>)) <= 블럭의 시작 엔티티 이름

3) 블럭의 정보를 통한 엔티티 분리 (exp-block)

위에서 확인한 바와 같이 해당 BLOCK의 정보의 끝에는 엔티티 이름이 들어있는데 이것을 이용하면 BLOCK 내에 어떤 엔티티들이 포함되어있는가를 알 수 있다.

Command: (setq en (cdr (assoc -2 (tblsearch "BLOCK" "TEST"))))
<Entity name: 400009e5>
Command: (entget en)
((-1 . <Entity name: 400009e5>) (0 . "LINE") (8 . "0")
 (10 0.0 0.0 0.0) (11 2.0 2.0 0.0) (210 0.0 0.0 1.0))
Command: (setq en (entnext en))
nil <= 더 이상 BLOCK에 포함된 entity가 존재하지 않는다는 뜻

위의 과정을 통해 얻어낸 엔티티 중 3DFACE, INSERT, LINE, POINT, POLYLINE, SEQEND, SOLID, TRACE, VERTEX에 대해서만 삽입될 때의 X, Y scale에 따른 좌표변환 작업을 수행하도록 하겠다. 그 중 POLYLINE과 SEQEND 같이 기하학적인 자료를 갖지 않는 엔티티 자료와 INSERT의 경우를 제외하면 모두 10, 11, 12, 13 필드만을 사용한다. 아래를 보자.

  10 11 12 13
3DFACE * * * *
LINE * *    
POINT *      
SOLID * * * *
TRACE * *    
VERTEX *      

위의 자료를 잘 분석해 보면 각 엔티티들을 처리하는 함수를 따로 따로 작성할 필요가 없음을 알 수 있다. 즉, 좌표점이 1, 2, 그리고 4개인 경우에 대한 처리 함수만을 작성하면 되겠다.

그리고, 분리할 수 없는 엔티티가 블럭내에 존재하는 경우에는 에러를 발생시키고 작업을 계속 수행한 후 일반적인 EXPLODE 명령에서처럼 원래 블럭을 도면상에서 완전히 삭제하지 않고 그대로 둔다.

4) 엔티티 데이타의 좌표 변환 (calc-xpoint, subst-point, point?-exp)

먼저, scaling, 그 다음으로 아래에 있는 익히 잘 알고 있을 2차원 회전변환 공식을 사용하고, 마지막으로 translation을 통해 엔티티의 좌표점을 좌표변환하게 된다. 이번 예제에서는 이렇게 얻은 좌표점을 AutoCAD 명령에 직접사용해서 엔티티를 재생성하는 방법을 사용하지 않고, ENTMAKE 함수를 사용하여 보다 빠르게 엔티티를 생성하였다. 사실, ENTMAKE 함수를 사용하지 않으면 엔티티의 선형태나 레이어 설정등을 각각 다른 AutoCAD 명령을 사용하여 수행하게 되므로 프로그램도 복잡해지게 된다.

new_x = old_x * cos(ang) - old_y * sin(ang)
new_y = old_x * sin(ang) + old_y * cos(ang)

그리고, BLOCK 속에 내포된 BLOCK의 경우에는 삽입 위치와 X, Y scale, 행, 열의 간격 데이타를 변환한 후 BLOCK 형태 그대로 삽입한다 (INSERT-EXP 함수 참조).

5) 새로 생성된 엔티티들을 하나의 selection-set으로 만든다.(pick-entity)

이 기능은 EXPLODE 이후에 분리된 엔티티들을 한꺼번에 조작하기 위해서 또는 MINSERT 된 BLOCK을 분리시킨 후에 ARRAY 하기 위해 사용된다. 이 기능의 구현 과정을 살펴보면 먼저, 모든 작업에 우선해서 현재 가장 마지막으로 생성된 엔티티의 이름을 보관해 두었다가 해당 작업이 끝난 시점에서 저장해둔 엔티티 이후로 생성된 모든 엔티티의 이름을 조사해서 하나씩 새로 만든 selection-set에 추가하게 된다. 이 기법은 다른 프로그램에서도 유용하게 쓰일 수 있는 기법이므로 잘 익혀두기 바란다.


그림 1. 예제 블럭 정의


그림 2. X, Y 스케일이 다르게 INSERT된 상태


그림 3. EXPLODE된 후 (ARC와 CIRCLE은 EXPLODE되지 않았다.)


그림 4. MINSERT된 상태


그림 5. EXPLODE된 후



관련 자료
disk [1] MEXPLODE.LSP : X, Y 비율이 다른 BLOCK을 EXPLODE하는 프로그램

Last updated 2002-09-06 by choi@moon-sun.com
This page has been accessed : Counter times.
Home