I came up with something that seems to work.
The ideas from subsonics and brewbuck are more interesting approaches, but I could not find a way to impliment them.
The main problem was anticipating and handling the various patterns that could occur. Things became much simpler
when I handled the lower and upper ends of the node field independantly from the inner region.
Groups at the lower and upper ends cannot be centered as groups in the inner region can be. At best you can only
left justify or right justify the groups. The node field ends at the lower and upper limits of the color table.
(A group is any sequence of nodes which are too close to each other to align with their actual positions; they would
have to overlap. So they need to be separated, or expanded)
After the ends are aligned, the inner groups (if any) are all handled in a consistant way. The groups will be centered
and if a group impinges on an adjacent node or group, it will merge with it and form a new larger group on the next
pass of the algorithm.
It looks like this:
Code:
void setnodefields(void)
{ int n, n1, n2, gsize, center, g1, g2, x;
for( n = 0; n < nnodes; n++ ) // set initial field positions to actual table positions
nodef[n] = nodep[n];
g1 = 1;
while( g1 ) // repeat until all groups expanded and aligned
{ n = 1;
n1 = 1;
while( nodef[n]-nodef[n-1] <= NODEPITCH && n < nnodes-1 ) // align any group at left end
{ nodef[n] = nodef[n-1]+NODEPITCH;
n1 = ++n;
}
n = nnodes-2; // align any group at right end
n2 = nnodes-2;
while( nodef[n+1]-nodef[n] <= NODEPITCH && n > 0 )
{ nodef[n] = nodef[n+1]-NODEPITCH;
n2 = --n;
}
n = n1;
g1 = 0;
while( ! g1 && n < n2 ) // locate internal group
{ if( nodef[n+1]-nodef[n] < NODEPITCH )
{ g1 = n;
while( nodef[n+1]-nodef[n] < NODEPITCH && n < n2 )
g2 = ++n;
gsize = g2+1-g1; // expand and center group
center = ( nodep[g2]+nodep[g1] )/2;
nodef[g1] = center-( gsize*NODEPITCH-NODEGAP )/2;
for( n = g1+1; n <= g2; n++ )
nodef[n] = nodef[n-1]+NODEPITCH;
}
n++;
}
}
for(n = 0; n < nnodes; n++) // set node rectangles
{ x = n*NODEPITCH;
nsubfield[n].top = 0;
asubfield[n].top = NODEHEIGHT/2;
asubfield[n].bottom = NODEHEIGHT;
if(link[n] == LINK1)
asubfield[n].left = nsubfield[n].left = x+2;
else if(link[n] == LINK2)
asubfield[n].left = nsubfield[n].left = x-2;
else
asubfield[n].left = nsubfield[n].left = nodef[n];
asubfield[n].right = nsubfield[n].right = nsubfield[n].left+NODEWIDTH;
if(altnode[n])
nsubfield[n].bottom = nfield.top+NODEHEIGHT/2;
else
nsubfield[n].bottom = nfield.top+NODEHEIGHT;
}
}