Graphisoft®

API Development KitVersion: 18

요소 개요

 

API_ElemTypeID structure에 적용 가능한 타입의 요소들이 열거되어 있습니다. 요소의 정의는 모든 요소 타입의 union인 API_Element structure에 설명되어 있습니다. 모든 정의는 API_Elem_Head라는 공통 헤더 structure로 시작합니다.

특정 타입의 요소(API_WallType, API_LineType 등)를 설명하는 모든 structure는 논리적으로 다른 부분들로 분리되어 있습니다.

많은 요소 관련 함수들은 파라미터 목록의 API_Element structure를 사용합니다. 일반적으로 union에 있는 필수 필드를 채워야 합니다. ArchiCAD는 값들을 기반으로 요청을 parse하고, 동일한 structure에서 리턴 파라미터들을 전달합니다. 이것은 대부분의 함수들이 프로토타입에 const 지시어를 갖고 있지 않은 이유입니다.


데이터베이스에서 요소 가져오기

API 11부터 우리는 typeID/index 식별에서 GUID-기반 식별으로 이동하기 시작한다는 점에 유의하십시오. API 12에서는 GUID 방식이 우선입니다. API 18에서는 GUID 방법만 사용 가능하며, typeID/index 식별이 제거되었습니다.

간단한 예제를 보겠습니다. 당신이 데이터베이스의 지정된 요소의 데이터를 가져오는 데 관심이 있다고 가정하겠습니다. 이 경우 API_Element 타입의 변수를 사용해야 합니다.

API_Element  element;
GSErrCode    err;

BNZeroMemory (&element, sizeof (API_Element));
element.header.guid = GSGuid2APIGuid (GS::Guid ("EF7A21F7-F841-4030-B6DC-C1DC8DA2F1E6"));

err = ACAPI_Element_Get (&element);

union의 element.wall 파트에 벽의 데이터가 리턴됩니다. 반환된 헤더의 hasMemo 필드를 확인해야 합니다. 만약 이것이 설정되면 게이블 및 폴리곤 노드와 같은 요소에 대해 추가 데이터를 사용할 수 있다는 정보가 표시됩니다. 이 데이터를 생성하는 것은 비교적 긴 변환 프로세스일 수 있기 때문에, 이 정보는 추가적인 함수 호출로 얻을 수 있습니다.

GSErrCode       err;
API_ElementMemo memo;

err = ACAPI_Element_GetMemo (element.header.guid, &memo, APIMemoMask_All);

이 경우 특정 요소와 관련된 추가 데이터를 모두 확보했습니다. 메모 structure는 여러 개의 핸들과 포인터(동적 메모리)를 모은 것입니다. 만약 무엇인가가 할당되면 즉, 값이 NULL이 아닌 경우 데이터를 포함합니다. 더 이상 데이터가 필요하지 않은 경우 할당된 메모리 블록을 해제해야 합니다. 제안된 방법은 다음과 같습니다:

ACAPI_DisposeElemMemoHdls (&memo);

만약 당신이 이 함수를 사용하면 모든 동적 데이터가 자유로워질 수 있으며, 당신의 애드온이 좀 더 나중 버전의 ArchiCAD에 설치되더라도 호환성 문제가 발생하지 않습니다.

API 함수들에 의해 반환된 오류 코드들을 조사하고 반환된 값을 해석하는 것이 매우 중요합니다.

데이터베이스에서 특정 타입의 요소의 인스턴스들을 살펴보는 것이 일반적입니다. 다음 예제는 다음과 같은 좋은 템플릿을 제공합니다:  12

GS::Array<API_Guid> elemList;
GSErrCode err = ACAPI_Element_GetElemList (API_WallID, &elemList);
for (Int32 i = 0; i < elemList.GetSize () && err == NoError; ++i) {
    API_Element element;
    BNZeroMemory (&element, sizeof (API_Element));
    element.header.guid = elemList[i];
    if (ACAPI_Element_Get (&element) == NoError) {
        /* 당신이 하고자 하는 것 */
    }
}

이러한 루프를 설정하는 더 나은 방법을 활용하려면 API의 요소 필터 서비스를 사용해야 합니다. 또한, 활성 층에만 있거나 가시적인 레이어에 있거나 편집 가능한 요소에만 관심이 있는 요소 등이 일반적입니다. ACAPI_Element_Get 함수를 루프로 호출하면, ArchiCAD는 필요하지 않더라도 모든 요소를 API 형식으로 변환하도록 요청 받습니다. 이 알고리즘은 매우 느릴 수 있습니다.

