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):
field | type | size | comment |
dummy | int(4B) | 1 | for FORTRAN compatibility |
tag | char(1B) | 16 | identifies the file type. Value : "NDSKEL" |
dummy | int(4B) | 1 | |
dummy | int(4B) | 1 | |
comment | char(1B) | 80 | a comment on the file (string) |
ndims | int(4B) | 1 | number of dimensions |
dims | int(4B) | 20 | dimension of underlying grid (0=none, ndims values are read) |
x0 | double(8B) | 20 | origin of bounding box (ndims first values are meaningful) |
delta | double(8B) | 20 | size of bounding box (ndims first values are meaningful) |
nsegs | int(4B) | 1 | number of segments |
nnodes | int(4B) | 1 | number of nodes |
nsegdata | int(4B) | 1 | number of additional data associated to segments. |
nnodedata | int(4B) | 1 | number of additional data associated to nodes. |
dummy | int(4B) | 1 | |
dummy | int(4B) | 1 | this block is ommited if nsegdata=0 |
seg_data_info | char(1B) | 20×nsegdata | name of the segment data field |
dummy | int(4B) | 1 | this block is ommited if nsegdata=0 |
dummy | int(4B) | 1 | this block is ommited if nnodedata=0 |
node_data_info | char(1B) | 20×nnodedata | name of the node data field |
dummy | int(4B) | 1 | this block is ommited if nnodedata=0 |
dummy | int(4B) | 1 | |
segpos | float(4B) | 2×nsegs×ndims | coordinates of segment extremities |
dummy | int(4B) | 1 | |
dummy | int(4B) | 1 | |
nodepos | float(4B) | nnodes×ndims | coordinates of nodes |
dummy | int(4B) | 1 | |
dummy | int(4B) | 1 | |
segdata | double(8B) | nsegdata×nsegs | value of the segments data fields |
dummy | int(4B) | 1 | |
dummy | int(4B) | 1 | |
nodedata | double(8B) | nnodedata×nnodes | value of the nodes data fields |
dummy | int(4B) | 1 | |
dummy | int(4B) | 1 | following block is repeated for each node (×nnodes). |
pos_index | int(4B) | 1 | index in the nodepos/nodedata arrays |
flags | int(4B) | 1 | flags (identify boundary nodes) |
nnext | int(4B) | 1 | number of connected arcs |
type | int(4B) | 1 | critical index (ndims+1 for bifurcations / trimmed arc axtremity) |
index | int(4B) | 1 | index of this node |
nsegs | int(4B) | nnext | number of segments in each connected arc |
* | * | * | blue section repeated for each connected arc (×nnext) |
nextNode | int(4B) | 1 | index of the other node of the arc |
nextSeg | int(4B) | 1 | index of the first segment on the arc |
dummy | int(4B) | 1 | |
dummy | int(4B) | 1 | following block is repeated for each segment (×nsegs). |
pos_index | int(4B) | 1 | index in the segpos/segdata arrays |
nodes | int(4B) | 2 | index of the 2 nodes at the endpoints of the current arc. |
flags | int(4B) | 1 | flags (identify boundary nodes) |
index | int(4B) | 1 | index of this segment |
next_seg | int(4B) | 1 | index of the next segment in the node (-1 if none) |
prev_seg | int(4B) | 1 | index of the previous segment in the node (-1 if none) |
dummy | int(4B) | 1 | |