ARX119의 BIM/CAD 연구소

arx119.egloos.com

포토로그 방명록 업그레이드/기능 요청



Layer Walk++ 제작과정 (2) Layer walk ++ (dotnet)

안녕하세요.....

(그림 1-1 : TrueView2011에서 동작모습)


많이 기다려셨는지 모르겠네요. Layer walk++ 두번째 글을 날려먹은 후에 다시 쓰기까지 시간이 걸렸네요.

틈틈히 글을 채워간다는 것이 이렇게 힘든지 몰랐네요...

우선 지난시간에는 간단하게나마 개발 환경적인 내용을 다뤘구요...

이번 시간에는 AutoCAD 닷넷의 API를 직접 다뤄보도록 하겠습니다.

많은 분들이 개발자들은 머릿속에 모든 코드를 넣어놓고 일한다고 생각들을

하시는것 같습니다. 하지만 실상은 그렇지 않는것 같습니다.

다만 방법을 경험해봤다는게 제일큰 차이점 인것 같습니다.

제가 이런말씀을 드리는 이유는 어려울것이 없다는 겁니다.

"모르면 배워가면서 구현하면 되지요"

이번 시간의 주요 키(?)는 레이어 입니다.

따라서 오토캐드의 레이어관련 지식이 있어야 합니다. 다행이도

이글을 읽으신는 분들은 직/간접으로 캐드를 접하시는 분이라 생각이 듭니다.

그러면 가장 어려운 지식 습득 단계를 넘으셨습니다.

오토캐드에서 레이어를 켜거나 끄려면 "Layer"란 명령을 실행하죠.

레이어의 정보는 도면마다 다르다는것을 알고 계실겁니다.

API를 이용해서 레이어의 정보를 접근하시려면 제일먼저 현재 활성된 도면을 알아야 할것입니다.

그것을 알려주는 API가 어디서 찾아야 할까요?  ApplicationServices 쪽에 있습니다.

ApplicationServices는 오토캐드 응용프로그램의 정보또는 상태를 알아보는 API를 모아놓은 것 입니다.

앞시간에 말씀드렸듯이 API를 찾으실땐(기억이 가물가물하시면) 무조건 Autodesk를 치시라고 했습니다.

Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MDIActiveDocument

인텔리센스 기능의 도움을 받으시면 거침없이 찾으실수 있으실 겁니다. (안된다구요? 그러시면 이것만은 외우세야 합니다.)

그러면 레이어의 정보에 접근하는 방법을 살펴보겠습니다.

레이어는 오토캐드의 자료구조 구성으로 봤으때 심볼테이블(SymbolTable)로 되어있습니다.

어떻게 SymbolTable인지 어떻게 아냐구요? 그러시다면 AutoCAD 닷넷 API를 보시면 잘 구성된 다이어그램을 통해서