다음 예에서는 오직 당신이 관심 있는 요소들을 얻기 위한 매우 효과적이고 빠른 방법을 볼 수 있습니다:  12

GS::Array<API_Guid> elemList;
ACAPI_Element_GetElemList (API_WallID, &elemList, APIFilt_OnActFloor);
for (GS::Array<API_Guid>::ConstIterator it = elemList.Enumerate (); it != NULL; ++it) {
    API_Element element;
    BNZeroMemory (&element, sizeof (API_Element));
    element.header.guid = *it;
    if (ACAPI_Element_Get (&element) == NoError) {
        /* 당신이 하고자 하는 것 */
    }
}

당신은 이제 APIERR_DELETED 리턴 코드가 확인되지 않은 것을 볼 수 있습니다. 모든 요소가 삭제된 요소뿐만 아니라 필요에 부합하지 않는 것을 필터링하기 때문입니다.

또한 APIDb_DrawOrderGetNextIDAPIDb_CreationOrderGetNextID 데이터베이스 함수들로 각각 그리기 순서와 생성 순서에 따라 요소들을 열거할 수도 있습니다.


요소 생성하기

요소 생성 절차도 상당히 간단합니다. API_Element의 적절한 부분을 채우고 선택적으로 API_ElementMemo structure를 채우기만 하면 됩니다. ACAPI_Element_Create 함수는 다음과 같이 작동합니다:

ArchiCAD가 당신이 할당한 동적 데이터 structure를 해제하지 않고 ArchiCAD에게 전달한다는 것이 매우 중요합니다. 그것들은 당신의 코드에 의해 해제되어야 합니다.

또 다른 중요한 참고 사항은 다음과 같습니다. 향후 호환성 때문에 당신이 채운 모든 데이터 structure는 0으로 초기화해야 합니다. filler들은 API의 나중 버전에서 사용될 수 있으므로, 만약 초기화되지 않으면 결과를 예측할 수 없습니다.

요소를 작성하는 템플릿은 다음과 같아야 합니다:

API_Element     element;
API_ElementMemo memo;
API_Guid        wallGuid;
GSErrCode       err;

BNZeroMemory (&element, sizeof (API_Element));
BNZeroMemory (&memo, sizeof (API_ElementMemo));

element.header.typeID = API_WallID;
/* element.wall 채우기         */
/* 폴리곤 벽에 대한 memo 채우기 */

err = ACAPI_Element_Create (&element, &memo);

wallGuid = element.header.guid;

ACAPI_DisposeElemMemoHdls (&memo);

많은 요소들이 서로를 지칭합니다. 그리고 이러한 상호 참조는 매우 쉽게 설정할 수 있습니다. ArchiCAD의 일반적인 논리를 따르기만 하면 되는데, 이는 참조된 요소들이 반드시 존재해야 한다는 것을 의미합니다. 예를 들면, 먼저 벽을 만든 다음 창을 벽에 배치하고 관련 레이블을 지정할 수도 있습니다.

API 함수들을 사용하여도 같은 작업을 해야 합니다. ACAPI_Element_Create 함수는 참조에서 사용될 수 있는 생성된 요소의 guid를 리턴합니다. 만약 당신이 생성된 벽에 창을 배치하고 레이블을 지정하려면 다음을 수행하십시오:

BNZeroMemory (&element, sizeof (API_Element));
element.header.typeID = API_WindowID;

element.window.owner = wallGuid;
/* 나머지 파라미터들을 설정합니다... */

err = ACAPI_Element_Create (&element, NULL);

BNZeroMemory (&element, sizeof (API_Element));
element.header.typeID = API_LabelID;

element.label.parentType = API_WallID;
element.label.parent     = wallGuid;
/* 나머지 파라미터들을 설정합니다... */

err = ACAPI_Element_Create (&element, NULL);

선택 제어하기

당신은 또한 활성화된 선택을 제어할 수 있습니다.

ArchiCAD에는 2가지 기본 유형의 선택 방법이 있습니다:

둘 다 API의 지원을 받고 있습니다. API_SelTypeID structure에서 활성화된 선택 방법의 가능한 값이 열거되어 있습니다. API_SelEmpty 식별자는 ArchiCAD의 현재 데이터베이스에서 선택된 것이 없음을 의미합니다. API_SelElems 식별자는 요소들이 개별적으로 선택될 때 1번째 방법에 해당합니다. 다른 값들은 선택이 어떤 종류의 marquee 모양에 의해 이루어졌다는 것을 식별합니다.

