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
deleteChain(directedLine * begin,directedLine * end)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 
deleteSingleLine(directedLine * dline)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 
myequal(Real a[2],Real b[2])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 
deleteDegenerateLines()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 
deleteDegenerateLinesAllPolygons()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 
cutIntersectionAllPoly(int & cutOccur)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 
deleteSinglePolygonWithSline()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 
deletePolygonListWithSline()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 
deleteSinglePolygon()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 
deletePolygonList()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*/
directedLine(short dir,sampledLine * sl)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 
init(short dir,sampledLine * sl)299 void directedLine::init(short dir, sampledLine* sl)
300 {
301   direction = dir;
302   sline = sl;
303 }
304 
directedLine()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 
~directedLine()316 directedLine::~directedLine()
317 {
318 }
319 
head()320 Real* directedLine::head()
321 {
322 
323   return (direction==INCREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
324 }
325 
getVertex(Int i)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 
tail()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*/
insert(directedLine * nl)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 
numEdges()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 
numEdgesAllPolygons()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  */
isPolygon()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  */
isConnected()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 
compV2InY(Real A[2],Real B[2])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 
compV2InX(Real A[2],Real B[2])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  */
compInY(directedLine * nl)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  */
compInX(directedLine * nl)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  */
compInY2(directedLine * v1,directedLine * v2)447 static Int compInY2(directedLine* v1, directedLine* v2)
448 {
449   return v1->compInY(v2);
450 }
451 #ifdef NOT_USED
compInX(directedLine * v1,directedLine * v2)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  */
sortAllPolygons()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 
printSingle()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*/
printList()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*/
printAllPolygons()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*/
insertPolygon(directedLine * oldList)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  */
cutoffPolygon(directedLine * p)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 
numPolygons()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  */
toArraySinglePolygon(directedLine ** array,Int index)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  */
toArrayAllPolygons(Int & total_num_edges)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  */
polyArea()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*/
connectDiagonal(directedLine * v1,directedLine * v2,directedLine ** ret_p1,directedLine ** ret_p2,sampledLine ** generatedLine,directedLine * polygonList)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*/
connectDiagonal_2slines(directedLine * v1,directedLine * v2,directedLine ** ret_p1,directedLine ** ret_p2,directedLine * polygonList)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 
samePolygon(directedLine * v1,directedLine * v2)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 
findRoot()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 
rootLinkFindRoot()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  */
writeAllPolygons(char * filename)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 
readAllPolygons(char * filename)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