요소 개요
API_ElemTypeID structure에 적용 가능한 타입의 요소들이 열거되어 있습니다. 요소의 정의는 모든 요소 타입의 union인 API_Element structure에 설명되어 있습니다. 모든 정의는 API_Elem_Head라는 공통 헤더 structure로 시작합니다.
typeID
필드는 요소의 타입을 식별합니다.variationID
필드는API_ObjectID
,API_LampID
,API_WindowID
,API_DoorID
의 경우,typeID
의 확장입니다. 이것은 요소의 서브 카테고리를 식별합니다. (예. Stair)guid
필드는 프로젝트의 전체 수명에 걸쳐 일정한 요소의 글로벌한 고유 식별자를 제공합니다. 이러한 값은 자동으로 생성되며 고유 ID가 할당되는 것을 제어할 방법이 없습니다.modiStamp
필드는 요소 수정 여부를 확인할 수 있는 스탬프를 제공합니다.guid
및groupGuid
필드에는 그룹화 정보가 들어 있습니다. 첫 번째는 주어진 요소가 속한 그룹을 식별합니다. 두 번째는 중첩된 그룹의 경우 루트-모그룹을 식별합니다.floorInd
필드는 요소가 속한 층을 식별합니다. (모든 요소 타입에는 적용되지 않습니다)layer
는 요소에 대해 선택된 레이어의 속성 인덱스입니다. (모든 요소 유형에는 적용되지 않습니다)hasMemo
필드는 flag이며, 주어진 요소에는 API_Element_Memo structure에 설명된 추가 데이터가 있음을 보여줍니다.drwIndex
필드는 요소의 그리기 순서를 결정하며 사용자 또는 API에서 Send to Back/Bring to Front 커맨드로로 조정할 수 있습니다.drwIndex
가 더 큰 요소는 나중에 그려지게 됩니다.
특정 타입의 요소(API_WallType, API_LineType 등)를 설명하는 모든 structure는 논리적으로 다른 부분들로 분리되어 있습니다.
- 처음 부분은 헤더입니다. 이것은 요소 타입에 독립적인 공통 정보를 포함합니다.
- 다음 부분은 Tool Setting 다이얼로그 또는 Info Box에서 설정할 수 있는 파라미터에 해당합니다. 이것들은 지오메트리에 의존하지 않고 속성, 제어 플래그 등과 같은 일반적인 파라미터들을 설명합니다.
- 마지막 부분은 요소가 평면도에 배치되는 동안 수행된 사용자 클릭에 해당합니다. 이 부분은 순수한 기하학적 설명입니다.
많은 요소 관련 함수들은 파라미터 목록의 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 함수들에 의해 반환된 오류 코드들을 조사하고 반환된 값을 해석하는 것이 매우 중요합니다.
데이터베이스에서 특정 타입의 요소의 인스턴스들을 살펴보는 것이 일반적입니다. 다음 예제는 다음과 같은 좋은 템플릿을 제공합니다:
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 형식으로 변환하도록 요청 받습니다. 이 알고리즘은 매우 느릴 수 있습니다.
다음 예에서는 오직 당신이 관심 있는 요소들을 얻기 위한 매우 효과적이고 빠른 방법을 볼 수 있습니다:
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_DrawOrderGetNextID와 APIDb_CreationOrderGetNextID 데이터베이스 함수들로 각각 그리기 순서와 생성 순서에 따라 요소들을 열거할 수도 있습니다.
요소 생성하기
요소 생성 절차도 상당히 간단합니다. API_Element의 적절한 부분을 채우고 선택적으로 API_ElementMemo structure를 채우기만 하면 됩니다. ACAPI_Element_Create 함수는 다음과 같이 작동합니다:
- 이것은 불일치 가능성이 있는 데이터를 체크합니다. 어떤 문제가 발생하면 자동으로 수정되거나(부적합한 속성 참조와 같이) 오류 코드가 생성됩니다.
- 예를 들어 헤더 structure의
guid
필드는 자동으로 생성되기 때문에 무시합니다. 이 값들은 해당 필드 안에 반환됩니다. - 생성된 요소는 데이터 structure 내에 배치됩니다.
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가지 기본 유형의 선택 방법이 있습니다:
- 선택은 개별적으로 선택된 요소들에 의해 제어될 수 있습니다.
- 또 다른 가능성은 marquee 영역에 의존하는 것입니다.
둘 다 API의 지원을 받고 있습니다. API_SelTypeID structure에서 활성화된 선택 방법의 가능한 값이 열거되어 있습니다.
API_SelEmpty
식별자는 ArchiCAD의 현재 데이터베이스에서 선택된 것이 없음을 의미합니다.
API_SelElems
식별자는 요소들이 개별적으로 선택될 때 1번째 방법에 해당합니다. 다른 값들은 선택이 어떤 종류의 marquee 모양에 의해 이루어졌다는 것을 식별합니다.
개별적으로 선택된 요소들의 경우, ArchiCAD는 선택된 모든 요소를 리턴합니다. marquee 기반 선택의 경우, marquee 영역과 교차하거나 marquee 영역 내에 있는 요소들만 리턴합니다.
요소 선택 절차가 매우 용이합니다. 개별 요소 또는 요소 그룹을 선택하려면 ACAPI_Element_Select 함수를 호출하기만 하면 됩니다. 새 선택을 열거나 실제 선택에 하나 이상의 요소를 추가할 수도 있습니다.
한 요소의 내부 파트들: API_Neig structure
ACAPI_Element_Select와 ACAPI_Selection_Get 함수는 모두 API_Neig structure를 사용합니다. 이 데이터 structure는 요소들의 내부 파트들을 구별할 수 있게 해줍니다.
요소의 노드 또는 가장자리 중 하나를 이동시키는 동안 주어진 요소의 모양을 통해 커서가 얼마나 똑똑한지 알 수 있습니다. 이 모든 점 또는 가장자리는 API_Neig structure로 설명할 수 있습니다.
neigID
필드는 요소 타입을 식별합니다. API_NeigID의 가능한 값과 API_ElemTypeID structure 사이에 대응성을 설정할 수 있습니다; 첫 번째 것은 두 번째 것의 하위 종류입니다. 변환 목적으로 APIAny_NeigToCoordID 함수를 사용합니다.guid
필드는 요소 guid입니다.inIndex
필드는 특수 점 또는 가장자리의 내부 인덱스를 식별합니다.flags
필드는 단지 정보를 제공합니다. 예를 들면 설명된 점 또는 가장자리가 다각형 요소(API_NeigFlg_HoleSel
)의 하위 윤곽 또는 메인 윤곽에 속하는 경우.
예제를 봅시다. 지붕에 따르면 특별한 관심사는 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로 시작합니다.
typeID
필드는 구성요소의 타입을 식별합니다.index
필드는 주어진 구성요소의 현재 데이터베이스 인덱스를 제공합니다. 이 숫자는 프로젝트의 전체 수명에 걸쳐 특정 요소에 대해 일정하지 않다는 것을 참고하십시오.
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 인덱스들은 모든 경우에서 연속적이며, 다른 인덱스들은 연속적이지 않습니다.
- 3D 모델은 삭제된 평면도 요소들의 데이터를 가질 수도 있습니다. 그것들은 삭제된 body들을 통해서만 식별될 수 있습니다.
- 동일한 형상을 갖는 평면도 요소들은 3D 표현 데이터의 primitive들을 공유할 수 있지만 body는 공유하지 않을 수 있습니다. 모든 body에는 참조된 공유 정점과 법선 벡터를 올바른 위치와 방향으로 변환하는 변환 행렬이 포함되어 있습니다.
일단 body의 정의를 갖게 되면, 당신이 관심 있는 primitive들을 검토하기 위해 내부 루프를 설정할 수 있습니다. API_BodyType 레코드에서 모든 내부 구성요소의 수를 얻습니다. 인덱스는 1부터 시작해야 합니다.
빛과 재료 구성요소는 3D 모델의 글로벌(body 상대적이 아닌) 구성요소이기 때문에 자체 루프에서 얻을 수 있습니다.
실제로 존재하는 ArchiCAD의 3D 모델의 데이터를 얻는 것은 매우 중요합니다. 이 데이터는 평면도 요소들과 일치하지 않는 경우가 많습니다. 3D 창의 업데이트 메커니즘은 Preferences 다이얼로그의 스위치와 같이 많은 것에 따라 달라집니다. 일반적으로 위의 템플릿을 사용하는 경우, 3D 창에서 볼 수 있는 모델을 얻습니다.
특정 요소의 3D 표현 가져오기
또한 당신이 관심 있는 특정 평면도 요소의 3D 표현을 얻을 수 있는 가능성도 있습니다. 기본 메커니즘은 이전 예제와 동일합니다. 유일한 차이점은 body들이 주어진 요소에 속한다는 정보가 필요하다는 것입니다.
특정 평면도 요소에 할당된 body는 ACAPI_Element_Get3DInfo 함수로 얻을 수 있습니다. 이 함수는 메인 3D 데이터 컨테이너들의 인덱스 범위를 전달하기 위해 API_ElemInfo3D structure를 채웁니다.
fbody
및lbody
필드는 처음과 마지막 body 인덱스를 정의합니다. 이 범위의 인덱스들은 body 정의를 얻기 위해 사용되어야 합니다.- flight 및
llight
필드는 처음과 마지막 light 인덱스를 정의합니다. 객체의 3D GDL 스크립트는 주어진 요소가 발광을 갖는지 여부를 결정하는 LIGHT 커맨드를 포함할 수도 있습니다. 이 데이터는 이러한 인덱스를 기반으로 API_LghtType을 통해 얻을 수 있습니다.
중요한 참고: 이런 식으로 얻은 데이터는 실제로 존재하는 ArchiCAD의 3D 모델과 독립적입니다. 만약 기존 데이터가 일관성이 없는 경우, ArchiCAD는 주어진 요소를 3D로 다시 변환하여 올바른 결과를 보장합니다. 일반적으로 실제 평면도 데이터와 완전히 동기화된 모델을 얻습니다.
3D 모델을 매우 신중하게 얻으려면, 위에서 언급한 방법 중 하나를 선택해야 합니다.
일관된 데이터가 필요한 경우 관심 있는 평면도 요소들을 검토하는 루프를 설정하는 두 번째 방법을 선택해야 합니다. 이 경우 요소별로 3D 모델 요소를 얻을 수 있습니다.
당신은 종종 첫 번째 방법을 선택해야 합니다. 예를 들면, "Save As 3D" 다이얼로그에서 애드온을 호출하면 사용자가 저장하고자 하는 데이터는 실제로 3D 창에서 볼 수 있습니다.