개별적으로 선택된 요소들의 경우, ArchiCAD는 선택된 모든 요소를 리턴합니다. marquee 기반 선택의 경우, marquee 영역과 교차하거나 marquee 영역 내에 있는 요소들만 리턴합니다.

요소 선택 절차가 매우 용이합니다. 개별 요소 또는 요소 그룹을 선택하려면 ACAPI_Element_Select 함수를 호출하기만 하면 됩니다. 새 선택을 열거나 실제 선택에 하나 이상의 요소를 추가할 수도 있습니다.

 


한 요소의 내부 파트들: API_Neig structure

ACAPI_Element_SelectACAPI_Selection_Get 함수는 모두 API_Neig structure를 사용합니다. 이 데이터 structure는 요소들의 내부 파트들을 구별할 수 있게 해줍니다.

요소의 노드 또는 가장자리 중 하나를 이동시키는 동안 주어진 요소의 모양을 통해 커서가 얼마나 똑똑한지 알 수 있습니다. 이 모든 점 또는 가장자리는 API_Neig structure로 설명할 수 있습니다.

예제를 봅시다. 지붕에 따르면 특별한 관심사는 3가지 하위 클래스로 구성됩니다. 그것들은 다음과 같습니다:

 

neigID

inIndex 범위

설명

APINeig_Roof

[1...n]

지붕 폴리곤의 정점 중 하나를 식별합니다. inIndex 값은 정점 배열에서 정점의 위치에 해당합니다. 점이 지붕 폴리곤의 메인 외곽에 속하면 flags의 holeSel 비트가 세트되지 않습니다.

APINeig_RoofOn

[1...n]

지붕 폴리곤의 모서리 중 하나를 식별합니다. inIndex 값은 정점 배열에서 시작 정점의 위치에 해당합니다. 모서리가 지붕 폴리곤의 서브 외곽에 속하면 flags의 holeSel 비트가 세트됩니다.

APINeig_RBL

[1...2]

지붕의 레퍼런스 라인을 식별합니다. Index 값 1과 2는 각각 그 시작점과 끝점을 의미합니다.

선택한 요소들을 검토할 때, 선택이 수행되었을 때 마우스에서 점 또는 모서리를 클릭한 정보를 얻습니다. 선택에 따른 유일한 유용한 정보는 전체 폴리곤 요소가 선택되는지 또는 그 하위 외곽 중 하나인지 여부 뿐입니다.

만약 당신이 APIdefs_Elements.h 파일에서 API_Neig structure를 검색해 보면, 여러 곳에서 사용되는 것을 볼 수 있을 것입니다.

입력 함수들에서 클릭한 점에 대한 정보를 제공하는 데 사용됩니다; APIIo_GetPointID 함수를 참조하십시오.


3D 모델  

  3D 모델에 접근하는 권장 방법은 ModelAccess 예제에 설명되어 있습니다.

실제 데이터베이스의 3D 표현은 API_Component3D structure를 통해 접근할 수 있습니다.

적용 가능한 타입의 요소들이 API_3DTypeID structure에 열거되어 있습니다. 3D 구성요소의 정의는 API_Component3D structure에 설명되어 있으며, 이는 사실 모든 구성요소 타입의 union입니다. 모든 정의는 공통 헤더 structure인 API_3D_Head로 시작합니다.

3D 모델이 API structure에 어떻게 대응하는지 이해하기 전에, GDL 참조 매뉴얼의 Primitive Elements 챕터를 주의 깊게 읽어보십시오.

특정 요소의 3D 표현은 API_BodyType structure에 기반합니다. 하나의 요소는 3차원 기하를 설명하기 위해 하나 이상의 body를 갖고 있을 수 있습니다. 일반적으로 body는 여러 정점, 모서리, 폴리곤 및 법선 벡터로 구성됩니다. 이 데이터 structure는 내부 구성요소의 수뿐만 아니라 일부 상태 비트, 표면 프로퍼티 및 글로벌 변환 행렬을 제공합니다. API_Elem_Head structure를 통해 부모 요소에 대한 참조도 얻을 수 있습니다.

3D 기하 자체는 API_PgonType, API_PedgType, API_EdgeType, API_VertType, API_VectType structure들로 설명됩니다. 이것들은 GDL 참조 매뉴얼에 문서화되어 있습니다.

