ObjectARX 강좌

[ObjectARX] 3. Entity

matesoft 2026. 3. 21. 22:37
반응형

개요

일반적으로 오토캐드에서 우리들이 엔티티라고 하는 것에는 Polyline, Line, Circle, Arc, Text, Solid , Region, Spline, Ellipse 등이 있다. 오토캐드 사용자들은 에티티를 모니터 화면상으로 볼 수 있고 그것들을 조작 할 수 있다. 오토캐드에서 사용하는 엔티티들은 AcDbEntity라는 클래스에서 상속을 받아(그래픽 객체인 경우) 정의 되어 있다. 엔티티들은 자신의 오브젝트가 각각의 데이터를 가지고 있지만, 예외적으로 관련된 다른 오브젝트가 데이터를 가지고 있는 경우가 있다.

몇 가지 엔티티를 제외한 모든 엔티티들은 필요한 기하학적인 포함하고 있다. 몇몇 엔티티들은 기하학적인 정보 뿐만 아니라 속성도 포함하고 있다. 그리고 여러 개의 복잡한 오브젝트로 구성된 Complex Entity는 다음과 같은 것들이 있다.

 

■ AcDb2dPolyline : AcDb2dPolylineVertex 객체를 소유한다.

■ AcDb3dPolyline : AcDb3dPolylineVertex 객체를 소유한다.

■ AcDbPolygonmesh : AcDbPolygonMeshVertex 객체를 소유한다.

■ AcDbPolyFacemesh : AcDbPolyFaceMeshVertex 객체를 소유한다.

■ AcDbBlockReference : AcDbAttribute 객체를 소유한다.

■ AcDbMInsertBlock : AcDbAttribute 객체를 소유한다.

 

일반적으로 오토캐드 데이터베이스에 있는 엔티티들은 AcDbBlockTableRecord에 속해 있다. 새롭게 생성되는 모든 블록 테이블에는 항상 두 개의 미리 정의된 레코드가 존재 한다. *MODEL_SPACE와 *PAPER_SPACE는 사용자가 오토캐드의 Model Space나 Paer Space에서 작업한 엔티티들을 저장한다. AcDbEntity의 Ownership 계층도는 그림과 같다.

일반적인 엔티티의 특성

일반적으로 엔티티는 다수의 공통적인 속성을 가지고 있고, 각 엔티티 클래스에는 그것들의 값을 얻어 오거나 설정하는 여러 개의 멤버 함수들이 존재한다. 보통 엔티티를 새롭게 생성하여 블록 테이블 레코드에 추가할 때 오토캐드는 자동적으로 기본 속성값으로 설정하여 추가한다. 이때 사용되는 함수는 AcDbEntity::setDatabaseDefaults(); 이다. 오토캐드 사용자가 명령어 라인에서 속성 값을 입력하여 바꿀 수 있는 속성으로는 Color, LineType, LineType Scale, Visibiltiy, Layer 등이 있다.

공통적인 엔티티 조작 함수들

AcDbEntity 클래스에서 상소받은 엔티티들은 많은 공통 함수를 가진다. 아래의 함수 리스트는 입반적으로 많이 사용되는 함수들 이다.

함수명 함수 설명
intersectWith 오토캐드의Trim, Extend, Fillet, Chamfer, Break 명령등에 Object Snap 교차점을 찾는데사용한다.
transformBy 객체의 좌표점을 이동시키거나 또는 크기를 변화 시키거나 회전시키기 위한 변환 행렬의형 태로 넘겨 주는데 사용한다.
getTransformedCopy 객체를 변환행렬을 사용하여 새로운 위치에 새로운 엔티티를 생성할 때사용 한다.
getOsnapPoints 스냅포인트좌표를리턴해준다.
getGripPoints 그립포인트(Grip Point) 좌표를리턴해 준다. 여기서그립포인트는Stretch Point의Superset이다.
moveStretchPoints 지정된 좌표점을이동 시키기 위해 오토캐드의 STRETCH 명령어에 의해 사용된다.
moveGripPointsAt 지정된 좌표점을 이동시키기 위해 오토캐드의 Grip 편집 기능에 의해 사용된다.
worldDraw 엔티티에 대해 뷰에 독립적인 기하학적인 표현을 생성하는데 사용된다.
viewportDraw 엔티티에 대해 뷰에의존적인 기하학적인 표현을 생성하는데 사용된다.
draw( ) 오토캐드 화면에 엔티티를 그려준다.
list( ) 오토캐드의 LIST 명령어에 의해 사용된다.
getGeomExtents( ) 사용자 엔티티의 3D 범위를포함하는 박스의 구석점을 리턴 해준다.
explode( ) 엔티티를 가장 작은 단위의 요소로 분해 해준다.
getSubentPathsAtGsMarker( ) 주어진 GS Marker에 해당하는Subentity Path를 리턴 해준다.
getGsMarkersAtSubentPath( ) 주어진 Subentity Path에 해당하는GS Marker를 리턴 해준다.
subentPtr( ) 주어진 Subentity Path에해당하는포인터를 리턴 해준다.
ighlight( ) 지정된 Subentity를 하이라이트 해준다.

 

