Articulo de referencia

JMesh

{{cite web|url=https://github.com/NeuroJSON/jmesh/blob/master/JMesh_specification.md|title=JMesh Specification - Version 1 Draft 1|website=[[GitHub]]|date=14 March 2022|publishe...

JMesh es un formato de archivo portátil y extensible basado en JSON para el almacenamiento e intercambio de datos geométricos no estructurados, incluyendo geometrías discretizadas como mallas triangulares y tetraédricas, geometrías paramétricas como curvas y superficies NURBS, y geometrías constructivas como la geometría sólida constructiva (CGS) de primitivas de forma y mallas. Basado en la especificación JData , un archivo JMesh utiliza las construcciones JSON y UBJSON ( Universal Binary JSON ) para serializar y codificar estructuras de datos geométricos; por lo tanto, puede ser procesado directamente por la mayoría de los analizadores JSON y UBJSON existentes. La especificación JMesh define una lista de construcciones compatibles con JSON para codificar datos geométricos, incluidos vértices N-dimensionales (ND), curvas, superficies, elementos sólidos, primitivas de forma, sus interacciones (como CGS) y relaciones espaciales, junto con sus propiedades asociadas, como valores numéricos, colores, normales, materiales, texturas y otras propiedades relacionadas con la manipulación de datos gráficos, la fabricación 3D, la representación gráfica por ordenador y las animaciones.

Ejemplo de archivo JMesh

La siguiente malla (una malla tetraédrica de un cubo unitario) contiene 8 vértices 3D, 12 caras triangulares y 6 elementos tetraédricos.

La malla anterior se puede almacenar en formato JMesh/JSON como

{ "_DataInfo_" :{ "JMeshVersion" : 0.5 , "CreationTime" : "19-dic-2021 11:53:43" , "Comment" : "Creado por iso2mesh 1.9.5-Rev(http:\/\/iso2mesh.sf.net)" }, "MeshVertex3" :[ [ 0 , 0 , 0 ], [ 1 , 0 , 0 ], [ 0 , 1 , 0 ], [ 1 , 1 , 0 ], [ 0 , 0 , 1 ], [ 1 , 0 , 1 ], [ 0 , 1 , 1 ], [ 1 , 1 , 1 ] ], "MeshTri3" :[ [ 1 , 2 , 4 ], [ 1 , 2 , 6 ], [ 1 , 3 , 4 ], [ 1 , 3 , 7 ], [ 1 , 5 , 6 ], [ 1 , 5 , 7 ], [ 2 , 8 , 4 ], [ 2 , 8 , 6 ], [ 3 , 8 , 4 ], [ 3 , 8 , 7 ], [ 5 , 8 , 6 ], [ 5 , 8 , 7 ] ], "MeshTet4" : [ [ 1 , 2 , 4 , 8 ], [ 1 , 3 , 4 , 8 ], [ 1 , 2 , 6 , 8 ], [ 1 , 5 , 6 , 8 ], [ 1, 3 , 7 , 8 ], [ 1 , 5 , 7 , 8 ] ] }

El "_DataInfo_"registro opcional puede contener metadatos adicionales según la especificación JData .

En lugar de usar construcciones de datos de malla específicas de dimensión, es decir MeshVertex3, , MeshTri3, y MeshTet4, también se pueden reemplazar con los contenedores de datos de malla flexibles correspondientes, MeshNode, MeshSurf, y MeshElem, respectivamente. Se recomienda agregar "Dimension": 3en el "_DataInfo_"encabezado de metadatos para ayudar a los analizadores a procesar correctamente los datos numéricos en cada entrada.

Alternativamente, según las especificaciones de JMesh y JData , las matrices 2D con formato JSON mencionadas anteriormente se pueden almacenar como una estructura utilizando el formato de matriz ND anotada de JData para agregar soporte adicional para tipos de datos binarios, como se muestra a continuación.

{ "_DataInfo_" :{ "JMeshVersion" : 0.5 , "Dimension" : 3 }, "MeshNode" :{ "_ArrayType_" : "double" , "_ArraySize_" :[ 8 , 3 ], "_ArrayData_" :[ 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 ] }, "MeshSurf" :{ "_ArrayType_" : "uint8" , "_ArraySize_" :[ 12 , 3 ], "_ArrayData_" :[ 1 , 2 , 4 , 1 , 2 , 6 , 1 , 3 , 4 , 1 , 3 , 7 , 1 , 5 , 6 , 1 , 5 , 7 , 2 , 8 , 4 , 2 , 8 , 6 , 3 , 8 , 4 , 3 , 8 , 7 , 5 , 8 , 6 , 5 , 8 , 7 ] }, "MeshElem" :{ "_ArrayType_" : " uint8" , " _ArraySize_" :[ 6 , 4 ], "_ArrayData_" :[ 1 , 2 , 4 , 8 , 1 , 3 , 4 , 8 , 1 ,2 , 6 , 8 ,1 , 5 , 6 , 8 , 1 , 3 , 7 , 8 , 1 , 5 , 7 , 8 ] } }

Para archivos de datos de malla grandes, se admite la compresión a nivel de registro a través de la especificación JData . Solo a modo de ilustración, los datos JMesh anteriores también se pueden escribir como

{ "_DataInfo_" :{ "JMeshVersion" : 0.5 , "Dimension" : 3 }, "MeshNode" :{ "_ArrayType_" : "double" , "_ArraySize_" :[ 8 , 3 ], "_ArrayZipSize_" :[ 1 , 24 ], "_ArrayZipType_" : "zlib" , "_ArrayZipData_" : "eJxjYMAHPtjjlcaQh/GJ1YdLPy51mDQAp2EONQ==" }, "MeshSurf" :{ "_ArrayType_" : "uint8" , "_ArraySize_" :[ 12 , 3 ], "_ArrayZipSize_" :[ 1 , 36 ], "_ArrayZipType_" : "zlib" , "_ArrayZipData_" : "eJwFwYcNAAAIArAAMv6/2BY8MNBBhQOXOy7aafXi9QEJtwCj" }, "MeshElem" :{ "_ArrayType_" : "uint8" , "_ArraySize_" :[ 6 , 4 ], "_ArrayZipSize_" :[ 1 , 24 ], "_ArrayZipType_" : "zlib" , "_ArrayZipData_" : "eJxjZGLhYGQGYiY2DkZWIGZmB9LsHAAExABt" } }

donde las cadenas "_ArrayZipData_"almacenan el flujo binario serializado por filas, comprimido con Zlib y codificado en Base64 de los datos de la matriz binaria sin procesar con la precisión especificada en . La compresión de datos_ArrayType_ a nivel de registro puede ofrecer una reducción de tamaño significativa al almacenar archivos de malla grandes.

Descripción general del formato

Sintaxis de JMesh

Todos los archivos JMesh cumplen con la especificación JData . Al igual que JData, dispone de un formato de texto basado en el esquema de serialización JSON y un formato binario basado en el esquema de serialización UBJSON.

Casi todos los contenedores de datos de malla compatibles (es decir, los nodos JData con nombre) se pueden definir utilizando una de las dos formas: una matriz ND o una estructura.

Formato de matriz

Para datos simples, se puede usar el "formato de matriz" para almacenar los datos bajo una palabra clave JMesh. En tal caso, el formato de los datos debe seguir las reglas de la "palabra clave de almacenamiento de matriz N-dimensional" definidas en la especificación JData. Por ejemplo, se puede almacenar una matriz 1D o 2D usando el formato de almacenamiento directo como

"jmesh_container_1d" : [ v1 , v2 ,..., vn ], "jmesh_container_2d" : [ [ v11 , v12 ,..., v1n ], [ v21 , v22 ,..., v2n ], ... [ vm1 , vm2 ,..., vmn ] ]

o utilizando el formato de "almacenamiento anotado" como

"jmesh_container_nd" : { "_ArrayType_" : "typename" , "_ArraySize_" : [ N1 , N2 , N3 ,...], "_ArrayData_" : [ v1 , v2 , v3 ,...] }

Forma de estructura

También se puede utilizar una estructura JData para almacenar los datos principales y para admitir metadatos adicionales asociados con el contenedor. Por ejemplo, un contenedor basado en una estructura puede tener los siguientes subcampos:

"jmesh_container_struct" : { "_DataInfo_" : { ... }, "Data" : [ ... ], "Properties" : [ ... ] }

Solo "Data"se requiere el subcampo, y este debe contener los mismos datos almacenados en formato de matriz (ya sea en formato directo o anotado) que se muestran arriba.

El subcampo opcional "Properties"permite almacenar datos adicionales junto con este elemento de forma/malla. El "Properties"subcampo puede ser una matriz o una estructura con subcampos adicionales.

La opción "_DataInfo_"es la construcción JData para almacenar metadatos asociados a esta estructura. Se puede usar para almacenar metadatos simples, como la fecha de adquisición de datos , el nombre del operador o el número de versión. La estrategia para dividir los metadatos entre _DataInfo_y Propertiesdepende del usuario.

Resumen de palabras clave de JMesh

La mayoría de las palabras clave del contenedor de datos asociadas con geometrías discretizadas tienen el prefijo "Mesh"; las palabras clave asociadas con construcciones de formas paramétricas tienen el prefijo "Shape"; las palabras clave asociadas con geometrías sólidas constructivas tienen el prefijo "CSG". Muchas de las palabras clave terminan con un valor numérico que normalmente representa el número de columna de los datos cuando se almacenan en formato de matriz.

  • Agrupación de malla : MeshGroup, MeshObject,MeshPart
  • Vértices : MeshVertex1, MeshVertex2, MeshVertex3,MeshVertex4
  • Líneas : MeshLine, MeshEdge,MeshBSpline2D
  • Superficies : MeshTri3, MeshQuad4, MeshPLC,MeshNURBS
  • Sólido : MeshTet4, MeshHex8, MeshPyramid5,MeshTet10
  • Contenedores flexibles : MeshNode, MeshSurf, MeshPoly,MeshElem
  • Operadores CSG : CSGObject, CSGUnion, CSGIntersect,CSGSubtract
  • Textura : Texture1D, Texture2D,Texture3D
  • Primitivas de formas 2D : ShapeBox2, ShapeDisc2, ShapeEllipse, ShapeLine2, ShapeArrow2, ShapeAnnulus,ShapeGrid2
  • Primitivas de formas 3D : ShapeLine3, ShapePlane3, ShapeBox3, ShapeDisc3, ShapeGrid3, ShapeSphere, ShapeCylinder, ShapeEllipsoid, ShapeTorus, ShapeCone, ShapeConeFrustum, ShapeSphereShell,ShapeSphereSegment
  • Extrusión y rotación : ShapeExtrude2D, ShapeExtrude3D,ShapeRevolve3D
  • Propiedades : Color, Normal, Size, Label,Value

Vértices

  • "MeshVertex1"Define un vector de posición unidimensional. Debe definirse como un vector numérico de N × 1 o 1 × N, donde N es igual al número total de vértices. Los valores de este vector serán las coordenadas de los vértices unidimensionales.
"MeshVertex1" : [ x1 , x2 , x3 , ...]
  • "MeshVertex2"Define un vector de posición bidimensional. Debe definirse como una matriz numérica de N x 2, donde N es el número total de vértices. Cada fila de esta matriz contiene las coordenadas del vértice.
"MeshVertex2" : [ [ x1 , y1 ], [ x2 , y2 ], [ x3 , y3 ], ... ]
  • "MeshVertex3"define un vector de posición 3D. Al igual que MeshVertex2, debe definirse como una matriz numérica de N x 3.
"MeshVertex3" : [ [ x1 , y1 , z1 ], [ x2 , y2 , z2 ], [ x3 , y3 , z3 ], ... ]

Segmentos de línea y curvas

  • "MeshPolyLine"Define un conjunto de segmentos de línea mediante una lista unidimensional ordenada de índices de nodos (que comienza en 1). Debe definirse mediante un vector de enteros de 1xN o Nx1. Si un índice es 0, marca el final del segmento de línea actual y comienza un nuevo segmento de línea desde el siguiente índice.
"MeshPolyLine": [N1, N2, N3, ... ]
  • "MeshEdge"Define un conjunto de segmentos de línea mediante una matriz bidimensional con un par de índices de nodos en cada fila. Debe definirse mediante una matriz entera de N x 2, donde N es el número total de aristas.
"MeshEdge" : [ [ N11 , N12 ], [ N21 , N22 ], [ N31 , N32 ], ... ]

Superficies

  • "MeshTri3"Define una superficie discretizada compuesta por triángulos con una terna de índices de nodos en cada fila del arreglo. Debe definirse mediante un arreglo entero de N x 3, donde N es el número total de triángulos.
"MeshTri3" : [ [ N11 , N12 , N13 ], [ N21 , N22 , N23 ], [ N31 , N32 , N33 ], ... ]
  • "MeshQuad4"Define una superficie discretizada formada por cuadriláteros con un cuádruple de índices de nodos en cada fila de la matriz. Debe definirse mediante una matriz entera de N x 4, donde N es el número total de cuadriláteros.
"MeshQuad4" : [ [ N11 , N12 , N13 , N14 ], [ N21 , N22 , N23 , N24 ], [ N31 , N32 , N33 , N24 ], ... ]
  • "MeshPLC"Define una superficie discretizada compuesta por polígonos (lineales complejos por partes) de longitudes de arista uniformes o variables. Debe definirse mediante una matriz cuyos elementos sean vectores enteros de longitud igual o variable.
"PLC de malla" : [ [ N11 , N12 , N13 , ...], [ N21 , N22 , N23 , N24 , ...], [ N31 , N32 , N33 , N34 , ..., ...], ... ]

Elementos sólidos

  • "MeshTet4"Define un dominio volumétrico discretizado compuesto por elementos tetraédricos, donde cada elemento está formado por un cuarteto de índices de nodos. Debe definirse mediante una matriz entera de N x 4, donde N es el número total de tetraedros.
"MeshTet4" : [ [ N11 , N12 , N13 , N14 ], [ N21 , N22 , N23 , N24 ], [ N31 , N32 , N33 , N34 ], ... ]
  • "MeshHex8"Define un dominio volumétrico discretizado compuesto por elementos hexaédricos de 8 nodos, donde cada elemento se especifica mediante un índice de nodo de 8 elementos. Debe definirse mediante una matriz entera de N x 8, donde N es el número total de hexaedros.
"MeshHex8" : [ [ N11 , N12 , N13 , ..., N18 ], [ N21 , N22 , N23 , ..., N28 ], [ N31 , N32 , N33 , ..., N28 ], ... ]
  • "MeshPyramid5"Define un dominio volumétrico discretizado compuesto por elementos piramidales de 5 nodos, donde cada elemento se especifica mediante un índice de nodo de 5 elementos. Debe definirse mediante una matriz entera de N x 5, donde N es el número total de pirámides.
"MeshPyramid5" : [ [ N11 , N12 , N13 , ..., N15 ], [ N21 , N22 , N23 , ..., N25 ], [ N31 , N32 , N33 , ..., N25 ], ... ]
  • "MeshTet10"Define un dominio volumétrico discretizado compuesto por elementos tetraédricos rectilíneos de 10 nodos, donde cada elemento se especifica mediante un índice de nodo de 10 elementos. Debe definirse mediante una matriz entera de N x 10, donde N es el número total de tetraedros de 10 nodos.
"MeshTet10" : [ [ N11 , N12 , N13 , ..., N1_10 ], [ N21 , N22 , N23 , ..., N2_10 ], [ N31 , N32 , N33 , ..., N2_10 ], ... ]

Las primeras 4 columnas de la matriz especifican los índices de los 4 vértices del tetraedro, idénticos a "MeshTet4", y las últimas 6 columnas de la matriz especifican los índices de los nodos de aristas medias, ordenados en el siguiente orden:

 [N1, N2, N3, N4, N12, N13, N14, N22, N23, N34]

Contenedores de datos de malla flexible

Los contenedores de datos de malla flexibles permiten codificar una amplia gama de datos de malla utilizando una sencilla matriz bidimensional.

  • "MeshNode"define un contenedor flexible para el almacenamiento de coordenadas de vértices y propiedades asociadas. Debe definirse mediante una matriz N x M, donde N es el número de vértices y M es el número de coordenadas (D) más el número de propiedades numéricas (P) asociadas a cada vértice, es decir, M = D + P.
"MeshNode" : [ [ x11 , y11 , z11 , ..., w1D , ..., v11 , v12 , ..., v1P ], [ x21 , y21 , z21 , ..., w2D , ..., v21 , v22 , ..., v2P ], [ x31 , y31 , z31 , ..., w3D , ..., v31 , v32 , ..., v3P ], ... ]
  • "MeshSurf"define un contenedor flexible para el almacenamiento de parches de superficie de longitud de nodo fija y las propiedades asociadas. Debe definirse mediante una matriz N x M, donde N es el número de elementos de superficie y M es el número de vértices por elemento (K) más el número de propiedades numéricas (P) adjuntas a lo largo de cada vértice, es decir, M = K + P
"MeshSurf" : [ [ N11 , N11 , ..., N1K , ..., v11 , v12 , ..., v1P ], [ N21 , N21 , ..., N2K , ..., v21 , v22 , ..., v2P ], [ N31 , N31 , ..., N3K , ..., v31 , v32 , ..., v3P ], ... ]
  • "MeshPoly"Define un contenedor flexible para el almacenamiento de parches de superficie de longitud de nodo variable y sus propiedades asociadas. De forma similar a "MeshPLC", debe definirse mediante una matriz con elementos de vectores enteros, pero puede contener metadatos adicionales en cada elemento. Para cada vector que representa un parche de superficie, la primera entrada no numérica, por ejemplo, una estructura o submatriz, del vector marca el inicio de los datos de la propiedad.
"MeshPoly" : [ [ N11 , N12 , N13 , ..., { propiedades }], [ N21 , N22 , N23 , N24 , ...], [ N31 , N32 , N33 , N34 , ..., ..., [ propiedades ] ], ... ]
  • "MeshElem"define un contenedor flexible para el almacenamiento de elementos volumétricos y las propiedades asociadas. Debe definirse mediante una matriz N x M, donde N es el número de elementos de superficie y M es el número de vértices por elemento (K) más el número de propiedades numéricas (P) asociadas a cada vértice, es decir, M = K + P
"MeshElem" : [ [ N11 , N11 , ..., N1K , ..., v11 , v12 , ..., v1P ], [ N21 , N21 , ..., N2K , ..., v21 , v22 , ..., v2P ], [ N31 , N31 , ..., N3K , ..., v31 , v32 , ..., v3P ], ... ]

Primitivas de forma

  • ShapeBox2 : Una caja delimitadora alineada con los ejes (AABB) bidimensional definida por los dos puntos diagonales ("O" como un extremo y "P" como el otro extremo).
"ShapeBox2" : { "O" : [ x0 , y0 ], "P" : [ x1 , y1 ]}
  • ShapeDisc2 : Un disco bidimensional definido por el centro ("O") y el radio "r".
"ShapeDisc2" : { "O" : [ x0 , y0 ], "R" : r }
  • ShapeEllipse : Una elipse bidimensional definida por el centro ("O"), los ejes x e y en el sistema de coordenadas sin rotar ("rx" y "ry"), y el ángulo de rotación "theta0".
"ShapeEllipse" : { "O" : [ x0 , y0 ], "R" : [ r1 , r2 ], "Angle" : theta0 }
  • ShapeLine2 : Una línea bidimensional definida por un punto a lo largo de la línea ("O"), y un vector bidimensional ("V") alineado con la dirección de la línea.
"ShapeLine2" : { "O" : [ x0 , y0 ], "V" : [ v1 , v2 ]}
  • ShapeArrow2 : Un objeto de flecha 2D definido por un punto a lo largo de la línea ("O"), y un vector 2D ("V") alineado con la dirección de la línea, y el tamaño de la punta de flecha se indica mediante el escalar "s".
"ShapeArrow2" : { "O" : [ x0 , y0 ], "V" : [ v1 , v2 ], "Size" : s }
  • ShapeAnnulus : Un anillo bidimensional definido por el centro ("O"), el radio exterior (r1) y el radio interior (r2).
"ShapeAnnulus" : { "O" : [ x0 , y0 ], "R" : [ r1 , r2 ]}
  • ShapeGrid2 : Una cuadrícula bidimensional definida por un extremo de la línea diagonal ("O") y el otro extremo ("P"); el número de segmentos a lo largo de las coordenadas primera y segunda se indica mediante "Nx" y "Ny", respectivamente.
"ShapeGrid2" : { "O" : [ x0 , y0 ], "P" : [ x1 , y1 ], "Paso" : [ Nx , Ny ]}
  • ShapeLine3 : Una línea 3D definida por un punto a lo largo de la línea ("O"), y un vector 3D ("V") alineado con la dirección de la línea.
"ShapeLine3" : { "O" : [ x0 , y0 , z0 ], "V" : [ v1 , v2 , v3 ]}
  • ShapePlane3 : Un plano 3D definido por un punto a lo largo de la línea ("O") y un vector 3D ("N") que apunta en la dirección normal del plano.
"ShapePlane3" : { "O" : [ x0 , y0 , z0 ], "N" : [ v1 , v2 , v3 ]}
  • ShapeBox3 : Una caja delimitadora alineada con los ejes en 3D (AABB) definida por los dos puntos diagonales ("O" como un extremo y "P" como el otro extremo).
"ShapeBox3" : { "O" : [ x0 , y0 , z0 ], "P" : [ x1 , y1 , z1 ]}
  • ShapeDisc3 : Un disco 3D definido por el centro ("O") y el radio "R"; la dirección normal del disco se especifica en "N".
"ShapeDisc3" : { "O" : [ x0 , y0 , z0 ], "R" : r , "N" : [ v1 , v2 , v3 ]}
  • ShapeGrid3 : Una cuadrícula 3D definida por un extremo de la línea diagonal ("O") y el otro extremo ("P"); el número de segmentos a lo largo de las coordenadas x/y/z se indica mediante "Nx", "Ny" y "Nz", respectivamente.
"ShapeGrid3" : { "O" : [ x0 , y0 , z0 ], "P" : [ x1 , y1 , z1 ], "Paso" : [ Nx , Ny , Nz ]}
  • ShapeSphere : Una esfera 3D definida por el centro ("O") y el radio "r".
"ShapeSphere" : { "O" : [ x0 , y0 , z0 ], "R" : r }
  • ShapeCylinder : Un cilindro 3D definido por un extremo del eje cilíndrico ("O") y el otro extremo del eje "P"; el radio del cilindro se especifica en "r".
"ShapeCylinder" : { "O" : [ x0 , y0 , z0 ], "P" : [ x1 , y1 , z1 ], "R" : r }
  • ShapeEllipsoid : Un elipsoide 3D definido por la posición del centro ("O"), los ejes x, y y z en el sistema de coordenadas pre-rotado (rx, ry, rz), y el ángulo de rotación azimutal theta0 y el ángulo de rotación cenital phi0.
"ShapeEllipsoid" : { "O" : [ x0 , y0 , z0 ], "R" : [ rx , ry , rz ], "Angle" : [ theta0 , phi0 ]}
  • ShapeTorus : Un toroide 3D definido por el centro del toroide ("O"), el radio del toroide (r1) y el radio del tubo (r2) y el vector de dirección normal "N".
"ShapeTorus" : { "O" : [ x0 , y0 , z0 ], "R" : r1 , "Rtube" : r2 , "N" : [ v1 , v2 , v3 ]}
  • ShapeCone : Un cono 3D definido por el centro del círculo inferior del cono ("O"), el radio del círculo inferior (r) y la posición de la punta "P".
"ShapeCone" : { "O" : [ x0 , y0 , z0 ], "P" : [ x1 , y1 , z1 ], "R" : r }

Biblioteca de software

Dado que la especificación JMesh se define a partir de la especificación JData , comparte los mismos formatos de serialización de datos subyacentes: JSON para archivos JMesh basados ​​en texto (.jmsh) y BJData / UBJSON para archivos JMesh binarios (.bmsh). La mayoría de los analizadores JSON existentes pueden analizar fácilmente los archivos JMesh basados ​​en texto, y de manera similar, los analizadores UBJSON existentes pueden utilizarse para analizar archivos .bmsh sin modificaciones.

En MATLAB / GNU Octave , se admite guardar datos de malla en formato JMesh en Iso2Mesh , una caja de herramientas de generación de mallas 3D , a través de la savejmeshfunción.

Véase también

Referencias

  1. "Especificación JMesh - Versión 1 Borrador 1" . GitHub . 14 de marzo de 2022.
  2. "NeuroJSON/jmesh" . GitHub . 14 de marzo de 2022.
  • Sitio web oficial
  • Proyecto NeuroJSON
  • Caja de herramientas Iso2Mesh para la generación de mallas 3D
  • Especificación JData (última versión)