EasyAR Mega Annotation 형식 0.5
이 문서는 EMA 0.5의 형식 사양을 정의합니다.
시작하기 전에
- EasyAR Mega Annotation 형식 소개를 읽고 EMA의 용도와 적용 시나리오를 확인하십시오.
이 문서에서 "producer"는 EMA 데이터를 생성하는 프로그램을, "consumer"는 EMA 데이터를 읽는 프로그램을 의미합니다.
형식 규칙
- EMA 파일은 UTF-8 인코딩을 사용하며 RFC 8259에 정의된 JSON 문법을 따릅니다.
- 같은 객체 안의 필드 이름은 중복될 수 없습니다.
- 필드 이름은 대소문자를 구분합니다. 이 문서에서 정의한 필드 이름은 표와 예시에 제시된 형식을 사용해야 합니다.
- 필수 필드는 존재해야 하며 표에 정의된 타입을 사용해야 합니다. 선택 필드는 값이 없으면 생략할 수 있습니다.
- UUID는 하이픈이 포함된 문자열로 작성합니다. 예:
123e4567-e89b-12d3-a456-426614174000. - 타임스탬프는
YYYY-MM-DDThh:mm:ssZ형식의 UTC 날짜-시간 문자열을 사용하며 초 단위까지 정확합니다. 예:2026-08-12T00:00:00Z. 이 형식은 W3C Date and Time Formats에 정의된 UTC 표현을 따릅니다. - 좌표 변환은 오른손 OpenGL 좌표계를 사용합니다. +X는 오른쪽, +Y는 위쪽, +Z는 뒤쪽을 가리킵니다.
문서 구조
EMA 문서의 루트 객체에는 형식 버전, 생성자, 확장 선언, Mega Block 목록 및 annotation 목록이 포함됩니다.
EMA 루트 객체 구조 예:
{
"version": "0.5.0",
"generatedBy": "EasyAR Mega Support 2.14.0",
"blocks": [],
"annotations": [],
"extensions": []
}
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
version |
string | 예 | EMA 형식 버전입니다. 0.5 문서는 0.5.0으로 작성합니다. |
generatedBy |
string | 예 | 문서를 생성한 도구 또는 주체 정보이며 일반적으로 제품 이름과 버전을 포함합니다. |
blocks |
array<Block> | 예 | 문서가 참조하는 Mega Block입니다. 빈 배열일 수 있습니다. |
annotations |
array<Annotation> | 예 | annotation 객체입니다. 빈 배열일 수 있습니다. |
extensions |
array<string> | 아니요 | 문서가 사용하는 확장 선언입니다. 확장을 참조하십시오. |
Block
Block는 EMA 문서가 참조하는 Mega Block과 해당 좌표 정보를 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
id |
UUID string | 예 | Mega Block의 고유 식별자입니다. EasyAR Mega 서비스가 반환한 값을 사용해야 합니다. |
timestamp |
date-time string | 예 | Mega Block의 마지막 수정 시간입니다. EasyAR Mega 서비스가 반환한 값을 사용해야 합니다. 형식 규칙을 참조하십시오. |
location |
Location | 아니요 | Mega Block 원점의 WGS 84 지리 위치입니다. |
transform |
Transform | 예 | EMA 장면 루트 좌표계에 대한 Mega Block의 변환입니다. |
keepTransform |
boolean | 예 | 문서에 기록된 transform을 유지하고 적용할지 여부입니다. true는 수동 조정된 변환을 유지함을 의미합니다. |
Mega Block 예:
{
"id": "37f11da4-84c0-4fd1-839f-0d86a43cce21",
"timestamp": "2026-08-12T00:00:00Z",
"location": {
"latitude": 31.2304,
"longitude": 121.4737,
"altitude": 5.5
},
"transform": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 },
"scale": { "x": 1.0, "y": 1.0, "z": 1.0 }
},
"keepTransform": true
}
Annotation
Annotation은 EMA 문서의 annotation을 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type |
string | 예 | annotation 타입입니다. 값은 node 또는 relationship입니다. |
id |
UUID string | 예 | annotation의 고유 식별자입니다. annotations의 ID는 고유해야 합니다. |
timestamp |
date-time string | 예 | annotation의 마지막 수정 시간입니다. 형식 규칙을 참조하십시오. |
featureType |
string | 아니요 | annotation이 속한 기능 타입입니다. |
properties |
object | 아니요 | annotation 속성과 확장 데이터입니다. |
Node
Node는 공간 위치를 가진 annotation을 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type |
string | 예 | node로 고정됩니다. |
geometry |
string | 예 | geometry 타입입니다. 값은 point 또는 cube입니다. |
parent |
Parent | 예 | node annotation의 참조 좌표계입니다. Mega Block 또는 WGS 84 지리 위치를 참조할 수 있으며, 후자의 제품 지원은 WorldParent를 참조하십시오. |
transform |
Transform | 예 | 참조 좌표계에 대한 node annotation의 변환입니다. 포함되는 필드는 geometry에 따라 결정됩니다. |
geometry가 point이면 위치점을 나타냅니다. cube이면 원점을 중심으로 하는 박스 영역을 나타냅니다. 각 geometry의 transform 요구사항은 Transform을 참조하십시오.
점 annotation 예:
{
"type": "node",
"id": "b62fd4b5-66aa-4418-a603-69ae6faedbe6",
"timestamp": "2026-08-12T00:00:01Z",
"geometry": "point",
"parent": {
"type": "block",
"id": "37f11da4-84c0-4fd1-839f-0d86a43cce21",
"timestamp": "2026-08-12T00:00:00Z"
},
"transform": {
"position": { "x": 1.0, "y": 2.0, "z": 3.0 }
},
"properties": {
"name": "Entrance"
}
}
박스 영역 annotation 예:
{
"type": "node",
"id": "76c0e24a-a01a-4a50-9246-e7d827c96b38",
"timestamp": "2026-08-12T00:00:02Z",
"geometry": "cube",
"parent": {
"type": "block",
"id": "37f11da4-84c0-4fd1-839f-0d86a43cce21",
"timestamp": "2026-08-12T00:00:00Z"
},
"transform": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 },
"scale": { "x": 0.5, "y": 1.75, "z": 0.5 }
}
}
Relationship
Relationship는 annotation 간의 관계를 나타내며 여러 annotation을 하나의 컬렉션으로 구성하는 데도 사용할 수 있습니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type |
string | 예 | relationship로 고정됩니다. |
members |
array<UUID string> | 예 | 멤버 annotation ID를 순서대로 기록합니다. 멤버는 node 또는 relationship annotation을 참조할 수 있습니다. |
관계 annotation 예:
{
"type": "relationship",
"id": "b7cf28e4-041e-460e-81cf-a0591c09faee",
"timestamp": "2026-08-12T00:00:03Z",
"members": [
"b62fd4b5-66aa-4418-a603-69ae6faedbe6",
"76c0e24a-a01a-4a50-9246-e7d827c96b38"
],
"properties": {
"name": "Annotation Group",
"isDirected": false
}
}
Parent
Parent는 Node가 붙는 참조 좌표계를 나타내며 Node 공간 변환의 해석 기준을 결정합니다.
BlockParent
BlockParent는 Mega Block 기반의 참조 좌표계를 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type |
string | 예 | block로 고정됩니다. |
id |
UUID string | 예 | 참조된 Mega Block의 ID입니다. 이 ID는 루트 객체의 blocks에 있어야 합니다. |
timestamp |
date-time string | 예 | annotation을 만들거나 업데이트할 때 참조된 Mega Block의 수정 시간입니다. 형식 규칙을 참조하십시오. |
WorldParent
WorldParent는 WGS 84 지리 위치를 원점으로 하는 월드 참조 좌표계를 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type |
string | 예 | world로 고정됩니다. |
location |
Location | 예 | node annotation 참조 좌표계 원점의 WGS 84 지리 위치입니다. |
경고
EMA 0.5는 parent.type이 world인 구조를 정의하지만 EasyAR Mega Studio 2.13 및 EasyAR Sense Unity Plugin 4003 이후 버전은 관련 기능을 제거했습니다. 형식 정의가 해당 제품 버전에서 WorldParent 사용을 지원한다는 의미는 아닙니다.
좌표와 기본 타입
Location
Location은 WGS 84 지리 위치를 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
latitude |
number | 예 | 위도이며 십진 도 단위로 표현되는 64비트 부동소수점 숫자입니다. |
longitude |
number | 예 | 경도이며 십진 도 단위로 표현되는 64비트 부동소수점 숫자입니다. |
altitude |
number | 예 | 고도이며 미터 단위의 64비트 부동소수점 숫자입니다. |
Transform
Transform는 참조 좌표계에 대한 객체의 공간 변환을 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
position |
Vector3F | 예 | 참조 좌표계에 대한 위치입니다. |
rotation |
Vector4F | 조건부 | 참조 좌표계에 대한 회전입니다. |
scale |
Vector3F | 조건부 | 참조 좌표계에 대한 스케일입니다. |
각 필드의 사용 사례별 요구사항은 다음과 같습니다:
| 사용 사례 | position |
rotation |
scale |
|---|---|---|---|
| Mega Block | 필수 | 필수 | 필수 |
geometry가 point인 annotation |
필수 | 생략 | 생략 |
geometry가 cube인 annotation |
필수 | 필수 | 필수 |
Vector3F
Vector3F는 위치와 스케일을 기록하는 3차원 벡터를 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
x |
number | 예 | x축 성분이며 32비트 부동소수점 숫자입니다. |
y |
number | 예 | y축 성분이며 32비트 부동소수점 숫자입니다. |
z |
number | 예 | z축 성분이며 32비트 부동소수점 숫자입니다. |
Vector4F
Vector4F는 회전을 기록하는 쿼터니언을 나타냅니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
x |
number | 예 | 쿼터니언의 x 성분이며 32비트 부동소수점 숫자입니다. |
y |
number | 예 | 쿼터니언의 y 성분이며 32비트 부동소수점 숫자입니다. |
z |
number | 예 | 쿼터니언의 z 성분이며 32비트 부동소수점 숫자입니다. |
w |
number | 예 | 쿼터니언의 w 성분이며 32비트 부동소수점 숫자입니다. |
속성
properties는 annotation의 공통 속성, 기능 속성 및 확장 데이터를 저장합니다. 이 필드는 키-값 객체이며 값은 임의의 JSON 값일 수 있습니다.
EMA 0.5는 다음 공통 속성을 정의합니다:
| 속성 | 적용 대상 | 타입 | 필수 | 설명 |
|---|---|---|---|---|
name |
node, relationship |
string | 아니요 | annotation의 표시 이름입니다. |
isDirected |
relationship |
boolean | 아니요 | 관계가 방향성을 가지는지 여부입니다. 지정하지 않으면 true입니다. |
category |
relationship |
string | 아니요 | 관계 카테고리입니다. |
기능 타입
featureType는 annotation이 참여하는 기능 타입을 지정합니다. 각 기능 타입은 관련 annotation의 구조, 관계 및 전용 속성을 정의합니다.
내비게이션 지점 그래프
내비게이션 지점 그래프는 공간의 내비게이션 지점, 내비게이션 지점을 연결하는 경로, 그리고 이들로 구성된 네트워크를 나타냅니다. 경로와 연결 관계를 표현할 수 있습니다. 내비게이션 지점 그래프를 구성하는 모든 annotation은 featureType을 navPointGraph로 설정합니다.
내비게이션 지점 그래프는 세 가지 annotation 타입으로 구성됩니다:
| 객체 | 구조 요구사항 |
|---|---|
| 내비게이션 지점 | type은 node이고 geometry는 point입니다. |
| 경로 | type은 relationship이고 members는 두 내비게이션 지점을 순서대로 참조합니다. |
| 네트워크 | type은 relationship이고 members는 네트워크에 포함된 내비게이션 지점과 경로를 참조합니다. |
내비게이션 지점 그래프의 관계 annotation은 다음 properties 속성을 사용합니다:
| 속성 | 적용 대상 | 타입 | 필수 | 설명 |
|---|---|---|---|---|
category |
경로, 네트워크 | string | 예 | 관계 타입을 구분합니다. 경로는 route, 네트워크는 network입니다. |
isDirected |
경로 | boolean | 아니요 | true는 members의 첫 번째 내비게이션 지점에서 두 번째 지점으로 향함을 의미하고, false는 무방향을 의미합니다. |
weight |
경로 | number | 아니요 | 경로 가중치이며 32비트 부동소수점 숫자입니다. 구체적인 의미는 내비게이션 지점 그래프를 사용하는 애플리케이션이 정의합니다. |
내비게이션 지점 그래프 annotation 예:
[
{
"type": "node",
"id": "25634f2e-c42d-4163-84c4-86757e8f6e8f",
"timestamp": "2026-08-12T00:00:00Z",
"featureType": "navPointGraph",
"geometry": "point",
"parent": {
"type": "block",
"id": "37f11da4-84c0-4fd1-839f-0d86a43cce21",
"timestamp": "2026-08-12T00:00:00Z"
},
"transform": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 }
}
},
{
"type": "node",
"id": "fa144e57-c388-4673-a940-9a3f904247c5",
"timestamp": "2026-08-12T00:00:01Z",
"featureType": "navPointGraph",
"geometry": "point",
"parent": {
"type": "block",
"id": "37f11da4-84c0-4fd1-839f-0d86a43cce21",
"timestamp": "2026-08-12T00:00:00Z"
},
"transform": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 }
}
},
{
"type": "relationship",
"id": "455427a3-b68d-4237-a78f-22213de89dc8",
"timestamp": "2026-08-12T00:00:02Z",
"featureType": "navPointGraph",
"members": [
"25634f2e-c42d-4163-84c4-86757e8f6e8f",
"fa144e57-c388-4673-a940-9a3f904247c5"
],
"properties": {
"category": "route",
"isDirected": true,
"weight": 1.0
}
},
{
"type": "relationship",
"id": "b579c5fe-e574-410b-853f-77c985966d0f",
"timestamp": "2026-08-12T00:00:03Z",
"featureType": "navPointGraph",
"members": [
"25634f2e-c42d-4163-84c4-86757e8f6e8f",
"fa144e57-c388-4673-a940-9a3f904247c5",
"455427a3-b68d-4237-a78f-22213de89dc8"
],
"properties": {
"category": "network"
}
}
]
확장
확장은 EMA 0.5 핵심 구조를 변경하지 않고 annotation에 사용자 정의 데이터를 추가하는 데 사용됩니다.
루트 객체의 extensions 배열은 문서가 사용하는 확장을 선언합니다. 각 항목은 다음 형식을 사용합니다:
PROVIDER:NAME#MAJOR.MINOR.PATCH
PROVIDER는 확장 제공자 이름입니다.NAME은 확장 이름입니다.- 버전은 세 개의 음이 아닌 정수로 구성됩니다.
PROVIDER와NAME에는:또는#이 포함될 수 없습니다.- 동일한
PROVIDER:NAME은extensions에서 한 번만 선언됩니다.
확장 데이터는 annotation의 properties에 저장하며, 속성 이름은 PROVIDER:NAME이고 버전 번호는 포함하지 않습니다. 확장 값은 임의의 JSON 값일 수 있습니다. 나중에 필드를 추가할 수 있도록 JSON 객체를 권장합니다.
확장 선언 및 데이터 예:
{
"version": "0.5.0",
"generatedBy": "Sample Producer 1.0.0",
"extensions": [
"SampleCompany:SampleExtension#1.0.0"
],
"blocks": [],
"annotations": [
{
"type": "relationship",
"id": "15da6815-174a-4963-ac27-6dc97f324474",
"timestamp": "2026-08-12T00:00:04Z",
"members": [],
"properties": {
"SampleCompany:SampleExtension": {
"label": "sample",
"priority": 10
}
}
}
]
}
일관성 요구사항
producer는 다음을 보장해야 합니다:
- Mega Block ID와 annotation ID는 각각의 컬렉션에서 고유합니다.
parent.type이block이면parent.id는blocks에 있는 기존 Mega Block을 참조합니다.type이relationship이면members의 ID는annotations에 있는 기존 annotation을 참조합니다.properties에서 사용되는 확장 속성은extensions에 해당 선언이 있어야 합니다.
consumer는 인식하지 못하는 일반 필드를 무시할 수 있습니다. 인식할 수 없는 type, parent.type, geometry는 지원되지 않는 데이터로 처리해야 합니다.
전체 예
확장 데이터를 포함하는 완전한 EMA 문서 예:
{
"version": "0.5.0",
"generatedBy": "EasyAR Mega Support 2.14.0",
"extensions": [
"SampleCompany:SampleExtension#1.0.0"
],
"blocks": [
{
"id": "37f11da4-84c0-4fd1-839f-0d86a43cce21",
"timestamp": "2026-08-12T00:00:00Z",
"location": {
"latitude": 31.2304,
"longitude": 121.4737,
"altitude": 5.5
},
"transform": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 },
"scale": { "x": 1.0, "y": 1.0, "z": 1.0 }
},
"keepTransform": true
}
],
"annotations": [
{
"type": "node",
"id": "b62fd4b5-66aa-4418-a603-69ae6faedbe6",
"timestamp": "2026-08-12T00:00:01Z",
"geometry": "point",
"parent": {
"type": "block",
"id": "37f11da4-84c0-4fd1-839f-0d86a43cce21",
"timestamp": "2026-08-12T00:00:00Z"
},
"transform": {
"position": { "x": 1.0, "y": 2.0, "z": 3.0 }
},
"properties": {
"name": "Entrance",
"SampleCompany:SampleExtension": {
"label": "sample",
"priority": 10
}
}
},
{
"type": "node",
"id": "76c0e24a-a01a-4a50-9246-e7d827c96b38",
"timestamp": "2026-08-12T00:00:02Z",
"geometry": "cube",
"parent": {
"type": "block",
"id": "37f11da4-84c0-4fd1-839f-0d86a43cce21",
"timestamp": "2026-08-12T00:00:00Z"
},
"transform": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 },
"scale": { "x": 0.5, "y": 1.75, "z": 0.5 }
},
"properties": {
"name": "Display Area"
}
},
{
"type": "relationship",
"id": "b7cf28e4-041e-460e-81cf-a0591c09faee",
"timestamp": "2026-08-12T00:00:03Z",
"members": [
"b62fd4b5-66aa-4418-a603-69ae6faedbe6",
"76c0e24a-a01a-4a50-9246-e7d827c96b38"
],
"properties": {
"name": "Tour Area",
"isDirected": false
}
}
]
}