3D 표현은 또한 표면 재료의 공통 풀을 소유하고 있습니다. 기하 설명의 폴리곤 인스턴스는 인덱스에 의해 이러한 재료들을 참조합니다. 하나의 표면 정의는 API_UmatType structure에 의해 설명됩니다. 표면 재료는 두 가지 출처에서 나올 수 있습니다. 재료 목록에는 3D 기하의 아무 폴리곤에서 참조하는 모든 글로벌 재료 속성이 포함되어 있습니다. 재료는 GDL 스크립트에서도 정의될 수 있습니다.

평면도의 조명 도구와 함께 배치된 요소들에는 GDL 스크립트를 통해 정의된 빛 방출이 포함될 수 있습니다. 3D 기하에 존재하는 모든 광원은 API_LghtType structure로 설명됩니다.


전체 3D 모델 가져오기  

  3D 모델에 접근하는 권장 방법은 ModelAccess 예제에 설명되어 있습니다.

만약 당신이 실제로 존재하는 전체 3D 모델에 관심이 있는 경우, 다음 템플릿을 사용해야 합니다:

API_Component3D   comp3D;
Int32             nBody, i;
GSErrCode         err;

err = ACAPI_3D_GetNum (API_BodyID, &nBody);
BNZeroMemory (&comp3D, sizeof (API_Component3D));
comp3D.header.typeID = API_BodyID;
for (i = 1; i <= nBody && err == NoError; i++) {
    comp3D.header.index = i;
    err = ACAPI_3D_GetComponent (&comp3D);
    if (err == NoError) {
        /* body를 pgon, vert 등으로 분해함... */
    }
    if (err == APIERR_DELETED)
        err = NoError;
}

다음 이유 때문에 구성요소 API_BodyType에 기반한 루프에서 알고리즘을 구성하는 것이 매우 중요합니다:

일단 body의 정의를 갖게 되면, 당신이 관심 있는 primitive들을 검토하기 위해 내부 루프를 설정할 수 있습니다. API_BodyType 레코드에서 모든 내부 구성요소의 수를 얻습니다. 인덱스는 1부터 시작해야 합니다.

빛과 재료 구성요소는 3D 모델의 글로벌(body 상대적이 아닌) 구성요소이기 때문에 자체 루프에서 얻을 수 있습니다.

실제로 존재하는 ArchiCAD의 3D 모델의 데이터를 얻는 것은 매우 중요합니다. 이 데이터는 평면도 요소들과 일치하지 않는 경우가 많습니다. 3D 창의 업데이트 메커니즘은 Preferences 다이얼로그의 스위치와 같이 많은 것에 따라 달라집니다. 일반적으로 위의 템플릿을 사용하는 경우, 3D 창에서 볼 수 있는 모델을 얻습니다.


특정 요소의 3D 표현 가져오기

또한 당신이 관심 있는 특정 평면도 요소의 3D 표현을 얻을 수 있는 가능성도 있습니다. 기본 메커니즘은 이전 예제와 동일합니다. 유일한 차이점은 body들이 주어진 요소에 속한다는 정보가 필요하다는 것입니다.

특정 평면도 요소에 할당된 body는 ACAPI_Element_Get3DInfo 함수로 얻을 수 있습니다. 이 함수는 메인 3D 데이터 컨테이너들의 인덱스 범위를 전달하기 위해 API_ElemInfo3D structure를 채웁니다.

중요한 참고: 이런 식으로 얻은 데이터는 실제로 존재하는 ArchiCAD의 3D 모델과 독립적입니다. 만약 기존 데이터가 일관성이 없는 경우, ArchiCAD는 주어진 요소를 3D로 다시 변환하여 올바른 결과를 보장합니다. 일반적으로 실제 평면도 데이터와 완전히 동기화된 모델을 얻습니다.

3D 모델을 매우 신중하게 얻으려면, 위에서 언급한 방법 중 하나를 선택해야 합니다.

일관된 데이터가 필요한 경우 관심 있는 평면도 요소들을 검토하는 루프를 설정하는 두 번째 방법을 선택해야 합니다. 이 경우 요소별로 3D 모델 요소를 얻을 수 있습니다.

당신은 종종 첫 번째 방법을 선택해야 합니다. 예를 들면, "Save As 3D" 다이얼로그에서 애드온을 호출하면 사용자가 저장하고자 하는 데이터는 실제로 3D 창에서 볼 수 있습니다.