이번에는 엔티티간의 교차점을 구하는 방법에 대해 알아본다. 예전에 LISP이나 ADS 환경에서 프로그램을 개발 할 때는 이런 엔티티간의 교차점을 계산하는 함수들을 직접 프로그래머가 개발을 해야 했기 때문에 상당히 어려움이 있었다. 하지만 ObjectARX에서는 엔티티간의 교차점을 구하는 함수들을 다수 제공 해주기 때문에 이런 문제는 쉽게 해결을 할 수 있게 되었다. 교차점 유형은 4가지가 있다.

교차점 유형 설명
kOnBothOperands 엔티티를 연장하지 않고 교차점을 계산한다.
kExtendThis ‘this’엔티티를 연장하여 교차점을 계산한다.  아래에서 Line1을 연장하여 Line2나 Line3와의 교차점을 계산한다.
kExtendArg Line2나 Line3를 연장하여 교차점을 계산한다. 아래 그림에서 Line1은 연장하지 않는다.
kExtendBoth ‘this’엔티티와 교차점을 계산하려고 하는 엔티티를 모두 연장하여 교차점을 계산한다

아래의 함수는 현재 엔티티간의 교차점을 구해주는 함수들이다.

virtual  Acad::ErrorStatus 
intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType, 
    AcGePoint3dArray& points,
    int thisGsMarker = 0, 
    int otherGsMarker = 0) const;
 
virtual  Acad::ErrorStatus 
intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType, 
    const AcGePlane& projPlane,
    AcGePoint3dArray& points, 
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;

 

위 함수에 대한 증명은 다음 글을 참조 한다.

직선의 벡터 방정식

https://matesoft.tistory.com/6

반응형

GS Markers와 Subentity

GS Marker는 엔티티가 자신을 표현하기 위해서 사용하는 그래픽 심볼이다. 모든 엔티티는 자신을 그리기 위해 AcGi 라이브러리에 포함된 폴리라인, 원, 호와 같은 그래픽 기본 요소를 호출한다. AcDbEntity에서 파생된 모든 클래스는 자신을 그리는데 사용하는 표시 벡터에 그래픽 시스템(GS) 마커를 연결할 수 있다. 각 엔티티 하위 클래스는 GS 마커를 삽입할 위치를 제어한다. 사용자가 엔티티를 선택하면 GS 마커를 사용하여 선택된 엔티티의 부분을 식별 할 수 있다.

AcDb3dSolid에서 파생된 솔리드는 정점, 모서리 및 면으로 구성된다. 이러한 각 요소는 GS 마커로 식별할 수 있다. 엔티티 클래스 생성자는 엔티티에 가장 적합한 위치를 고려하여 GS 마커를 삽입할 위치를 결정한다. 예를 들어 상자는 상자를 그리는 데 사용된 각 선에 대해 GS 마커를 생성한다. 원기둥은 윗면, 아랫면 및 바깥쪽 면에 각각 하나씩, 총 세 개의 GS 마커를 생성한다.

 

예를 들어, AcDb3dSolid는 Vertex, Edge, Face등으로 구성되어 있다. 각 요소들은 Subentity로 등록하면 객체를 Iterating 할 때 GS Marker를 통해 빠르게 탐색할 수 있게 된다.

ObjectARX에서 제공하는 getSubentPathsAtGsMarker( ) 함수를 사용한 특별한 GS Marker를 사용하여 GS Marker와 연관있는 Subentity를 알아낼 수 있다. Subentity Path는 AcDbFullSubentPath 클래스에 Object ID와 Subentity ID로 구성되어 있다.

엔티티 분해(Explode)

몇몇 엔티티들은 가장 작은 요소로 분해될 수 있다. 예를 들면, Box 엔티티는 Region, Line 등으로 분해되고, Polyline 엔티티는 Line으로 분해 된다. AcDbEntity에서 상속받은 (그래픽 객체) 객체들은 기본적으로 Explode overriding 객체를 지원한다.

Attribute

