Subversion Repositories display

Rev

Rev 128 | Blame | Compare with Previous | Last modification | View Log | RSS feed


The NOD file holds information about roads and how they connect together.
First read John Mechalas' document at http://sourceforge.net/projects/garmin-img
(henceforth referred to as [JM])

Section NOD 2
=============

Offset | Size   | Description
-------+--------+--------------------------
00     | 1      | Road classification
01     | 3      | Pointer into NOD 1
04     | 1      | Number of bits from offset 0x06
05     | 1      | unknown
06     | varies | Little endian bit mask, with the number
       |        | of bits taken from 0x04

Some definitions of the road classification can be found in [JM].

The bit mask at 06 is read from the least significant bit of a byte
and the bytes are read in little endian order.  Frequently every
bit is set to one.  Since a road only points to one entry in NOD 2 and
yet must connect to more than one node, then this must be telling us
which other nodes (in addition to the one pointed at by 0x01) this road
connects to.

I'm speculating that you read entries in NOD 1 following the one pointed
to, and match them against the bit map.  Where there is a one in the bit
map, you take that node, and where there is a zero you skip it.  If this
is right then the number of bits set to 1 will be the same as the number
of (routing) nodes in the road.

Section NOD 1
=============

Consists of two kinds of area.  One contains records of variable length,
describing nodes in the road network. The other is a set of tables
related to the previous area of nodes. NOD 1 is made up of alternating
node and table areas.

The first byte of each node record provides a pointer to the associated
table area. The offset in NOD 1 of each table area is a multiple of
0x40, thus a node area is limited to a size of about 0x4000 bytes. In
practice, this first byte doesn't appear to exceed 0x30. (It is possible
that 0x40 is not hardcoded, but is instead specified by the "node align"
field in the NOD header.)

The table area starts with a header which specifies the number of
records in the tables, allowing to determine the offset of the next
node area, which follows the table area directly.

Node area
---------
The first area consists of variable sized records.  There are pointers
from NOD 2 and NOD 3 to these records.  There is often more than one
pointer to the same record.  There also appears to be cases where there
are no pointers (or none that have been discovered).

Each node record starts with a header.

Offset | Size   | Description
-------+--------+--------------------------
00     | 1      | Pointer to tables area
01     | 1      | Flags
02     | varies | Coordinate offsets

The following flags are known.

Flag   | Description
-------+----------------------------
0x20   | 2 byte coordinate offsets
0x10   | Restrictions
0x08   | Boundary node

If the flag 0x10 is set, there are routing restrictions at this node. The
flag signifies the presence of restrictions data at the end of the record.

The flag 0x08 is set if the node is a boundary node, that is if it lies
on the boundary of the IMG tile. In that case, there will be a pointer
from NOD 3 to this record.

Furthermore, the flags 0x40 and 0x04 are usually set. Their purpose is yet
to be determined. Possibly, these flags signify the presence of link and
position data in the record.

The coordinate offsets are relative to the base coordinates in the
header of the following tables area. If the flag 0x20 is set, each
coordinate offset is a two byte value, else both offsets are stored
in three bytes (12 bits each).

Links
-----
Following the coordinate offsets comes a sequence of variable length
records which describe links to other nodes. The last of these records
is marked by bit 0x80 in the second byte (Flags B below).

