Format EasyAR Mega Annotation 0.5
Ce document définit la spécification du format EMA 0.5.
Avant de commencer
- Lisez la présentation du format EasyAR Mega Annotation pour comprendre les usages et scénarios applicables d'EMA.
Dans ce document, "producteur" désigne un programme qui génère des données EMA, et "consommateur" un programme qui lit des données EMA.
Conventions du format
- Les fichiers EMA utilisent l'encodage UTF-8 et suivent la syntaxe JSON définie par RFC 8259.
- Les noms de champs dans un même objet ne doivent pas être dupliqués.
- Les noms de champs sont sensibles à la casse. Ceux définis ici doivent utiliser les formes indiquées dans les tableaux et exemples.
- Les champs requis doivent exister et utiliser les types définis dans les tableaux. Les champs facultatifs peuvent être omis sans valeur.
- Les UUID sont écrits sous forme de chaînes avec traits d'union, par exemple
123e4567-e89b-12d3-a456-426614174000. - Les horodatages utilisent des chaînes date-heure UTC au format
YYYY-MM-DDThh:mm:ssZ, avec une précision à la seconde. Par exemple2026-08-12T00:00:00Z. Ce format suit la représentation UTC définie par W3C Date and Time Formats. - Les transformations de coordonnées utilisent un repère OpenGL droitier: +X vers la droite, +Y vers le haut et +Z vers l'arrière.
Structure du document
L'objet racine d'un document EMA contient la version du format, le générateur, les déclarations d'extension, la liste des Mega Blocks et la liste des annotations.
Exemple de structure de l'objet racine EMA:
{
"version": "0.5.0",
"generatedBy": "EasyAR Mega Support 2.14.0",
"blocks": [],
"annotations": [],
"extensions": []
}
| Champ | Type | Requis | Description |
|---|---|---|---|
version |
string | Oui | Version du format EMA. Un document 0.5 s'écrit 0.5.0. |
generatedBy |
string | Oui | Informations sur l'outil ou l'entité ayant généré le document, généralement avec nom du produit et version. |
blocks |
array<Block> | Oui | Mega Blocks référencés par le document. Ce peut être un tableau vide. |
annotations |
array<Annotation> | Oui | Objets d'annotation. Ce peut être un tableau vide. |
extensions |
array<string> | Non | Déclarations d'extensions utilisées par le document. Voir Extensions. |
Block
Block représente un Mega Block référencé par un document EMA et ses informations de coordonnées.
| Champ | Type | Requis | Description |
|---|---|---|---|
id |
UUID string | Oui | Identifiant unique du Mega Block. La valeur renvoyée par le service EasyAR Mega doit être utilisée. |
timestamp |
date-time string | Oui | Heure de dernière modification du Mega Block. La valeur renvoyée par le service EasyAR Mega doit être utilisée. Voir Conventions du format. |
location |
Location | Non | Position géographique WGS 84 de l'origine du Mega Block. |
transform |
Transform | Oui | Transformation du Mega Block par rapport au repère racine de la scène EMA. |
keepTransform |
boolean | Oui | Indique s'il faut conserver et appliquer le transform enregistré dans le document. true signifie conserver la transformation ajustée manuellement. |
Exemple de 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 représente une annotation dans un document EMA.
| Champ | Type | Requis | Description |
|---|---|---|---|
type |
string | Oui | Type d'annotation. La valeur est node ou relationship. |
id |
UUID string | Oui | Identifiant unique de l'annotation. Les ID dans annotations doivent être uniques. |
timestamp |
date-time string | Oui | Heure de dernière modification de l'annotation. Voir Conventions du format. |
featureType |
string | Non | Type de fonctionnalité auquel appartient l'annotation. |
properties |
object | Non | Propriétés de l'annotation et données d'extension. |
Node
Node représente une annotation avec une position spatiale.
| Champ | Type | Requis | Description |
|---|---|---|---|
type |
string | Oui | Fixé à node. |
geometry |
string | Oui | Type de géométrie. La valeur est point ou cube. |
parent |
Parent | Oui | Repère de référence de l'annotation node. Il peut référencer un Mega Block ou une position géographique WGS 84; pour la prise en charge produit de ce dernier cas, voir WorldParent. |
transform |
Transform | Oui | Transformation de l'annotation node par rapport au repère de référence. Les champs inclus sont déterminés par geometry. |
Lorsque geometry vaut point, il représente un point de position. Lorsqu'il vaut cube, il représente une zone en boîte centrée sur l'origine. Voir Transform pour les exigences du champ transform.
Exemple d'annotation de point:
{
"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"
}
}
Exemple d'annotation de zone en boîte:
{
"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 représente une relation entre annotations et peut aussi organiser plusieurs annotations en collection.
| Champ | Type | Requis | Description |
|---|---|---|---|
type |
string | Oui | Fixé à relationship. |
members |
array<UUID string> | Oui | Enregistre dans l'ordre les ID des annotations membres. Les membres peuvent référencer des annotations node ou relationship. |
Exemple d'annotation de relation:
{
"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 représente le repère de référence auquel un Node est attaché et détermine la base d'interprétation de sa transformation spatiale.
BlockParent
BlockParent représente un repère de référence basé sur un Mega Block.
| Champ | Type | Requis | Description |
|---|---|---|---|
type |
string | Oui | Fixé à block. |
id |
UUID string | Oui | ID du Mega Block référencé. Cet ID doit exister dans blocks de l'objet racine. |
timestamp |
date-time string | Oui | Heure de modification du Mega Block référencé lors de la création ou mise à jour de l'annotation. Voir Conventions du format. |
WorldParent
WorldParent représente un repère mondial dont l'origine est une position géographique WGS 84.
| Champ | Type | Requis | Description |
|---|---|---|---|
type |
string | Oui | Fixé à world. |
location |
Location | Oui | Position géographique WGS 84 de l'origine du repère de référence de l'annotation node. |
Avertissement
EMA 0.5 définit la structure où parent.type vaut world, mais EasyAR Mega Studio 2.13 et les versions postérieures à EasyAR Sense Unity Plugin 4003 ont supprimé les fonctionnalités associées. La définition du format ne signifie pas que ces versions du produit prennent en charge WorldParent.
Coordonnées et types de base
Location
Location représente une position géographique WGS 84.
| Champ | Type | Requis | Description |
|---|---|---|---|
latitude |
number | Oui | Latitude, nombre à virgule flottante 64 bits exprimé en degrés décimaux. |
longitude |
number | Oui | Longitude, nombre à virgule flottante 64 bits exprimé en degrés décimaux. |
altitude |
number | Oui | Altitude, nombre à virgule flottante 64 bits en mètres. |
Transform
Transform représente la transformation spatiale d'un objet par rapport à un repère de référence.
| Champ | Type | Requis | Description |
|---|---|---|---|
position |
Vector3F | Oui | Position par rapport au repère de référence. |
rotation |
Vector4F | Conditionnel | Rotation par rapport au repère de référence. |
scale |
Vector3F | Conditionnel | Échelle par rapport au repère de référence. |
Les exigences de chaque champ selon les cas d'utilisation sont les suivantes:
| Cas d'utilisation | position |
rotation |
scale |
|---|---|---|---|
| Mega Block | Requis | Requis | Requis |
geometry valant point |
Requis | Omis | Omis |
geometry valant cube |
Requis | Requis | Requis |
Vector3F
Vector3F représente un vecteur tridimensionnel utilisé pour enregistrer position et échelle.
| Champ | Type | Requis | Description |
|---|---|---|---|
x |
number | Oui | Composante de l'axe x, nombre à virgule flottante 32 bits. |
y |
number | Oui | Composante de l'axe y, nombre à virgule flottante 32 bits. |
z |
number | Oui | Composante de l'axe z, nombre à virgule flottante 32 bits. |
Vector4F
Vector4F représente un quaternion utilisé pour enregistrer la rotation.
| Champ | Type | Requis | Description |
|---|---|---|---|
x |
number | Oui | Composante x du quaternion, nombre à virgule flottante 32 bits. |
y |
number | Oui | Composante y du quaternion, nombre à virgule flottante 32 bits. |
z |
number | Oui | Composante z du quaternion, nombre à virgule flottante 32 bits. |
w |
number | Oui | Composante w du quaternion, nombre à virgule flottante 32 bits. |
Propriétés
properties stocke les propriétés communes, les propriétés de fonctionnalité et les données d'extension des annotations. Ce champ est un objet clé-valeur, et la valeur peut être n'importe quelle valeur JSON.
EMA 0.5 définit les propriétés communes suivantes:
| Propriété | Objet applicable | Type | Requis | Description |
|---|---|---|---|---|
name |
node, relationship |
string | Non | Nom affiché de l'annotation. |
isDirected |
relationship |
boolean | Non | Indique si la relation est dirigée. Si non spécifié, la valeur est true. |
category |
relationship |
string | Non | Catégorie de relation. |
Types de fonctionnalités
featureType spécifie le type de fonctionnalité auquel l'annotation participe. Chaque type définit la structure, la relation et les propriétés dédiées des annotations associées.
Graphe de points de navigation
Un graphe de points de navigation représente les points de navigation dans l'espace, les itinéraires qui les relient et le réseau qu'ils composent. Il peut exprimer les itinéraires et les relations de connectivité. Toutes les annotations qui le composent définissent featureType sur navPointGraph.
Le graphe de points de navigation se compose de trois types d'annotations:
| Objet | Exigence de structure |
|---|---|
| Point de navigation | type vaut node, et geometry vaut point. |
| Itinéraire | type vaut relationship, et members référence deux points de navigation dans l'ordre. |
| Réseau | type vaut relationship, et members référence les points de navigation et itinéraires inclus dans le réseau. |
Les annotations de relation dans un graphe de points de navigation utilisent les propriétés properties suivantes:
| Propriété | Objet applicable | Type | Requis | Description |
|---|---|---|---|---|
category |
Itinéraire, réseau | string | Oui | Distingue les types de relation: itinéraire vaut route, et réseau vaut network. |
isDirected |
Itinéraire | boolean | Non | true signifie du premier point de navigation dans members vers le second; false signifie non dirigé. |
weight |
Itinéraire | number | Non | Poids de l'itinéraire, nombre à virgule flottante 32 bits. Le sens précis est défini par l'application qui utilise le graphe de points de navigation. |
Exemple d'annotation de graphe de points de navigation:
[
{
"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"
}
}
]
Extensions
Les extensions ajoutent des données personnalisées aux annotations sans modifier la structure centrale EMA 0.5.
Le tableau extensions de l'objet racine déclare les extensions utilisées par le document. Chaque élément utilise le format suivant:
PROVIDER:NAME#MAJOR.MINOR.PATCH
PROVIDERest le nom du fournisseur de l'extension.NAMEest le nom de l'extension.- La version se compose de trois entiers non négatifs.
PROVIDERetNAMEne doivent pas contenir:ni#.- Le même
PROVIDER:NAMEn'est déclaré qu'une seule fois dansextensions.
Les données d'extension sont stockées dans les properties de l'annotation, avec le nom de propriété PROVIDER:NAME et sans numéro de version. La valeur d'extension peut être n'importe quelle valeur JSON. Un objet JSON est recommandé afin de pouvoir ajouter des champs plus tard.
Exemple de déclaration et données d'extension:
{
"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
}
}
}
]
}
Exigences de cohérence
Les producteurs doivent s'assurer que:
- Les ID de Mega Block et d'annotation sont uniques dans leurs collections respectives.
- Lorsque
parent.typevautblock,parent.idréférence un Mega Block existant dansblocks. - Lorsque
typevautrelationship, les ID dansmembersréférencent des annotations existantes dansannotations. - Les propriétés d'extension utilisées dans
propertiesont des déclarations correspondantes dansextensions.
Les consommateurs peuvent ignorer les champs ordinaires non reconnus. Les type, parent.type ou geometry inconnus doivent être traités comme non pris en charge.
Exemple complet
Exemple de document EMA complet contenant des données d'extension:
{
"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
}
}
]
}