The Esri TIN format is a popular yet proprietary geospatial vector data format for geographic information system (GIS) software for storing elevation data as a triangulated irregular network. It is developed and regulated by Esri, US. The Esri TIN format can spatially describe elevation information including breaking edge features. Each points and triangle can carry a tag information.
A TIN stored in this file format can have any shape, cover multiple regions (e.g. islands) and contain holes (e.g. lakes).
In 2007 a reverse-engineered description of Esri TIN format came to light. Since then, the Virtual Terrain Project, an open-source software, has implemented support for reading the format, without the need of ArcGIS being installed.
Overview
The Esri TIN format is a digital vector storage format for storing elevation information including breaking edge features. The Esri TIN format was introduced with ArcView GIS.
The Esri TIN format consists of a collection of files with specific filenames and a common filename extension, stored in the same directory. Most of the files are mandatory files (tdenv.adf, tedg.adf, thul.adf, tmsk.adf, tmsx.adf, tnod.adf, tnxy.adf and tnz.adf), optionally a file containing the coordinate system and projection information (prj.adf) and files containing point tag information (tnval.adf and tndsc.adf) and triangle tag information (ttval.adf and ttdsc.adf) can be given.
Mandatory files tdenv.adf — header and statistical data tedg.adf — edges data and topology thul.adf — outer and inner hull polygon data tmsk.adf — mask data, masks invisible triangles tmsx.adf — index file for tmsk.adf tnod.adf — triangle node data tnxy.adf — position information (x and y coordinates) tnz.adf — height information (z values)
The endianness of most of the files is big-endian. tmsk.adf, tmsx.adf and tdenv.adf have mixed endianness.
Other files prj.adf — projection description, using a well-known text representation of coordinate reference systems; are single line {B286C06B-0879-11D2-AACA-00C04FA33C20} signifies an unknown coordinate system tndsc.adf — statistic on point tag usage tnval.adf — point tag data ttdsc.adf — description of triangle tag data ttval.adf — triangle tag data
The endianness of the file tndsc.adf and tnval.adf is little-endian.
Files generated by ArcGIS 10 tnodinfo.adf — point types and more teval.adf — edges data tdenv9.adf — the file tdenv.adf renamed
Size of file A TIN with n points (incl. superpoints) and k triangles, the file sizes calculate to: tnxy.adf : 16*n bytes tnz.adf : 4*n bytes tnod.adf : 12*k bytes tedg.adf : 12*k bytes tmsx.adf : 116 bytes tdenv.adf/tdenv9.adf : 104 bytes tmsk.adf : 132 + 4*ceiling(k/32) bytes thul.adf : min. 12 bytes, depends on the number of points in the convex hull polygon tndsc.adf : 24* the number of tag entries specified in tndsc.adf bytes (see below) tnval.adf : 4*n' bytes (n': number of tagged points, incl. superpoints; see below) tnodinfo.adf : 2*n bytes teval.adf : 16* the number of breaking edges entries specified in tdenv9.adf bytes (see below)
Mandatory files
tnxy.adf - X and Y coordinates of the points of the TIN
Contains and array of X and Y coordinate values, one pair for each point of the TIN. The data set for each point can be described by the following structure:
Bytes Type Endianness Usage 0–7 double big X coordinate value 8–15 double big Y coordinate value
tnz.adf - Z coordinates of the points of the TIN
Contains an array of Z coordinate values, one for each point of the TIN. The values are in same order as the values in tnxy.adf and together store the 3 dimensional coordinate of each point of the TIN. The data set for each point can be described by the following structure:
Bytes Type Endianness Usage 0–3 float big Z coordinate value
tnod.adf - Indices of the points that form the triangles of the TIN
Contains an array of indices to the points that form the triangles of the TIN, 3 indices for each triangle. The indices are in the range of 1 to the number of points ([1, # of points]). The front face of a triangle (usually the upper side) is that face, that has the 3 points/corners ordered clockwise when viewed. The data set for each triangle can be described by the following structure:
Bytes Type Endianness Usage 0–3 int32 big Index of the first point of a triangle 4–7 int32 big Index of the second point of a triangle 8–11 int32 big Index of the third point of a triangle
tedg.adf - Topology of the triangles and the type of its edges
Contains information about the topology of the triangles and the type of their edges.
There is an entry for each triangle with each 3 indices, that point to the position (number of the index) in tnod.adf file to identify the triangle, that shares an edge with the triangle described by the current data set, and the point of that triangle, that form that edge.
For each triangle in tnod.adf exists a data set at the same file location in tedg.adf. Each of the values point to the location in tnod.adf, where the point is specified (the index of that point) that form an edge. At the same time, since the location in tnod.adf and tedg.adf correspond, each of the values point to the location in tedg.adf, where the location of the value is specified. Rule: If edge a of triangle A points to edge b of triangle B, then edge b of triangle B must point to edge a of triangle A. Since edge definition in tedg.adf and point definition in tnod.adf of each triangle are at the same location the files, the indices in tedg.adf point to the point definition in tnod.adf of the neighbouring triangles.
The indices encode the actual index and type of the edge. The actual indices are not file offsets in bytes, but rather in int32 values, in the range of 1 to the number of points ([1, # of points]). If the value is negative (bit 31 is set) the edge is a breaking edge. Furthermore, bit 30 of the int32 values is used to determine if the edge is a hard or soft breaking edge. If the actual index would be 1234 (0x000004D2) then a hard breaking edge would be encoded as -1234 (0xFFFFFB2E) and a soft breaking edge as -1073743058 (0xBFFFB2E). The edge definition of the neighbouring triangle must mirror the edge type. ATTENTION: This behaviour has changed since ArcGIS 10. Please compare with the information given in section 'Format changes and files new with ArcGIS 10'.
The data set for each triangle can be described by the following structure:
Bytes Type Endianness Usage 0–3 int32 big Encoded index of point definition (index of a point) of the neighbouring triangle in tnod.adf that form an edge with the first point of the triangle 4–7 int32 big Encoded index of point definition (index of a point) of the neighbouring triangle in tnod.adf that form an edge with the second point of the triangle 8–11 int32 big Encoded index of point definition (index of a point) of the neighbouring triangle in tnod.adf that form an edge with the third point the a triangle
tdenv.adf - Header or statistics
This file contains information that could be seen as a mix of file header and statistic data.
Bytes Type Endianness Usage 0–3 int32 big Number of points (regular points and superpoints) 4–7 int32 big Number of triangles 8–11 int32 big Number of indices and separators in thul.adf 12–15 int32 big 0 (in version 9) / number of breaking edge entries in teval.adf (version 10) 16–19 int32 big Number of triangles, not masked in tmsk.adf 20–23 int32 big Number of regular points 24–27 int32 big Number of superpoints 28–31 float big Minimum height (Z value of the lowest point; zmin) 32–35 float big Maximum height (Z value of the highest point; zmax) 36–39 int32 ? big Unknown, different values encountered 40–47 double big Minimum extent in X direction (xmin) 48–55 double big Minimum extent in Y direction (ymin) 56–63 double big Maximum extent in X direction (xmax) 64–71 double big Maximum extent in Y direction (ymax) 72–79 double ? big Unknown, always 0 80–87 double ? big Unknown, different values encountered 88–91 int32 big Unknown, always 70001 (version 9) / 90001 (version 10); maybe a version number 92–95 int32 little Number of used tags (incl. tag 0 for superpoints) 96–99 int32 ? big Unknown, always 0; maybe unused 100–103 int32 ? big Unknown, always 0; maybe unused
thul.adf - Hull, bounding polygon and holes
Contains an array of indices and separators, that defines the outer boundary of the TIN and its holes. The indices are in the range of 1 to the number of points ([1, # of points]). The separators are -1 (0xFFFFFFFF) and zero (0).
If the TIN is constructed using superpoints (usually the first 4 points), thul.adf lists the indices of these points and then -1 (0xFFFFFFFF). After the separator follows one or more lists of indices that form bounding polygons (outer boundaries) and maybe holes (inner boundaries). These lists are separated by zero (0) values.
If the TIN does not contain superpoints, thul.adf starts with the -1 (0xFFFFFFFF) separator, which is followed by one or more lists of indices that form bounding polygons (outer boundaries) and maybe holes (inner boundaries). These lists are separated by zero (0) values.
The indices and separators are 4 byte integer values (int32), stored in big-endian byte order.
tmsk.adf - Mask
Contains an array of bits (stored in 4 byte integers) that specify the visibility of the triangles of the TIN. This can be used to hide the triangles inside of terrain holes or outside the terrain (outside the outer boundaries).
The file is stored using the same structures (header and records) as a shapefile, but since it only stores the visibility values of the triangles many fields of the header are used.
The file header is fixed at 100 bytes in length and contains 17 fields; nine 4-byte (32-bit signed integer or int32) integer fields followed by eight 8-byte (double) signed floating point fields:
Bytes Type Endianness Usage 0–3 int32 big File code (always hex value 0x0000270a) 4–23 int32 big Unused; five uint32 24–27 int32 big File length (in 16-bit words, including the header) 28–31 int32 little Version 0 ; probably unused 32–35 int32 little Shape type 0 ; probably unused 36–43 double little Minimum X extent (always 0.0) ; unused 44–51 double little Minimum Y extent (always 0.0) ; unused 52–59 double little Maximum X extent (always 0.0) ; unused 60–67 double little Maximum Y extent (always 0.0) ; unused 68–75 double little Minimum Z extent (always 0.0) ; unused 76–83 double little Maximum Z extent (always 0.0) ; unused 84–91 double little Minimum M extent (always 0.0) ; unused 92–99 double little Maximum M extent (always 0.0) ; unused
The file then contains at least 2 records. Each record is prefixed with a record-header of 8 bytes:
Bytes Type Endianness Usage 0–3 int32 big Record number (1-based) 4–7 int32 big Record length (in 16-bit words)
Following the record header is the actual data.
Record 1: The data of record number 1 is 2 word long and contains only the size of the data of record number 2 in 4 byte integers, stored as 4 byte integer (big-endian) itself.
Record 2: The data of record number 2 contain the following variable length structure:
Bytes Type Endianness Usage 0–3 int32 big Number of integer in the mask array 4–7 int32 big Unused; always 0; maybe an offset (bits, bytes or integers?) into the mask array, where the actual mask bits start 8–11 int32 big Number of used bits in the mask array 12– uint32[] big Mask array
Bit 0 (least significant bit) of the first integer contains the visibility flag (invisible if set to 1) of the first triangle defined in tnod.adf. Bit 1 of the first integer contains the visibility flag (invisible if set to 1) of the second triangle, and so on. All 32 bits of the integers get used (no sign bit).
Record 0: Records with the record number 0 must be ignored.
tmsx.adf - Index file for the mask