lib/spaceSaver.c

Go to the documentation of this file.
00001 /* spaceSaver - routines that help layout 1-D objects into a
00002  * minimum number of tracks so that no two objects overlap
00003  * within a single track. 
00004  *
00005  * This file is copyright 2002 Jim Kent, but license is hereby
00006  * granted for all use - public, private or commercial. */
00007 
00008 #include "common.h"
00009 #include "spaceSaver.h"
00010 
00011 static char const rcsid[] = "$Id: spaceSaver.c,v 1.10 2004/09/02 20:08:44 kent Exp $";
00012 
00013 
00014 struct spaceSaver *spaceSaverMaxCellsNew(int winStart, int winEnd, int maxRows, int maxCells)
00015 /* Create a new space saver around the given window.   */
00016 {
00017 struct spaceSaver *ss;
00018 float winWidth;
00019 
00020 AllocVar(ss);
00021 ss->winStart = winStart;
00022 ss->winEnd = winEnd;
00023 ss->maxRows = maxRows;
00024 winWidth = winEnd - winStart;
00025 ss->cellsInRow = winWidth;
00026 while (ss->cellsInRow > maxCells)
00027     ss->cellsInRow /= 2;
00028 ss->scale = ss->cellsInRow/winWidth;
00029 return ss;
00030 }
00031 
00032 struct spaceSaver *spaceSaverNew(int winStart, int winEnd, int maxRows)
00033 /* Create a new space saver around the given window.   */
00034 {
00035 return spaceSaverMaxCellsNew(winStart, winEnd, maxRows, 800);
00036 }
00037 
00038 void spaceSaverFree(struct spaceSaver **pSs)
00039 /* Free up a space saver. */
00040 {
00041 struct spaceSaver *ss = *pSs;
00042 if (ss != NULL)
00043     {
00044     struct spaceRowTracker *srt;
00045     for (srt = ss->rowList; srt != NULL; srt = srt->next)
00046         freeMem(srt->used);
00047     slFreeList(&ss->rowList);
00048     slFreeList(&ss->nodeList);
00049     freez(pSs);
00050     }
00051 }
00052 
00053 static boolean allClear(bool *b, int count)
00054 /* Return TRUE if count bools starting at b are all 0 */
00055 {
00056 int i;
00057 for (i=0; i<count; ++i)
00058     if (b[i])
00059         return FALSE;
00060 return TRUE;
00061 }
00062 
00063 struct spaceNode *spaceSaverAddOverflow(struct spaceSaver *ss, int start, int end, 
00064                                         void *val, boolean allowOverflow)
00065 /* Add a new node to space saver. Returns NULL if can't fit item in
00066  * and allowOverflow == FALSE. If allowOverflow == TRUE then put items
00067  * that won't fit in last row. */
00068 {
00069 int cellStart, cellEnd, cellWidth;
00070 struct spaceRowTracker *srt, *freeSrt = NULL;
00071 int rowIx = 0;
00072 struct spaceNode *sn;
00073 
00074 if (ss->isFull)
00075     return NULL;
00076 
00077 if ((start -= ss->winStart) < 0)
00078     start = 0;
00079 end -= ss->winStart;    /* We'll clip this in cell coordinates. */
00080 
00081 cellStart = round(start * ss->scale);
00082 cellEnd = round(end * ss->scale)+1;
00083 if (cellEnd > ss->cellsInRow)
00084     cellEnd = ss->cellsInRow;
00085 cellWidth = cellEnd - cellStart;
00086 
00087 /* Find free row. */
00088 for (srt = ss->rowList; srt != NULL; srt = srt->next)
00089     {
00090     if (allClear(srt->used + cellStart, cellWidth))
00091         {
00092         freeSrt = srt;
00093         break;
00094         }
00095     ++rowIx;
00096     }
00097 
00098 /* If no free row make new row. */
00099 if (freeSrt == NULL)
00100     {
00101     if (ss->rowCount >= ss->maxRows)
00102         {
00103         /* Abort if too many rows and no
00104            overflow allowed. */
00105         if(!allowOverflow) 
00106             {
00107             ss->isFull = TRUE;
00108             return NULL;
00109             }
00110         }
00111     else 
00112         {
00113         AllocVar(freeSrt);
00114         freeSrt->used = needMem(ss->cellsInRow);
00115         slAddTail(&ss->rowList, freeSrt);
00116         ++ss->rowCount;
00117         }
00118     }
00119 
00120 /* Mark that part of row used (except in overflow case). */
00121 if(freeSrt != NULL)
00122     memset(freeSrt->used + cellStart, 1, cellWidth);
00123 
00124 /* Make a space node. If allowing overflow it will
00125  all end up in the last row. */
00126 AllocVar(sn);
00127 sn->row = rowIx;
00128 sn->val = val;
00129 slAddHead(&ss->nodeList, sn);
00130 return sn;
00131 }
00132 
00133 struct spaceNode *spaceSaverAdd(struct spaceSaver *ss, 
00134         int start, int end, void *val)
00135 /* Add a new node to space saver. Returns NULL if can't fit
00136  * item in. */
00137 {
00138 return spaceSaverAddOverflow(ss, start, end, val, FALSE);
00139 }
00140 
00141 void spaceSaverFinish(struct spaceSaver *ss)
00142 /* Tell spaceSaver done adding nodes. */
00143 {
00144 slReverse(&ss->nodeList);
00145 }

Generated on Tue Dec 25 18:39:32 2007 for blat by  doxygen 1.5.2