오토캐드 블럭은 블럭 테이블 레코드에 저장된 엔티티들의 모음이다. 각 블럭은 AcDbBlockBegin 객체, 하나 이상의 AcDbEntity 객체, 그리고 AcDbBlockEnd 객체로 구성된다.

블럭에슨 속성 정의가 포함될 수 있으며, 실무에서는 속성 편집을 통해 도면의 정보를 변경시킬 때 사용한다. 블럭에는 속성 정의가 포함될 수 있고 속성은 정보 텍스트이다.

다음 예제는 ASDK-BLOCK-WITH-ATTR이라는 이름의 새 블럭 테이블 레코드를 생성하고 블럭 테이블에 추가한다. 그런 다음 원형 엔티티를 생성하여 새 블럭 테이블 레코드에 추가한다. 그리고 두 개의 속성 정의 엔티티(두 번째는 첫 번째의 복제본)를 생성하여 동일한 블럭 테이블 레코드에 추가한다.

void defineBlockWithAttributes(
    AcDbObjectId& blockId, // This is a returned value.
    const AcGePoint3d& basePoint,
    double textHeight,
    double textAngle)
{
    int retCode = 0;
    AcDbBlockTable *pBlockTable = NULL;
    AcDbBlockTableRecord* pBlockRecord = new AcDbBlockTableRecord;
    AcDbObjectId entityId;
    // Step 1: Set the block name and base point of the 
    // block definition.
    //
    pBlockRecord->setName("ASDK-BLOCK-WITH-ATTR");
    pBlockRecord->setOrigin(basePoint);
    // Open the block table for write.
    //
    acdbHostApplicationServices()->workingDatabase()
        ->getSymbolTable(pBlockTable, AcDb::kForWrite);
    // Step 2: Add the block table record to block table.
    //
    pBlockTable->add(blockId, pBlockRecord);
    // Step 3: Create a circle entity.
    //
    AcDbCircle *pCircle = new AcDbCircle;
    pCircle->setCenter(basePoint);
    pCircle->setRadius(textHeight * 4.0);
    pCircle->setColorIndex(3);
    // Append the circle entity to the block record.
    //
    pBlockRecord->appendAcDbEntity(entityId, pCircle);
    pCircle->close();
    // Step 4: Create an attribute definition entity.
    //
    AcDbAttributeDefinition *pAttdef
        = new AcDbAttributeDefinition;
    // Set the attribute definition values.
    //
    pAttdef->setPosition(basePoint);
    pAttdef->setHeight(textHeight);
    pAttdef->setRotation(textAngle);
    // For horizontal modes other than AcDb::kTextLeft
    // and vertical modes other than AcDb::kTextBase,
    // you may need to call setAlignmentPoint(). See the
    // AcDbText::setAlignmentPoint() documentation for details.
    pAttdef->setHorizontalMode(AcDb::kTextLeft);
    pAttdef->setVerticalMode(AcDb::kTextBase);
    pAttdef->setPrompt("Prompt");
    pAttdef->setTextString("DEFAULT");
    pAttdef->setTag("Tag");
    pAttdef->setInvisible(Adesk::kFalse);
    pAttdef->setVerifiable(Adesk::kFalse);
    pAttdef->setPreset(Adesk::kFalse);
    pAttdef->setConstant(Adesk::kFalse);
    pAttdef->setFieldLength(25);
    // Append the attribute definition to the block.
    //
    pBlockRecord->appendAcDbEntity(entityId, pAttdef);
    // The second attribute definition is a little easier
    // because we are cloning the first one.
    //
    AcDbAttributeDefinition *pAttdef2
        = AcDbAttributeDefinition::cast(pAttdef->clone());
    // Set the values that are specific to the
    // second attribute definition.
    //
    AcGePoint3d tempPt(basePoint);
    tempPt.y -= pAttdef2->height();
    pAttdef2->setPosition(tempPt);
    pAttdef2->setColorIndex(1); // Red
    pAttdef2->setConstant(Adesk::kTrue);
    // Append the second attribute definition to the block.
    //
    pBlockRecord->appendAcDbEntity(entityId, pAttdef2);
    pAttdef->close();
    pAttdef2->close();
    pBlockRecord->close();
    pBlockTable->close();
    return;
}
반응형

'ObjectARX 강좌' 카테고리의 다른 글

[ObjectARX] 6. Dictionary  (0) 2026.03.27
[ObjectARX] 5. GS Marker  (0) 2026.03.23
[ObjectARX] 4. Symbol Table  (0) 2026.03.22
[ObjectARX] 2. Database  (0) 2026.03.19
[ObjectARX] 1. ObjectARX 소개  (2) 2026.03.18