This is the native binary format of DisPerSE. Functions for reading and writing NDskl format in C can be found within the file ${DISPERSE_SRC}/src/C/NDskeleton.c (see functions Load_NDskel, Save_NDskel and also Create_NDskel). In this format, the arcs of the Morse-Smale complex are described as arrays of nodes and segments with data associated to each of them. Each node contains information on critical points (which may also be bifurcations points or trimmed extremities of filaments). Each segment contains information on the local geometry of the arcs and global properties of the skeleton.

When using the C functions from Disperse, data is loaded into the following C structure which is close to the actual structure of the file (see file ${DISPERSE_SRC}/src/C/NDskeleton.h):

struct NDskl_seg_str {
   int nodes[2];  // index of the nodes at the extremity of the arc. Segment is oriented from nodes[0] toward nodes[1]
   float *pos;  // points to appropriate location in segpos
   int flags;  // non null if on boundary 
   int index;  // index of the segment in the Seg array
   double *data;  // points to the nsegdata supplementary data for this segment
   struct NDskl_seg_str *Next; // points to next segment in the arc, NULL if extremity (->connects to nodes[1])
   struct NDskl_seg_str *Prev; // points to previous segment in the arc, NULL if extremity (->connects to nodes[0])
 }; 
 typedef struct NDskl_seg_str NDskl_seg;
 struct NDskl_node_str {
   float *pos;  // points to appropriate location in nodepos
   int flags;  // non null if on boundary 
   int nnext;  // number of arcs connected
   int type;  // critical index
   int index;  // index of the node in the Node array
   int *nsegs; // number pf segments in each of the the nnext arcs
   double *data;   // points to the nnodedata supplementary data for this segment
   struct NDskl_node_str **Next;  // points to the node at the other extremity of each of the nnext arcs
   struct NDskl_seg_str **Seg;   // points to the first segment in the arcs, starting from current node.
 }; 
 typedef struct NDskl_node_str NDskl_node;
 typedef struct NDskel_str {
   char comment[80];
   
   int ndims;  // number of dimensions
   int *dims;  // dimension of the underlying grid, only meaningfull when computed from a regular grid
   double *x0;  // origin of the bounding box
   double *delta;  // dimension of the bounding box
    
   int nsegs;  // number of segments
   int nnodes;  // number of nodes
   
   int nsegdata;  // number of additional data for segments
   int nnodedata;  // number of additional data for nodes
   char **segdata_info;  // name of additional fields for segments
   char **nodedata_info;  // name of additional fields for nodes
   
   float *segpos;  // positions of the extremities of segments (2xndims coords for each segment)
   float *nodepos; // positions of the nodes (ndims coords for each segment)
   double *segdata; // additional data for segments (nsegs times nsegdata consecutive values)
   double *nodedata; // additional data for nodes (nnodes times nnodedata consecutive values)
   
   NDskl_seg *Seg;  // segment array (contains all segs)
   NDskl_node *Node;  // nodes array (contains all nodes)
 } NDskel;



The NDskl binary format is organized as follows (blocks are delimited by dummy variables indicating the size of the blocks for FORTRAN compatibility, but they are ignored in C):

NDskl binary format
fieldtypesizecomment
dummyint(4B) 1 for FORTRAN compatibility
tagchar(1B)16identifies the file type. Value : "NDSKEL"
dummyint(4B) 1
dummyint(4B) 1
commentchar(1B)80a comment on the file (string)
ndimsint(4B)1number of dimensions
dimsint(4B)20dimension of underlying grid (0=none, ndims values are read)
x0double(8B)20origin of bounding box (ndims first values are meaningful)
deltadouble(8B)20size of bounding box (ndims first values are meaningful)
nsegsint(4B)1number of segments
nnodesint(4B)1number of nodes
nsegdataint(4B)1number of additional data associated to segments.
nnodedataint(4B)1number of additional data associated to nodes.
dummyint(4B) 1
dummyint(4B) 1 this block is ommited if nsegdata=0
seg_data_infochar(1B)20×nsegdataname of the segment data field
dummyint(4B) 1 this block is ommited if nsegdata=0
dummyint(4B) 1 this block is ommited if nnodedata=0
node_data_infochar(1B)20×nnodedataname of the node data field
dummyint(4B) 1 this block is ommited if nnodedata=0
dummyint(4B) 1
segposfloat(4B)2×nsegs×ndimscoordinates of segment extremities
dummyint(4B) 1
dummyint(4B) 1
nodeposfloat(4B)nnodes×ndimscoordinates of nodes
dummyint(4B) 1
dummyint(4B) 1
segdatadouble(8B)nsegdata×nsegsvalue of the segments data fields
dummyint(4B) 1
dummyint(4B) 1
nodedatadouble(8B)nnodedata×nnodesvalue of the nodes data fields
dummyint(4B) 1
dummyint(4B) 1 following block is repeated for each node (×nnodes).
pos_indexint(4B)1index in the nodepos/nodedata arrays
flagsint(4B)1flags (identify boundary nodes)
nnextint(4B)1number of connected arcs
typeint(4B)1critical index (ndims+1 for bifurcations / trimmed arc axtremity)
indexint(4B)1index of this node
nsegsint(4B)nnextnumber of segments in each connected arc
* **blue section repeated for each connected arc (×nnext)
nextNodeint(4B)1index of the other node of the arc
nextSegint(4B)1index of the first segment on the arc
dummyint(4B) 1
dummyint(4B) 1 following block is repeated for each segment (×nsegs).
pos_indexint(4B)1index in the segpos/segdata arrays
nodesint(4B)2index of the 2 nodes at the endpoints of the current arc.
flagsint(4B)1flags (identify boundary nodes)
indexint(4B)1index of this segment
next_segint(4B)1index of the next segment in the node (-1 if none)
prev_segint(4B)1index of the previous segment in the node (-1 if none)
dummyint(4B) 1