Links may point to nodes in the same or another node area in NOD 1. We
call the latter inter-area links, the former intra-area links. A link
may point to a directly adjacent node in the road network (a "direct
link"), or to a node that may be reached by following a sequence of
direct links (an "indirect link"). For direct links, there is always
an opposite direct link from the destination node. This is not the
case for indirect links. Indirect links appear to always point to
nodes on the same polyline.

It is not clear whether inter-area indirect links are allowed.

The destination node of an intra-area link is given by a signed 14-bit
integer stored in bytes two and three. Byte three is the low byte, the
low 6 bits of byte two are the high bits.

An inter-area link is signified by the presence of bit 0x40 in the
second byte. In that case, the low six bits of byte two are an index
into Table B in the following tables area, which holds a pointer to
another nodes area of NOD 1.

Notation:
here          | libgarmin
--------------+--------------
direct link   | arc
indirect link | link

A link starts as follows.

Offset | Size   | Decription
-------+--------+-------------------------------------
00     | 1      | Flags A
01     | 1 or 2 | Flags B and pointer

Flags A:

Mask   | Description
-------+--------------------
0x80   | New direction
0x40   | Sign
0x07   | Destination class

Flags B:

Mask   | Description
-------+--------------------
0x80   | Last link
0x40   | Inter-area link

The links from a node appear to be grouped according to the direction
in which they leave the node. The first link within such a group is a
direct link, while following links will be indirect (leading to nodes
further along the road than the one pointed at by the previous direct
link). The bit 0x80 in the first byte signifies that a new group starts.
It is not set at the start of the first group. Thus, a link is direct
if it is the first link in a node record, or if bit 0x80 is set in its
first byte. Other links are indirect.

Each link has an orientation which is stored in bit 0x40 of Flags A.
This orientation is consistent within a polyline.

Direct links:

After the pointer, a direct link has a one byte index into the
following Table A, which gives some parameters for the segment and a
pointer to the road in NET. This is followed by a byte which usually
(but not always) agrees with the reverse link, and which may be
related to the segment length.

Following this is a variable amount of data is a sequence of bytes of
unknown length, between one and three bytes long. The first byte may
represent the direction in which the segment heads out of the node,
with North=0x00, East=0x40. In the absence of bits 0x10 and 0x08 in
Flags A, there appears to be more than one byte if and only if 0x20 is
set in Flags A. This may be related to the segment being curved. In
some cases, bit 0x08 in Flags correlates with long segments, whose
length would not fit into the length byte.

Indirect links:

These have no segment index and no byte agreeing with the opposite
link, if present. There are one or two bytes of unidentified data.

Restrictions:

If node flag 0x10 was set, the links are followed by a variable length
sequence of offsets into Table C. The corresponding record in Table C
describes a restriction at the node.

Depending on the size of the largest Table C in NOD 1, these may be
bytes or little-endian shorts (or larger?). It is unknown whether
their size may be determined without reading the header of each tables
area.  The last offset has its highest bit set.

Tables area
-----------
The second kind of subsection in NOD 1 occurs once after each node
area. It always starts on a 0x40 boundary in the section and zero
padding bytes are used achieve this alignment. There appear to be at
least 0x40 of these zero padding bytes always, such that an offset of
0x40 less would also appear to have sufficed.

The table area starts with a 9 byte header, and is followed by up to
three tables we call Table A, B and C.

There is a header area of 9 bytes. It is unclear whether the first
byte may contain other data in the higher bits. Only values up to
2 have been observed.

Offset | Size   | Description
-------+--------+------------------------------
00     | 1      | size of Table C size field
01     | 3      | base longitude
04     | 3      | base latitude
07     | 1      | number of records in Table A
08     | 1      | number of records in Table B

Table A contains fixed length records (always size 5?) that represent
road segments (parts of roads between adjacent nodes) that meet nodes
in the preceding nodes area. These contain pointers into NET and
routing data (speed, oneway, road class, toll, what vehicle types are
allowed).

Table B contains offsets into NOD 1. These are the destinations of
inter-area links from the preceding nodes area.

Table B is followed by one or more bytes giving the size of Table C.
If the first byte of the header before was zero, there is one zero
byte. If it was non-zero, there are that many bytes giving the byte
size of Table C as a little-endian integer.

Table C contains data that is related to restrictions. In the common
case, it contains records of size 11 that are of the following form.

Offset | Size   | Description
-------+--------+---------------------------
00     | 3      | Header (05 40 00)
03     | 2      | Source node
05     | 2      | Restriction node
07     | 2      | Destination node
09     | 1      | Source segment
10     | 1      | Destination segment

Such a record describes a restriction at "Restriction node" coming
from "Source node" via "Source segment" headed for "Destination node"
along "Destination segment".

The segments are given by indices into the preceding Table B.

The nodes are given by little-endian unsigned shorts which are negative
offsets from the start of the tables area.

It is unclear what inter-section restrictions or restrictions at
boundry nodes look like, if they are possible.

Section NOD 3
=============

These are boundary nodes that are on the edge of the map, and connect to
other maps in the set.  They are described in [JM].