Table of Contents

Формат EasyAR Mega Annotation 0.5

Этот документ определяет спецификацию формата EMA 0.5.

Перед началом

В этом документе "производитель" означает программу, создающую данные EMA, а "потребитель" означает программу, читающую данные EMA.

Соглашения формата

  • Файлы EMA используют кодировку UTF-8 и следуют синтаксису JSON, определенному в RFC 8259.
  • Имена полей в одном объекте не должны повторяться.
  • Имена полей чувствительны к регистру. Имена, определенные в этом документе, должны использовать формы из таблиц и примеров.
  • Обязательные поля должны присутствовать и использовать типы из таблиц. Необязательные поля можно опускать, если у них нет значения.
  • UUID записываются строками с дефисами, например 123e4567-e89b-12d3-a456-426614174000.
  • Временные метки используют строки даты и времени UTC в формате YYYY-MM-DDThh:mm:ssZ с точностью до секунды. Например, 2026-08-12T00:00:00Z. Этот формат следует UTC-представлению, определенному в W3C Date and Time Formats.
  • Преобразования координат используют правостороннюю систему OpenGL: +X вправо, +Y вверх, +Z назад.

Структура документа

Корневой объект документа EMA содержит версию формата, генератор, объявления расширений, список Mega Block и список аннотаций.

Пример структуры корневого объекта 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> Да Объекты аннотаций. Это может быть пустой массив.
extensions array<string> Нет Объявления расширений, используемые документом. См. Расширения.

Block

Block представляет Mega Block, на который ссылается документ EMA, и его координатную информацию.

Поле Тип Обязательно Описание
id UUID string Да Уникальный идентификатор Mega Block. Следует использовать значение, возвращенное службой EasyAR Mega.
timestamp date-time string Да Время последнего изменения Mega Block. Следует использовать значение, возвращенное службой EasyAR Mega. См. Соглашения формата.
location Location Нет Географическая позиция WGS 84 начала координат Mega Block.
transform Transform Да Преобразование Mega Block относительно корневой системы координат сцены EMA.
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.

Поле Тип Обязательно Описание
type string Да Тип аннотации. Значение: node или relationship.
id UUID string Да Уникальный идентификатор аннотации. ID в annotations должны быть уникальными.
timestamp date-time string Да Время последнего изменения аннотации. См. Соглашения формата.
featureType string Нет Тип функции, к которому относится аннотация.
properties object Нет Свойства аннотации и данные расширений.

Node

Node представляет аннотацию с пространственным положением.

Поле Тип Обязательно Описание
type string Да Фиксировано: node.
geometry string Да Тип геометрии. Значение: point или cube.
parent Parent Да Опорная система координат аннотации node. Она может ссылаться на Mega Block или географическую позицию WGS 84; поддержку второго варианта в продукте см. в WorldParent.
transform Transform Да Преобразование аннотации node относительно опорной системы координат. Включенные поля определяются geometry.

Если geometry равно point, это точка положения. Если geometry равно cube, это коробочная область с центром в начале координат. Требования к transform для разных геометрий см. в Transform.

Пример точечной аннотации:

{
  "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"
  }
}

Пример аннотации коробочной области:

{
  "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 представляет связь между аннотациями и также может использоваться для объединения нескольких аннотаций в набор.

Поле Тип Обязательно Описание
type string Да Фиксировано: relationship.
members array<UUID string> Да Записывает ID аннотаций-участников по порядку. Участники могут ссылаться на аннотации node или relationship.

Пример аннотации связи:

{
  "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, и определяет основу интерпретации его пространственного преобразования.

BlockParent

BlockParent представляет опорную систему координат на основе Mega Block.

Поле Тип Обязательно Описание
type string Да Фиксировано: block.
id UUID string Да ID указанного Mega Block. Этот ID должен существовать в blocks корневого объекта.
timestamp date-time string Да Время изменения Mega Block, на который ссылались при создании или обновлении аннотации. См. Соглашения формата.

WorldParent

WorldParent представляет мировую опорную систему координат с началом в географической позиции WGS 84.

Поле Тип Обязательно Описание
type string Да Фиксировано: world.
location Location Да Географическая позиция WGS 84 начала опорной системы координат аннотации node.
Предупреждение

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 Обязательно Пропущено Пропущено
Аннотация, у которой geometry равно cube Обязательно Обязательно Обязательно

Vector3F

Vector3F представляет трехмерный вектор для записи положения и масштаба.

Поле Тип Обязательно Описание
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 хранит общие свойства, свойства функций и данные расширений аннотаций. Это поле является объектом ключ-значение, а значение может быть любым значением JSON.

EMA 0.5 определяет следующие общие свойства:

Свойство Применимый объект Тип Обязательно Описание
name node, relationship string Нет Отображаемое имя аннотации.
isDirected relationship boolean Нет Указывает, является ли связь направленной. Если не указано, значение равно true.
category relationship string Нет Категория связи.

Типы функций

featureType задает тип функции, в котором участвует аннотация. Каждый тип функции определяет структуру, связь и специальные свойства связанных аннотаций.

Граф навигационных точек

Граф навигационных точек представляет навигационные точки в пространстве, маршруты между ними и сеть, составленную из них. Он может выражать маршруты и отношения связности. Все аннотации, составляющие граф навигационных точек, устанавливают featureType в navPointGraph.

Граф навигационных точек состоит из трех типов аннотаций:

Объект Требование к структуре
Навигационная точка type равно node, а geometry равно point.
Маршрут type равно relationship, а members по порядку ссылается на две навигационные точки.
Сеть type равно relationship, а members ссылается на навигационные точки и маршруты, входящие в сеть.

Аннотации связей в графе навигационных точек используют следующие свойства properties:

Свойство Применимый объект Тип Обязательно Описание
category Маршрут, сеть string Да Различает типы связей: маршрут — route, сеть — network.
isDirected Маршрут boolean Нет true означает направление от первой навигационной точки в members ко второй; false означает ненаправленную связь.
weight Маршрут number Нет Вес маршрута, 32-битное число с плавающей точкой. Конкретный смысл определяется приложением, использующим граф навигационных точек.

Пример аннотации графа навигационных точек:

[
  {
    "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.

Массив extensions корневого объекта объявляет расширения, используемые документом. Каждый элемент использует следующий формат:

PROVIDER:NAME#MAJOR.MINOR.PATCH
  • PROVIDER — имя поставщика расширения.
  • NAME — имя расширения.
  • Версия состоит из трех неотрицательных целых чисел.
  • PROVIDER и NAME не должны содержать : или #.
  • Одинаковый PROVIDER:NAME объявляется в extensions только один раз.

Данные расширения хранятся в 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
        }
      }
    }
  ]
}

Требования согласованности

Производители должны гарантировать:

  • ID Mega Block и ID аннотаций уникальны в своих коллекциях.
  • Когда parent.type равно block, parent.id ссылается на существующий Mega Block в blocks.
  • Когда type равно relationship, ID в members ссылаются на существующие аннотации в annotations.
  • Свойства расширений, используемые в properties, имеют соответствующие объявления в extensions.

Потребители могут игнорировать неизвестные обычные поля. Неизвестные 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
      }
    }
  ]
}