확인하실수 있습니다. (http://docs.autodesk.com/ACD/2010/ENU/AutoCAD%20.NET%20Developer's%20Guide/index.html)

모든 프로그램에서 그렇듯 정보를 관리하는 방법이 있고 각기 나름대로 철학을 가지고 있습니다.

오토캐드의 자료구조를 구분해 본다면, 크게 SymbolTable , SymbolTableRecord, Dictionary, Extention Dictionary으로 구분할수 있습니다. (좀더 자세한 설명은 acad_mdg.chm 파일을 통해서 알아볼수 있습니다.)



레이어들의 정보는 레이어 테이블에 보관이 되어있고 , 개별 레이어 정보는 레이어 테이블 레코드라는 곳에서 얻어올수 있습니다.

레이어 테이블은 오토캐드 Database(DWG) 가 생성될때 반드시 만들어지게 되어 있습니다. 물론 0의 레이어도 기본적으로

생성을 합니다.

단계 1 : 현재도면에서 레이어 테이블의 아이디를 찾으세요.

// 현재문서의 DWG(데이타베이스)를 얻어옵니다.
Autodesk.ApplicationServices.Document curDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MDIActiveDocument;
Autodesk.AutoCAD.DatabaseServices.Database db = curDoc.Database;

// DWG(데이타베이스)로 부터 레이어테이블 정보를 얻어옵니다.
Autodesk.AutoCAD.Database.ObjectId layerTableId = db.LayerTableId;

단계 2 : 네임스페이스를 사용하여 코드를 보기좋게 정리하세요.

너무 길어서 보기가 싫다구요... 그럼 정리들어갑니다.

namespace Autodesk.AutoCAD.ApplicationServiecs;
namespace Autodesk.AutoCAD.DatabaseServices;

Document curDoc = Application.DocumentManager.MDIActiveDocument;
Database db = curDoc.Database;

여기서 Application은 다른 닷넷 API에서도 볼수있는 이름이므로 같은 네임스페이스로 인한 컴파일 오류가 뜰수가 있습니다.

namespace Autodesk.AutoCAD.ApplicationServiecs;
namespace Autodesk.AutoCAD.DatabaseServices;
namespace AcadApp = Autodesk.AutoCAD.ApplicationServiecs.Application;

Document curDoc = AcadApp.DocumentManager.MDIActiveDocument;
Database db = curDoc.Database;

이렇게 하시면 더욱 좋습니다....

단계 3 : 레이어테이블 레코드를 얻어오세요.

현재 도면에서 Database와 레이어테이블 아이디를 얻어오는 방법을 살펴보았습니다.

다음에는 레이어 테이블 객체(LayerTable)와 레코드(LayerTableRecord) 객체를 얻어오겠습니다.

앞서서, 오토캐드 닷넷 API도 그렇듯이 바로 테이블의 위치를 가져오지 않고 아이디를 얻어와야 합니다.

주의 : 바로 얻어오면 좋은텐데 번거롭게 아이디를 얻어와야 하는지 생각하시는 분들이 계실것 같아서 말씀드립니다.

아이디를 얻어오는 가장 큰 장점은  코드의 안정성입니다. 예를 들어 객체의 포인터를 직접관리하게 된다면 객체의 수정또는

삭제되었을때 오류를 발생할 경우가 빈번해집니다. 특히 캐드 프로그램의 특징이 중간중간 캐드시스템으로 부터

일정 작업의 결과를 통보받고 이를 대응해 나가는데, 장시간의 수행시 이로인한 오류를 접하게 됩니다
.

따라서 꼭, 그리고 반드시, 아이디로 관리해 주시길... 위의 이유로 닷넷API에서는 직접 객체의 포인터를 제공하지 않고

Transaction 이라는 클래스를 통해서 아이디의 객체포인터를 얻을수 있도록 해줍니다.

ID -> Transaction -> Object

오토캐드 닷넷 API를 살펴보시면 Database의 LayerTableId 라는 프로퍼티를 통해서 현재 도면의 레이어 테이블 아이디를

제공하고 있습니다.

Database db = document.Database
ObjectId lyrId = db.LayerTableId;

아이디만을 얻어올경우라면 위의 루틴으로 가능하지만 , 아이디의 객체 정보를 얻어올 경우라면 Transaction을 사용하여

Database db = document.Database
Transactiontr = db.TransactionManager.StartTransaction();
using (tr)
{   
     ObjectId lyrId = db.LayerTableId;
     LayerTable lt = tr.GetObject(lyrId,OpenMode.ForRead) as LayerTable;
}

위와 같이 레이어 테이블 객체를 얻어올수 있습니다.

트랜젝션에 대해서 자세한 설명을 원하시면 웹에서 검색하시면 좋은 자료를 얻으실수 있을겁니다.

Transaction은 작업의 한 단위입니다.  

1. 원자성(atomicity) : transaction은 전부, 전무의 실행만이 있지  일부 실행으로 transaction의 기능을 가질 수는 없다.

2. 일관성(consistency) : transaction이 그 실행을 성공적으로 완료하면 언제나 일관된 데이터베이스 상태로 된다 라는 의미입니다.
3. 격리성(isolation) : 연산의 중간결과에 다른 transaction이나 작업이 접근할 수 없다라는 의미입니다.

4. 영속성(durability) : transaction의 일단 그 실행을 성공적으로 끝내면 그 결과를 어떠한 경우에라도 보장받는다 라는 의미입니다.
"
뭐, 거두 절미하고 귀납법적으로 설명을 드리면, 잘못된 DB의 조작으로 인해 자료를 소실하지 않고 안전하게 Database에 반영하는 기능 입니다.

전체적인 함수의 모습은 다음과 같습니다.

  //도면으로 부터 현재 레이어 상태를 얻어온다.
  public void GetLayerStatusFormDwg()
  {
   Database db = curDoc.Database; 
   Transactiontr = db.TransactionManager.StartTransaction();
   using (tr)
   {
    try
    {   
     ObjectId lyrId = db.LayerTableId;
     LayerTable lt = tr.GetObject(lyrId,OpenMode.ForRead) as LayerTable;
     SymbolTableEnumerator iterator = lt.GetEnumerator();
     while(iterator.MoveNext())
     {
      ObjectId ltrId = (ObjectId)iterator.Current;
      LayerTableRecord layerTableRecord = (LayerTableRecord)tr.GetObject(ltrId,OpenMode.ForRead);
      string name = layerTableRecord.Name;
      bool isOff = layerTableRecord.IsOff;
     }
    }
    catch(System.Exception ex)
    {
     curDoc.Editor.WriteMessage(ex.Message);
    }
   }
  }



아래에 보시면 layerwalk++ 프로젝트 소스를 다운받으실 수 있습니다.

먼저 소스를 쭉 살펴보시면 다음번에 설명드릴 내용을 충분히 이해하실거라 생각이 듭니다.

그리고 아래의 프로젝트는 정상적인 사용을 위해 만들어 놓은것이 아니므로 오류가 발생될 수 있습니다.

테스트 용으로 보시면 좋을 것 같습니다. AutoCAD R(LT) 2007~2011 에서 동작 합니다.
(이외 버전에서는 오류발생될수 있습니다.)

관련 유틸을 만들어 보시고 싶으신 분들은 완성도를 높여서 만들어 보세요...^^;

LayWalk++ Project source Download : LayWalk.zip

LayWalk++ Dotnet DLL Download : LayWalk_plusplus.zip

LayWalk++ Dotnet DLL Download (2013) : LayWalk2013.zip

오토캐드에서 테스트 하실때에는 netload -> 파일선택 하세요.

(LT와 TrueView에서 테스트 해보실 분들은 별도로 댓글 남겨주세요)

전문강사의 실력이 아니라서 이해를 하셨는지 궁금하네요.

다음시간에는 프로퍼티 도킹 다이얼로그 생성과 이벤트 를 가지고서 설명드리겠습니다.

즐거운 하루되세요...


덧글

  • 껌나무 2012/11/11 18:50 # 삭제 답글

    autocad lt 에서는 netload명령이 안되는 데 어떻게 로드 하나요?
  • arx119 2012/11/12 08:50 #

    LT에서는 dotnet프로그램을 netload로 로딩하실수 없습니다.

    만약사용하시는 o.s. 와 autocad의 버전을 알려주시면

    사용할 수 있도록 레지스트파일을 보내드리겠습니다.

    (메일주소를 비밀글로 알려주세요)
  • kw 2014/05/13 00:14 # 삭제 답글

    오... 정말 큰도움 되엇습니다. 감사합니다.
  • VBMan 2015/06/22 09:34 # 삭제 답글


    Windows7 & autocad 2014 lt 에서는 netload명령어 사용하고 싶습니다.
    방법 좀 알려주세요.? ^^
  • arx119 2015/06/22 11:41 #

    LT제품은 netload 함수를 사용할수없습니다.
    설령 dll을 LT로 로드시킨다해도 명령관련된
    api를 사용할수없습니다. idwgbar처럼 동작하지
    않는api를 피해서 dll을 만들고 레지스트리에 등록해서
    로딩시키면일부기능을 동작시킬수 있습니다.
    즐거운 하루되세요^^
댓글 입력 영역



구글번역

통계 위젯 (화이트)

3114
575
556899

국가접속Flag

free counters