Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields  

ToySegmentList.c

00001 /***************************************************************************
00002                           ToySegmentList.c  -  Core code for creating,
00003     modifying, copying, sorting, and deleting linked lists of segments.
00004                              -------------------
00005     begin                : Sat Jan 25 2003
00006     copyright            : (C) 2003 by Tyler Montbriand
00007     student #            : 200200370
00008     class                : CS330
00009     email                : monttyle@heavyspace.ca
00010 ***************************************************************************/
00011 
00012 #include <malloc.h>
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include "ToySegment.h"
00016 #include "ToySegmentList.h"
00017 
00018 /*  Remove 'node' from list.  Does not deallocate.  */
00019 void TMM_RemoveFromList(SegList *node)
00020 {
00021   /*  Can't do anything with nonexistent nodes  */
00022   if(node==NULL)  return;
00023 
00024   /*  Set nodes before/after it to point around it  */
00025   if(node->prev!=NULL)  node->prev->next=node->next;
00026   if(node->next!=NULL)  node->next->prev=node->prev;
00027 
00028   /*  Have this node point to nothing, for safety's sake  */
00029   node->prev=node->next=NULL;
00030 }
00031 
00033 void TMM_InsertBefore(SegList *pos, SegList *node)
00034 {
00035   node->next=pos;
00036 
00037   if(pos!=NULL)
00038   {
00039     node->prev=pos->prev;
00040     if(pos->prev!=NULL) pos->prev->next=node;
00041     pos->prev=node;
00042   }
00043 }
00044 
00046 void TMM_InsertAfter(SegList *pos, SegList *node)
00047 {
00048   /*  First, set up the new node  */
00049   node->prev=pos;
00050   if(pos==NULL) node->next=NULL;
00051   else          node->next=pos->next;
00052 
00053   if(pos!=NULL)
00054   {
00055     if(pos->next!=NULL)
00056     {
00057       pos->next->prev=node;
00058     }
00059     pos->next=node;
00060   }
00061 }
00062 
00066 SegList *TMM_OrderedInsert(SegList *list, SegList *node)
00067 {
00068   /*  If list doesn't exist, start a new list */
00069   if(list==NULL)
00070   {
00071     node->next=node->prev=NULL;
00072     return(node);
00073   }
00074 
00075   /*  Search until position is found  */
00076   while(list!=NULL)
00077   {
00078     if(list->seg.pos>node->seg.pos)
00079     {
00080       TMM_InsertBefore(list,node);
00081       return(TMM_SeekSegListHead(list));
00082     }
00083     else if(list->next==NULL)
00084     {
00085       TMM_InsertAfter(list,node);
00086       return(TMM_SeekSegListHead(list));
00087     }
00088 
00089     list=list->next;
00090   }
00091 
00092   /*  If this has happened something has gone REALLY wrong */
00093   return(NULL);
00094 }
00095 
00096 /*  Returns size of list in nodes  */
00097 int TMM_SegListSize(SegList *list)
00098 {
00099   int len=0;
00100   /*  Yes, we could optimize this algorithm by counting
00101       forwards and backwards.  but this works, so it's
00102       good enough for now.                              */
00103   list=TMM_SeekSegListHead(list);
00104   /*  A NULL list is actally valid - it means emtpy */
00105   if(list==NULL)  return(0);
00106 
00107   do  /*  Count every node in the list  */
00108   {
00109     len++;
00110     list=list->next;
00111   } while(list!=NULL);
00112 
00113   return(len);  /*  Return length */
00114 }
00115 
00116 
00117 /* Returns 1st memory space capable of holding n elements, or -1 if none
00118 */
00119 int TMM_FindSegSpace(SegList *list, int n)
00120 {
00121   list=TMM_SeekSegListHead(list);
00122 
00123   while(list!=NULL)
00124   {
00125     if(list->seg.len>=n)        return(list->seg.pos);
00126     list=list->next;
00127   }
00128 
00129   return(-1);
00130 }
00131 
00132 SegList *TMM_CopySegList(SegList *list)
00133 {
00134   SegList *copy=NULL;
00135   list=TMM_SeekSegListHead(list);
00136 
00137   while(list!=NULL)
00138   {
00139     SegList *node=TMM_CreateSegList(list->seg.pos,list->seg.len,NULL,NULL);
00140     copy=TMM_AppendSegList(copy,node);
00141     list=list->next;
00142   }
00143   return(copy);
00144 }
00145 
00146 SegList *TMM_AddAreaToSegList(SegList *list, int pos, int len)
00147 {
00148   /* ToySegment seg={pos,len};*/
00149   ToySegment seg;
00150   int intersect=0;
00151   SegList *head;
00152 
00153   seg.pos=pos;
00154   seg.len=len;
00155 
00156   if(list==NULL)        return(NULL);
00157 
00158   list=TMM_SeekSegListHead(list);
00159   head=list;
00160 
00161   while(list!=NULL)
00162   {
00163     intersect|=TMM_AreaIntersectsSeg(&seg,&(list->seg));
00164     list=list->next;
00165   }
00166   list=head;
00167 
00168   if(intersect)
00169   {
00170     return(list);
00171   }
00172   else
00173   {
00174     SegList *nlist=TMM_CreateSegList(seg.pos,seg.len,NULL,NULL);
00175     TMM_AppendSegList(head,nlist);
00176     list=TMM_SortSegList(list);
00177     list=TMM_MergeSegList(list);
00178     return(list);
00179   }
00180 }
00181 
00182 SegList *TMM_MergeSegList(SegList *list)
00183 {
00184   SegList *head;
00185 
00186   if(list==NULL)        return(NULL);
00187 
00188   list=TMM_SeekSegListHead(list);
00189   head=list;
00190 
00191   while(list->next!=NULL)
00192   {
00193     /* If the two segments are end-to-end, merge 'em - add length to the
00194        first one, and delete the following. */
00195     if(list->seg.len+list->seg.pos == list->next->seg.pos)
00196     {
00197       SegList *temp=list->next;
00198 
00199       list->seg.len+=temp->seg.len;
00200 
00201       if(temp->prev!=NULL)      temp->prev->next=temp->next;
00202       if(temp->next!=NULL)      temp->next->prev=list;
00203 
00204       free(temp);
00205 
00206       continue;
00207     }
00208 
00209     list=list->next;
00210   }
00211 
00212   return(head);
00213 }
00214 
00215 int TMM_CompSegList(const SegList *l1, const SegList *l2)
00216 {
00217   if(l1->seg.pos>l2->seg.pos)       return(1);
00218   else if(l1->seg.pos<l2->seg.pos)  return(-1);
00219   else                              return(0);
00220 }
00221 
00222 SegList *TMM_SortSegList(SegList *list)
00223 {
00224   if(list==NULL)        return(NULL);
00225 
00226   list=TMM_SeekSegListHead(list);
00227 
00228   while(list->next!=NULL)
00229   {
00230     /* bubble-sort */
00231     if(TMM_CompSegList(list,list->next)>0)
00232     {
00233       /* Easier to swap data than move nodes */
00234       ToySegment seg=list->next->seg;
00235       list->next->seg=list->seg;
00236       list->seg=seg;
00237       if(list->prev!=NULL)      list=list->prev;
00238       continue;
00239     }
00240 
00241     list=list->next;
00242   }
00243 
00244   list=TMM_SeekSegListHead(list);
00245   return(list);
00246 }
00247 
00248 SegList *TMM_RemoveAreaFromSegList(SegList *list, int pos, int len)
00249 {
00250 /*  ToySegment seg={pos,len}; */
00251   ToySegment seg;
00252   SegList *tail=TMM_SeekSegListEnd(list);
00253   list=TMM_SeekSegListHead(list);
00254 
00255   seg.pos=pos;
00256   seg.len=len;
00257 
00258   while(list!=NULL)
00259   {
00260     int v;
00261 
00262     ToySegment segs[2];
00263 
00264     v=TMM_SubtractSegs(&(list->seg),&seg,segs);
00265 
00266     switch(v)
00267     {
00268     case -1:    /*Nothing*/
00269       break;
00270 
00271     case 0:
00272     {
00273       /*Remove seg from list*/
00274       SegList *tmp=list->next;
00275 
00276       if((list->prev==NULL)&&(list->next==NULL))
00277 
00278 
00279       {
00280         free(list);
00281         return(NULL);
00282       }
00283 
00284       if(list->prev!=NULL)
00285       {
00286         list->prev->next = list->next;
00287       }
00288       if(list->next!=NULL)
00289       {
00290         list->next->prev=list->prev;
00291       }
00292 
00293 
00294       free(list);
00295       list=tmp;
00296       continue;
00297     }
00298 
00299     case 1:
00300       list->seg.len=segs[0].len;
00301       list->seg.pos=segs[0].pos;
00302       /*Modify seg*/
00303       break;
00304 
00305     case 2:
00306     {
00307       SegList *nseg=TMM_CreateSegList(segs[1].pos,segs[1].len,NULL,NULL);
00308 
00309       list->seg.len=segs[0].len;
00310       list->seg.pos=segs[0].pos;
00311 
00312       TMM_AppendSegList(tail,nseg);
00313       TMM_SeekSegListEnd(tail);
00314       break;
00315     }
00316     }
00317 
00318 
00319     list=list->next;
00320   }
00321 
00322   list=TMM_SeekSegListHead(tail);
00323   list=TMM_SortSegList(list);
00324 
00325   return(list);
00326 
00327 }
00328 
00329 void TMM_PrintSegList(SegList *list)
00330 {
00331   int n=0;
00332   list=TMM_SeekSegListHead(list);
00333   printf("Seg   Pos     Length\n");
00334   printf("----------------------\n");
00335   while(list!=NULL)
00336   {
00337     printf("%03d        %03d    %03d\n",n,list->seg.pos,list->seg.len);
00338     list=list->next;
00339     n++;
00340   }
00341 }
00342 
00343 
00344 SegList *TMM_AppendSegList(SegList *list,SegList *node)
00345 {
00346   list=TMM_SeekSegListEnd(list);
00347 
00348   if(node==NULL)        return(list);
00349   if(list==NULL)
00350   {
00351     node->prev=NULL;
00352     return node;
00353   }
00354   else
00355   {
00356     node->prev=list;
00357     list->next=node;
00358     return(TMM_SeekSegListHead(list));
00359   }
00360 }
00361 
00362 SegList *TMM_CreateSegList(int pos, int len, SegList *prev, SegList *next)
00363 {
00364   SegList *list=(SegList *)malloc(sizeof(SegList));
00365 
00366   if(list==NULL)
00367   {
00368     /* Out of memory */
00369     return(NULL);
00370   }
00371   else
00372   {
00373     list->next=next;
00374     list->prev=prev;
00375     list->seg.len=len;
00376     list->seg.pos=pos;
00377     return(list);
00378   }
00379 }
00380 
00381 SegList *TMM_SeekSegListHead(SegList *list)
00382 {
00383   SegList *l=list;
00384 
00385   if(l==NULL)   return NULL;
00386 
00387   while(l->prev!=NULL)  l=l->prev;
00388   return(l);
00389 }
00390 
00391 
00392 SegList *TMM_SeekSegListEnd(SegList *list)
00393 {
00394   SegList *l=list;
00395 
00396   if(l==NULL)   return NULL;
00397 
00398   while(l->next!=NULL)  l=l->next;
00399   return(l);
00400 }
00401 
00402 
00403 int TMM_FreeSegList(SegList *list)
00404 {
00405   SegList *l;
00406   if(list==NULL)        return(-1);
00407 
00408   l=TMM_SeekSegListHead(list);
00409 
00410   while(l->next!=NULL)
00411   {
00412     SegList *temp=l->next;
00413     free(l);
00414     l=temp;
00415   }
00416   free(l);
00417   return(0);
00418 }
00419 
00420 int TMM_AreaIntersectsSeg(ToySegment *seg1, ToySegment *seg2)
00421 {
00422   int dp=seg2->pos-seg1->pos;
00423 
00424   if(dp>0)
00425   {
00426     if(dp>=seg1->len)   return(0);  /*  No intersect  */
00427     else                return(1);  /*  Overlap       */
00428   }
00429   else
00430   {
00431     dp=-dp;
00432     if(seg2->len<=dp) return(0);    /*  no overlap  */
00433     else              return(1);    /*  Overlap     */
00434   }
00435 }
00436 
00437 
00438 int TMM_SubtractSegs(ToySegment *seg1, ToySegment *seg2, ToySegment segOut[2])
00439 {
00440   int dp=seg2->pos-seg1->pos;
00441 
00442   if(!TMM_AreaIntersectsSeg(seg1,seg2)) return(-1);
00443 
00444   if(dp>0)
00445   {
00446     if(SegEnd(seg2) >= SegEnd(seg1))
00447     {/*clip off end*/
00448       int olSize=seg1->len-dp;
00449       segOut[0].pos=seg1->pos;
00450       segOut[0].len=seg1->len-olSize;
00451       return(1);
00452     }
00453     else
00454     {/*Remove chunk from middle*/
00455       segOut[0].pos=seg1->pos;
00456       segOut[0].len=dp;
00457       segOut[1].pos=SegEnd(seg2);
00458       segOut[1].len=seg1->len-(seg2->len+dp);
00459       return(2);
00460     }
00461   }
00462   else  /*dp<0*/
00463   {     /*Make dp non-negative for more intuitive calculations*/
00464     dp=-dp;
00465 
00466     if(SegEnd(seg2)>=SegEnd(seg1))      return(0);      /*Totally remove*/
00467     else        /*Clip off front*/
00468     {
00469       int olSize=seg2->len-dp;
00470       segOut[0].pos=seg1->pos+olSize;
00471       segOut[0].len=seg1->len-olSize;
00472       return(1);
00473     }
00474   }
00475 }

Generated on Fri Apr 4 14:29:07 2003 for ToyMem by doxygen1.3-rc3