Home | History | Annotate | Line # | Download | only in nurbtess
      1 /*
      2 ** License Applicability. Except to the extent portions of this file are
      3 ** made subject to an alternative license as permitted in the SGI Free
      4 ** Software License B, Version 1.1 (the "License"), the contents of this
      5 ** file are subject only to the provisions of the License. You may not use
      6 ** this file except in compliance with the License. You may obtain a copy
      7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
      8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
      9 **
     10 ** http://oss.sgi.com/projects/FreeB
     11 **
     12 ** Note that, as provided in the License, the Software is distributed on an
     13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
     14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
     15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
     16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
     17 **
     18 ** Original Code. The Original Code is: OpenGL Sample Implementation,
     19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
     20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
     21 ** Copyright in any portions created by third parties is as indicated
     22 ** elsewhere herein. All Rights Reserved.
     23 **
     24 ** Additional Notice Provisions: The application programming interfaces
     25 ** established by SGI in conjunction with the Original Code are The
     26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
     27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
     28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
     29 ** Window System(R) (Version 1.3), released October 19, 1998. This software
     30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
     31 ** published by SGI, but has not been independently verified as being
     32 ** compliant with the OpenGL(R) version 1.2.1 Specification.
     33 **
     34 */
     35 /*
     36 */
     37 
     38 #include <stdlib.h>
     39 #include <stdio.h>
     40 #include <math.h>
     41 #include "glimports.h"
     42 #include "zlassert.h"
     43 
     44 #include "quicksort.h"
     45 #include "directedLine.h"
     46 #include "polyDBG.h"
     47 
     48 #ifdef __WATCOMC__
     49 #pragma warning 726 10
     50 #endif
     51 
     52 //we must return the newLine
     53 directedLine* directedLine::deleteChain(directedLine* begin, directedLine* end)
     54 {
     55   if(begin->head()[0] ==  end->tail()[0] &&
     56      begin->head()[1] ==  end->tail()[1]
     57      )
     58     {
     59       directedLine *ret = begin->prev;
     60       begin->prev->next = end->next;
     61       end->next->prev = begin->prev;
     62       delete begin->sline;
     63       delete end->sline;
     64       delete begin;
     65       delete end;
     66 
     67       return ret;
     68     }
     69 
     70   directedLine* newLine;
     71   sampledLine* sline = new sampledLine(begin->head(), end->tail());
     72   newLine =  new directedLine(INCREASING, sline);
     73   directedLine *p = begin->prev;
     74   directedLine *n = end->next;
     75   p->next = newLine;
     76   n->prev = newLine;
     77   newLine->prev = p;
     78   newLine->next = n;
     79 
     80   delete begin->sline;
     81   delete end->sline;
     82   delete begin;
     83   delete end;
     84   return newLine;
     85 }
     86 
     87 
     88 void directedLine::deleteSingleLine(directedLine* dline)
     89 {
     90   //make sure that dline->prev->tail is the same as
     91   //dline->next->head. This is for numerical erros.
     92   //for example, if we delete a line which is almost degeneate
     93   //within (epsilon), then we want to make that the polygon after deletion
     94   //is still a valid polygon
     95 
     96   dline->next->head()[0] =  dline->prev->tail()[0];
     97   dline->next->head()[1] =  dline->prev->tail()[1];
     98 
     99   dline->prev->next = dline->next;
    100   dline->next->prev = dline->prev;
    101 
    102   delete dline;
    103 
    104 }
    105 
    106 static Int myequal(Real a[2], Real b[2])
    107 {
    108   /*
    109   if(a[0]==b[0] && a[1] == b[1])
    110     return 1;
    111   else
    112     return 0;
    113     */
    114 
    115 
    116   if(fabs(a[0]-b[0]) < 0.00001 &&
    117      fabs(a[1]-b[1]) < 0.00001)
    118     return 1;
    119   else
    120     return 0;
    121 
    122 }
    123 
    124 directedLine* directedLine::deleteDegenerateLines()
    125 {
    126   //if there is only one edge or two edges, don't do anything
    127   if(this->next == this)
    128     return this;
    129   if(this->next == this->prev)
    130     return this;
    131 
    132   //find a nondegenerate line
    133   directedLine* temp;
    134   directedLine* first = NULL;
    135   if(! myequal(head(), tail()))
    136     /*
    137   if(head()[0] != tail()[0] ||
    138   head()[1] != tail()[1])
    139   */
    140     first = this;
    141   else
    142     {
    143       for(temp = this->next; temp != this; temp = temp->next)
    144 	{
    145 	  /*
    146 	  if(temp->head()[0] != temp->tail()[0] ||
    147 	     temp->head()[1] != temp->tail()[1])
    148 	     */
    149 	  if(! myequal(temp->head(), temp->tail()))
    150 	    {
    151 	      first = temp;
    152 	      break;
    153 	    }
    154 
    155 	}
    156     }
    157 
    158   //if there are no non-degenerate lines, then we simply return NULL.
    159   if(first == NULL)
    160     {
    161       deleteSinglePolygonWithSline();
    162       return NULL;
    163     }
    164 
    165   directedLine* tempNext = NULL;
    166   for(temp =first->next; temp != first; temp = tempNext)
    167     {
    168       tempNext = temp->getNext();
    169 /*
    170       if(temp->head()[0] == temp->tail()[0] &&
    171 	 temp->head()[1] == temp->tail()[1])
    172 */
    173 
    174       if(myequal(temp->head(), temp->tail()))
    175 	deleteSingleLine(temp);
    176     }
    177   return first;
    178 }
    179 
    180 directedLine* directedLine::deleteDegenerateLinesAllPolygons()
    181 {
    182   directedLine* temp;
    183   directedLine *tempNext = NULL;
    184   directedLine* ret= NULL;
    185   directedLine* retEnd = NULL;
    186   for(temp=this; temp != NULL; temp = tempNext)
    187     {
    188       tempNext = temp->nextPolygon;
    189       temp->nextPolygon = NULL;
    190       if(ret == NULL)
    191 	{
    192 	  ret = retEnd = temp->deleteDegenerateLines();
    193 
    194 	}
    195       else
    196 	{
    197 	  directedLine *newPolygon = temp->deleteDegenerateLines();
    198 	  if(newPolygon != NULL)
    199 	    {
    200 	  retEnd->nextPolygon = temp->deleteDegenerateLines();
    201 	  retEnd = retEnd->nextPolygon;
    202 	}
    203     }
    204     }
    205   return ret;
    206 }
    207 
    208 directedLine* directedLine::cutIntersectionAllPoly(int &cutOccur)
    209 {
    210   directedLine* temp;
    211   directedLine *tempNext = NULL;
    212   directedLine* ret= NULL;
    213   directedLine* retEnd = NULL;
    214   cutOccur = 0;
    215   for(temp=this; temp != NULL; temp = tempNext)
    216     {
    217       int eachCutOccur=0;
    218       tempNext = temp->nextPolygon;
    219       temp->nextPolygon = NULL;
    220       if(ret == NULL)
    221 	{
    222 
    223 	  ret = retEnd = DBG_cutIntersectionPoly(temp, eachCutOccur);
    224 	  if(eachCutOccur)
    225 	    cutOccur = 1;
    226 	}
    227       else
    228 	{
    229 
    230 	  retEnd->nextPolygon = DBG_cutIntersectionPoly(temp, eachCutOccur);
    231 	  retEnd = retEnd->nextPolygon;
    232 	  if(eachCutOccur)
    233 	    cutOccur = 1;
    234 	}
    235     }
    236   return ret;
    237 }
    238 
    239 
    240 void directedLine::deleteSinglePolygonWithSline()
    241 {
    242   directedLine *temp, *tempNext;
    243   prev->next = NULL;
    244   for(temp=this; temp != NULL; temp = tempNext)
    245     {
    246       tempNext = temp->next;
    247       delete temp->sline;
    248       delete temp;
    249     }
    250 }
    251 
    252 void directedLine::deletePolygonListWithSline()
    253 {
    254   directedLine *temp, *tempNext;
    255   for(temp=this; temp != NULL; temp=tempNext)
    256     {
    257       tempNext = temp->nextPolygon;
    258       temp->deleteSinglePolygonWithSline();
    259     }
    260 }
    261 
    262 void directedLine::deleteSinglePolygon()
    263 {
    264   directedLine *temp, *tempNext;
    265   prev->next = NULL;
    266   for(temp=this; temp != NULL; temp = tempNext)
    267     {
    268       tempNext = temp->next;
    269       delete temp;
    270     }
    271 }
    272 
    273 void directedLine::deletePolygonList()
    274 {
    275   directedLine *temp, *tempNext;
    276   for(temp=this; temp != NULL; temp=tempNext)
    277     {
    278       tempNext = temp->nextPolygon;
    279       temp->deleteSinglePolygon();
    280     }
    281 }
    282 
    283 
    284 /*a loop by itself*/
    285 directedLine::directedLine(short dir, sampledLine* sl)
    286 {
    287   direction = dir;
    288   sline = sl;
    289   next = this;
    290   prev = this;
    291   nextPolygon = NULL;
    292 //  prevPolygon = NULL;
    293   rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
    294 
    295   rootLink = NULL;
    296 
    297 }
    298 
    299 void directedLine::init(short dir, sampledLine* sl)
    300 {
    301   direction = dir;
    302   sline = sl;
    303 }
    304 
    305 directedLine::directedLine()
    306 {
    307   next = this;
    308   prev = this;
    309   nextPolygon = NULL;
    310   rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
    311   rootLink = NULL;
    312   direction = INCREASING;
    313   sline = NULL;
    314 }
    315 
    316 directedLine::~directedLine()
    317 {
    318 }
    319 
    320 Real* directedLine::head()
    321 {
    322 
    323   return (direction==INCREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
    324 }
    325 
    326 /*inline*/ Real* directedLine::getVertex(Int i)
    327 {
    328   return (direction==INCREASING)? (sline->get_points())[i] : (sline->get_points())[sline->get_npoints() - 1 -i];
    329 }
    330 
    331 Real* directedLine::tail()
    332 {
    333   return (direction==DECREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
    334 }
    335 
    336  /*insert a new line between prev and this*/
    337 void directedLine::insert(directedLine* nl)
    338 {
    339   nl->next = this;
    340   nl->prev = prev;
    341   prev->next = nl;
    342   prev = nl;
    343   nl->rootLink = this; /*assuming that 'this' is the root!!!*/
    344 }
    345 
    346 Int directedLine::numEdges()
    347 {
    348   Int ret=0;
    349   directedLine* temp;
    350   if(next == this) return 1;
    351 
    352   ret = 1;
    353   for(temp = next; temp != this; temp = temp->next)
    354     ret++;
    355   return ret;
    356 }
    357 
    358 Int directedLine::numEdgesAllPolygons()
    359 {
    360   Int ret=0;
    361   directedLine* temp;
    362   for(temp=this; temp!= NULL; temp=temp->nextPolygon)
    363     {
    364       ret += temp->numEdges();
    365     }
    366   return ret;
    367 }
    368 
    369 /*return 1 if the double linked list forms a polygon.
    370  */
    371 short directedLine::isPolygon()
    372 {
    373   directedLine* temp;
    374 
    375   /*a polygon contains at least 3 edges*/
    376   if(numEdges() <=2) return 0;
    377 
    378   /*check this edge*/
    379   if(! isConnected()) return 0;
    380 
    381   /*check all other edges*/
    382   for(temp=next; temp != this; temp = temp->next){
    383     if(!isConnected()) return 0;
    384   }
    385   return 1;
    386 }
    387 
    388 /*check if the head of this edge is connected to
    389  *the tail of the prev
    390  */
    391 short directedLine::isConnected()
    392 {
    393   if( (head()[0] == prev->tail()[0]) && (head()[1] == prev->tail()[1]))
    394     return 1;
    395   else
    396     return 0;
    397 }
    398 
    399 Int compV2InY(Real A[2], Real B[2])
    400 {
    401   if(A[1] < B[1]) return -1;
    402   if(A[1] == B[1] && A[0] < B[0]) return -1;
    403   if(A[1] == B[1] && A[0] == B[0]) return 0;
    404   return 1;
    405 }
    406 
    407 Int compV2InX(Real A[2], Real B[2])
    408 {
    409   if(A[0] < B[0]) return -1;
    410   if(A[0] == B[0] && A[1] < B[1]) return -1;
    411   if(A[0] == B[0] && A[1] == B[1]) return 0;
    412   return 1;
    413 }
    414 
    415 /*compare two vertices NOT lines!
    416  *A vertex is the head of a directed line.
    417  *(x_1, y_1) <= (x_2, y_2) if
    418  *either y_1 < y_2
    419  *or	 y_1 == y_2 && x_1 < x_2.
    420  *return -1 if this->head() <= nl->head(),
    421  *return  1 otherwise
    422  */
    423 Int directedLine::compInY(directedLine* nl)
    424 {
    425   if(head()[1] < nl->head()[1]) return -1;
    426   if(head()[1] == nl->head()[1] && head()[0] < nl->head()[0]) return -1;
    427   return 1;
    428 }
    429 
    430 /*compare two vertices NOT lines!
    431  *A vertex is the head of a directed line.
    432  *(x_1, y_1) <= (x_2, y_2) if
    433  *either x_1 < x_2
    434  *or	 x_1 == x_2 && y_1 < y_2.
    435  *return -1 if this->head() <= nl->head(),
    436  *return  1 otherwise
    437  */
    438 Int directedLine::compInX(directedLine* nl)
    439 {
    440   if(head()[0] < nl->head()[0]) return -1;
    441   if(head()[0] == nl->head()[0] && head()[1] < nl->head()[1]) return -1;
    442   return 1;
    443 }
    444 
    445 /*used by sort precedures
    446  */
    447 static Int compInY2(directedLine* v1, directedLine* v2)
    448 {
    449   return v1->compInY(v2);
    450 }
    451 #ifdef NOT_USED
    452 static Int compInX(directedLine* v1, directedLine* v2)
    453 {
    454   return v1->compInX(v2);
    455 }
    456 #endif
    457 
    458 /*sort all the vertices NOT the lines!
    459  *a vertex is the head of a directed line
    460  */
    461 directedLine** directedLine::sortAllPolygons()
    462 {
    463   Int total_num_edges = 0;
    464   directedLine** array = toArrayAllPolygons(total_num_edges);
    465   quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void *, void *)) compInY2);
    466 
    467   return array;
    468 }
    469 
    470 void directedLine::printSingle()
    471 {
    472   if(direction == INCREASING)
    473     printf("direction is INCREASING\n");
    474   else
    475     printf("direction is DECREASING\n");
    476   printf("head=%f,%f)\n", head()[0], head()[1]);
    477   sline->print();
    478 }
    479 
    480 /*print one polygon*/
    481 void directedLine::printList()
    482 {
    483   directedLine* temp;
    484   printSingle();
    485   for(temp = next; temp!=this; temp=temp->next)
    486     temp->printSingle();
    487 }
    488 
    489 /*print all the polygons*/
    490 void directedLine::printAllPolygons()
    491 {
    492   directedLine *temp;
    493   for(temp = this; temp!=NULL; temp = temp->nextPolygon)
    494     {
    495       printf("polygon:\n");
    496       temp->printList();
    497     }
    498 }
    499 
    500 /*insert this polygon into the head of the old polygon List*/
    501 directedLine* directedLine::insertPolygon(directedLine* oldList)
    502 {
    503   /*this polygon is a root*/
    504   setRootBit();
    505   if(oldList == NULL) return this;
    506   nextPolygon = oldList;
    507 /*  oldList->prevPolygon = this;*/
    508   return this;
    509 }
    510 
    511 /*cutoff means delete. but we don't deallocate any space,
    512  *so we use cutoff instead of delete
    513  */
    514 directedLine* directedLine::cutoffPolygon(directedLine *p)
    515 {
    516   directedLine* temp;
    517   directedLine* prev_polygon  = NULL;
    518   if(p == NULL) return this;
    519 
    520   for(temp=this; temp != p; temp = temp->nextPolygon)
    521     {
    522       if(temp == NULL)
    523 	{
    524 	  fprintf(stderr, "in cutoffPolygon, not found\n");
    525 	  exit(1);
    526 	}
    527       prev_polygon = temp;
    528     }
    529 
    530 /*  prev_polygon = p->prevPolygon;*/
    531 
    532   p->resetRootBit();
    533   if(prev_polygon == NULL) /*this is the one to cutoff*/
    534     return nextPolygon;
    535   else {
    536     prev_polygon->nextPolygon = p->nextPolygon;
    537     return this;
    538   }
    539 }
    540 
    541 Int directedLine::numPolygons()
    542 {
    543   if(nextPolygon == NULL) return 1;
    544   else return 1+nextPolygon->numPolygons();
    545 }
    546 
    547 
    548 /*let  array[index ...] denote
    549  *all the edges in this polygon
    550  *return the next available index of array.
    551  */
    552 Int directedLine::toArraySinglePolygon(directedLine** array, Int index)
    553 {
    554   directedLine *temp;
    555   array[index++] = this;
    556   for(temp = next; temp != this; temp = temp->next)
    557     {
    558       array[index++] = temp;
    559     }
    560   return index;
    561 }
    562 
    563 /*the space is allocated. The caller is responsible for
    564  *deallocate the space.
    565  *total_num_edges is set to be the total number of edges of all polygons
    566  */
    567 directedLine** directedLine::toArrayAllPolygons(Int& total_num_edges)
    568 {
    569   total_num_edges=numEdgesAllPolygons();
    570   directedLine** ret = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges);
    571   assert(ret);
    572 
    573   directedLine *temp;
    574   Int index = 0;
    575   for(temp=this; temp != NULL; temp=temp->nextPolygon) {
    576     index = temp->toArraySinglePolygon(ret, index);
    577   }
    578   return ret;
    579 }
    580 
    581 /*assume the polygon is a simple polygon, return
    582  *the area enclosed by it.
    583  *if thee order is counterclock wise, the area is positive.
    584  */
    585 Real directedLine::polyArea()
    586 {
    587   directedLine* temp;
    588   Real ret=0.0;
    589   Real x1,y1,x2,y2;
    590   x1 = this->head()[0];
    591   y1 = this->head()[1];
    592   x2 = this->next->head()[0];
    593   y2 = this->next->head()[1];
    594   ret = -(x2*y1-x1*y2);
    595   for(temp=this->next; temp!=this; temp = temp->next)
    596     {
    597       x1 = temp->head()[0];
    598       y1 = temp->head()[1];
    599       x2 = temp->next->head()[0];
    600       y2 = temp->next->head()[1];
    601       ret += -( x2*y1-x1*y2);
    602     }
    603   return Real(0.5)*ret;
    604 }
    605 
    606 /*******************split or combine polygons begin********************/
    607 /*conect a diagonal of a single simple polygon or  two simple polygons.
    608  *If the two vertices v1 (head) and v2 (head) are in the same simple polygon,
    609  *then we actually split the simple polygon into two polygons.
    610  *If instead two vertices velong to two difference polygons,
    611  *then we combine the  two polygons into one polygon.
    612  *It is upto the caller to decide whether this is a split or a
    613  *combination.
    614  *
    615  *Case Split:
    616  *split a single simple polygon into two simple polygons by
    617  *connecting a diagonal (two vertices).
    618  *v1, v2: the two vertices are the head() of the two directedLines.
    619  *  this routine generates one new sampledLine which is returned in
    620  *generatedLine,
    621  *and it generates two directedLines returned in ret_p1 and ret_p2.
    622  *ret_p1 and ret_p2 are used as the entry to the two new polygons.
    623  *Notice the caller should not deallocate the space of v2 and v2 after
    624  *calling this function, since all of the edges are connected to
    625  *ret_p1 or ret_p2.
    626  *
    627  *combine:
    628  *combine two simpolygons into one by connecting one diagonal.
    629  *the returned polygon is returned in ret_p1.
    630  */
    631 /*ARGSUSED*/
    632 void directedLine::connectDiagonal(directedLine* v1, directedLine* v2,
    633 			   directedLine** ret_p1,
    634 			   directedLine** ret_p2,
    635 			   sampledLine** generatedLine,
    636 			   directedLine* polygonList								   )
    637 {
    638   sampledLine *nsline  = new sampledLine(2);
    639 
    640 
    641 
    642   nsline->setPoint(0, v1->head());
    643   nsline->setPoint(1, v2->head());
    644 
    645 
    646 
    647   /*the increasing line is from v1 head to v2 head*/
    648   directedLine* newLineInc = new directedLine(INCREASING, nsline);
    649 
    650 
    651 
    652   directedLine* newLineDec = new directedLine(DECREASING, nsline);
    653 
    654 
    655   directedLine* v1Prev = v1->prev;
    656   directedLine* v2Prev = v2->prev;
    657 
    658   v1	    ->prev = newLineDec;
    659   v2Prev    ->next = newLineDec;
    660   newLineDec->next = v1;
    661   newLineDec->prev = v2Prev;
    662 
    663   v2	    ->prev = newLineInc;
    664   v1Prev    ->next = newLineInc;
    665   newLineInc->next = v2;
    666   newLineInc->prev = v1Prev;
    667 
    668   *ret_p1 = newLineDec;
    669   *ret_p2 = newLineInc;
    670   *generatedLine = nsline;
    671 }
    672 
    673 //see the function connectDiangle
    674 /*ARGSUSED*/
    675 void directedLine::connectDiagonal_2slines(directedLine* v1, directedLine* v2,
    676 			   directedLine** ret_p1,
    677 			   directedLine** ret_p2,
    678 			   directedLine* polygonList								   )
    679 {
    680   sampledLine *nsline  = new sampledLine(2);
    681   sampledLine *nsline2	= new sampledLine(2);
    682 
    683   nsline->setPoint(0, v1->head());
    684   nsline->setPoint(1, v2->head());
    685   nsline2->setPoint(0, v1->head());
    686   nsline2->setPoint(1, v2->head());
    687 
    688   /*the increasing line is from v1 head to v2 head*/
    689   directedLine* newLineInc = new directedLine(INCREASING, nsline);
    690 
    691   directedLine* newLineDec = new directedLine(DECREASING, nsline2);
    692 
    693   directedLine* v1Prev = v1->prev;
    694   directedLine* v2Prev = v2->prev;
    695 
    696   v1	    ->prev = newLineDec;
    697   v2Prev    ->next = newLineDec;
    698   newLineDec->next = v1;
    699   newLineDec->prev = v2Prev;
    700 
    701   v2	    ->prev = newLineInc;
    702   v1Prev    ->next = newLineInc;
    703   newLineInc->next = v2;
    704   newLineInc->prev = v1Prev;
    705 
    706   *ret_p1 = newLineDec;
    707   *ret_p2 = newLineInc;
    708 
    709 }
    710 
    711 Int directedLine::samePolygon(directedLine* v1, directedLine* v2)
    712 {
    713   if(v1 == v2) return 1;
    714   directedLine *temp;
    715   for(temp = v1->next; temp != v1; temp = temp->next)
    716     {
    717       if(temp == v2) return 1;
    718     }
    719   return 0;
    720 }
    721 
    722 directedLine* directedLine::findRoot()
    723 {
    724   if(rootBit) return this;
    725   directedLine* temp;
    726   for(temp = next; temp != this; temp = temp->next)
    727     if(temp -> rootBit ) return temp;
    728   return NULL; /*should not happen*/
    729 }
    730 
    731 directedLine* directedLine::rootLinkFindRoot()
    732 {
    733   directedLine* tempRoot;
    734   directedLine* tempLink;
    735   tempRoot = this;
    736   tempLink = rootLink;
    737   while(tempLink != NULL){
    738     tempRoot = tempLink;
    739     tempLink = tempRoot->rootLink;
    740   }
    741   return tempRoot;
    742 }
    743 
    744 /*******************split or combine polygons end********************/
    745 
    746 /*****************IO stuff begin*******************/
    747 
    748 /*format:
    749  *#polygons
    750  * #vertices
    751  *  vertices
    752  * #vertices
    753  *  vertices
    754  *...
    755  */
    756 void directedLine::writeAllPolygons(char* filename)
    757 {
    758   FILE* fp = fopen(filename, "w");
    759   assert(fp);
    760   Int nPolygons = numPolygons();
    761   directedLine *root;
    762   fprintf(fp, "%i\n", nPolygons);
    763   for(root = this; root != NULL; root = root->nextPolygon)
    764     {
    765       directedLine *temp;
    766       Int npoints=0;
    767       npoints = root->get_npoints()-1;
    768       for(temp = root->next; temp != root; temp=temp->next)
    769 	npoints += temp->get_npoints()-1;
    770       fprintf(fp, "%i\n", npoints/*root->numEdges()*/);
    771 
    772 
    773       for(Int i=0; i<root->get_npoints()-1; i++){
    774 	fprintf(fp, "%f ", root->getVertex(i)[0]);
    775 	fprintf(fp, "%f ", root->getVertex(i)[1]);
    776       }
    777 
    778       for(temp=root->next; temp != root; temp = temp->next)
    779 	{
    780 	  for(Int i=0; i<temp->get_npoints()-1; i++){
    781 
    782 	    fprintf(fp, "%f ", temp->getVertex(i)[0]);
    783 	    fprintf(fp, "%f ", temp->getVertex(i)[1]);
    784 	  }
    785 	  fprintf(fp,"\n");
    786 	}
    787       fprintf(fp, "\n");
    788     }
    789   fclose(fp);
    790 }
    791 
    792 directedLine* readAllPolygons(char* filename)
    793 {
    794   Int i,j;
    795   FILE* fp = fopen(filename, "r");
    796   Int nPolygons;
    797   int result;
    798 
    799   assert(fp);
    800   result = fscanf(fp, "%i", &nPolygons);
    801   assert(result != EOF);
    802   directedLine *ret = NULL;
    803 
    804   for(i=0; i<nPolygons; i++)
    805     {
    806       Int nEdges;
    807       result = fscanf(fp, "%i", &nEdges);
    808       assert(result != EOF);
    809       Real vert[2][2] = { { 0 } };
    810       Real VV[2][2];
    811       /*the first two vertices*/
    812       result = fscanf(fp, "%f", &(vert[0][0]));
    813       assert(result != EOF);
    814       result = fscanf(fp, "%f", &(vert[0][1]));
    815       assert(result != EOF);
    816       result = fscanf(fp, "%f", &(vert[1][0]));
    817       assert(result != EOF);
    818       result = fscanf(fp, "%f", &(vert[1][1]));
    819       assert(result != EOF);
    820       VV[1][0] = vert[0][0];
    821       VV[1][1] = vert[0][1];
    822       sampledLine *sLine = new sampledLine(2, vert);
    823       directedLine *thisPoly = new directedLine(INCREASING, sLine);
    824 thisPoly->rootLinkSet(NULL);
    825 
    826       directedLine *dLine;
    827       for(j=2; j<nEdges; j++)
    828 	{
    829 	  vert[0][0]=vert[1][0];
    830 	  vert[0][1]=vert[1][1];
    831 	  result = fscanf(fp, "%f", &(vert[1][0]));
    832 	  assert(result != EOF);
    833 	  result = fscanf(fp, "%f", &(vert[1][1]));
    834 	  assert(result != EOF);
    835 	  sLine = new sampledLine(2,vert);
    836 	  dLine = new directedLine(INCREASING, sLine);
    837 dLine->rootLinkSet(thisPoly);
    838 	  thisPoly->insert(dLine);
    839 	}
    840 
    841       VV[0][0]=vert[1][0];
    842       VV[0][1]=vert[1][1];
    843       sLine = new sampledLine(2,VV);
    844       dLine = new directedLine(INCREASING, sLine);
    845 dLine->rootLinkSet(thisPoly);
    846       thisPoly->insert(dLine);
    847 
    848       ret = thisPoly->insertPolygon(ret);
    849     }
    850   fclose(fp);
    851   return ret;
    852 }
    853 
    854 
    855 
    856 
    857 
    858 
    859 
    860 
    861