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:
10 ** http://oss.sgi.com/projects/FreeB
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.
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.
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.
41 #include "glimports.h"
44 #include "monoTriangulation.h"
45 #include "polyUtil.h" /*for area*/
46 #include "partitionX.h"
47 #include "monoPolyPart.h"
51 extern directedLine
* polygonConvert(directedLine
* polygon
);
55 void monoTriangulationOpt(directedLine
* poly
, primStream
* pStream
)
58 Int n_edges
= poly
->numEdges();
59 directedLine
** cusps
= (directedLine
**) malloc(sizeof(directedLine
*)*n_edges
);
61 findInteriorCuspsX(poly
, n_cusps
, cusps
);
62 if(n_cusps
==0) //u monotine
64 monoTriangulationFun(poly
, compV2InX
, pStream
);
66 else if(n_cusps
== 1) // one interior cusp
68 directedLine
* new_polygon
= polygonConvert(cusps
[0]);
69 directedLine
* other
= findDiagonal_singleCuspX(new_polygon
);
70 //<other> should NOT be null unless there are self-intersecting
71 //trim curves. In that case, we don't want to core dump, instead,
72 //we triangulate anyway, and print out error message.
75 monoTriangulationFun(poly
, compV2InX
, pStream
);
82 new_polygon
->connectDiagonal_2slines(new_polygon
, other
,
87 monoTriangulationFun(ret_p1
, compV2InX
, pStream
);
88 monoTriangulationFun(ret_p2
, compV2InX
, pStream
);
90 ret_p1
->deleteSinglePolygonWithSline();
91 ret_p2
->deleteSinglePolygonWithSline();
96 //we need a general partitionX funtion (supposed to be in partitionX.C,
97 //not implemented yet. XXX
98 monoTriangulationFun(poly
, compV2InY
, pStream
);
104 void monoTriangulationRecOpt(Real
* topVertex
, Real
* botVertex
,
105 vertexArray
* left_chain
, Int left_current
,
106 vertexArray
* right_chain
, Int right_current
,
110 Int n_left
= left_chain
->getNumElements();
111 Int n_right
= right_chain
->getNumElements();
112 if(left_current
>= n_left
-1 ||
113 right_current
>= n_right
-1)
115 monoTriangulationRec(topVertex
, botVertex
, left_chain
, left_current
,
116 right_chain
, right_current
, pStream
);
119 //now both left and right have at least two vertices each.
120 Real left_v
= left_chain
->getVertex(left_current
)[1];
121 Real right_v
= right_chain
->getVertex(right_current
)[1];
123 if(left_v
<= right_v
) //first left vertex is below right
125 //find the last vertex of right which is above or equal to left
126 for(j
=right_current
; j
<=n_right
-1; j
++)
128 if(right_chain
->getVertex(j
)[1] < left_v
)
131 monoTriangulationRecGen(topVertex
, left_chain
->getVertex(left_current
),
132 left_chain
, left_current
, left_current
,
133 right_chain
, right_current
, j
-1,
135 monoTriangulationRecOpt(right_chain
->getVertex(j
-1),
137 left_chain
, left_current
,
141 else //first right vertex is strictly below left
143 //find the last vertex of left which is strictly above right
144 for(i
=left_current
; i
<=n_left
-1; i
++)
146 if(left_chain
->getVertex(i
)[1] <= right_v
)
149 monoTriangulationRecGen(topVertex
, right_chain
->getVertex(right_current
),
150 left_chain
, left_current
, i
-1,
151 right_chain
, right_current
, right_current
,
153 monoTriangulationRecOpt(left_chain
->getVertex(i
-1),
156 right_chain
, right_current
,
162 void monoTriangulationRecGenTBOpt(Real
* topVertex
, Real
* botVertex
,
163 vertexArray
* inc_chain
, Int inc_current
, Int inc_end
,
164 vertexArray
* dec_chain
, Int dec_current
, Int dec_end
,
167 pStream
->triangle(topVertex
, inc_chain
->getVertex(inc_current
), dec_chain
->getVertex(dec_current
));
169 /*printf("**(%f,%f)\n", inc_chain->getArray()[0][0],inc_chain->getArray()[0][1]);*/
170 triangulateXYMonoTB(inc_end
-inc_current
+1, inc_chain
->getArray()+inc_current
, dec_end
-dec_current
+1, dec_chain
->getArray()+dec_current
, pStream
);
172 pStream
->triangle(botVertex
, dec_chain
->getVertex(dec_end
), inc_chain
->getVertex(inc_end
));
178 *the strip is going top to bottom. compared to the funtion
179 * triangulateXYmono()
181 void triangulateXYMonoTB(Int n_left
, Real
** leftVerts
,
182 Int n_right
, Real
** rightVerts
,
190 assert(n_left
>=1 && n_right
>=1);
191 if(leftVerts
[0][1] >= rightVerts
[0][1])
195 topMostV
= leftVerts
[0];
201 topMostV
= rightVerts
[0];
206 if(i
>= n_left
) /*case1: no more in left*/
209 if(j
<n_right
-1) /*at least two vertices in right*/
212 pStream
->insert(topMostV
);
213 for(k
=n_right
-1; k
>=j
; k
--)
214 pStream
->insert(rightVerts
[j
]);
216 pStream
->end(PRIMITIVE_STREAM_FAN
);
222 else if(j
>= n_right
) /*case2: no more in right*/
225 if(i
<n_left
-1) /*at least two vertices in left*/
228 pStream
->insert(topMostV
);
230 for(k
=i
; k
<n_left
; k
++)
231 pStream
->insert(leftVerts
[k
]);
233 pStream
->end(PRIMITIVE_STREAM_FAN
);
238 else /* case3: neither is empty, plus the topMostV, there is at least one triangle to output*/
241 if(leftVerts
[i
][1] >= rightVerts
[j
][1])
244 pStream
->insert(rightVerts
[j
]); /*the origin of this fan*/
246 pStream
->insert(topMostV
);
248 /*find the last k>=i such that
249 *leftverts[k][1] >= rightverts[j][1]
254 if(leftVerts
[k
][1] < rightVerts
[j
][1])
261 pStream
->insert(leftVerts
[l
]);
264 pStream
->end(PRIMITIVE_STREAM_FAN
);
265 //update i for next loop
267 topMostV
= leftVerts
[k
];
270 else /*leftVerts[i][1] < rightVerts[j][1]*/
273 pStream
->insert(leftVerts
[i
]);/*the origion of this fan*/
275 /*find the last k>=j such that
276 *rightverts[k][1] > leftverts[i][1]*/
280 if(rightVerts
[k
][1] <= leftVerts
[i
][1])
287 pStream
->insert(rightVerts
[l
]);
289 pStream
->insert(topMostV
);
290 pStream
->end(PRIMITIVE_STREAM_FAN
);
292 topMostV
= rightVerts
[j
-1];
298 static int chainConvex(vertexArray
* inc_chain
, Int inc_current
, Int inc_end
)
301 //if there are no more than 2 vertices, return 1
302 if(inc_current
>= inc_end
-1) return 1;
303 for(i
=inc_current
; i
<= inc_end
-2; i
++)
305 if(area(inc_chain
->getVertex(i
), inc_chain
->getVertex(i
+1), inc_chain
->getVertex(i
+2)) <0)
311 static int chainConcave(vertexArray
* dec_chain
, Int dec_current
, Int dec_end
)
314 //if there are no more than 2 vertices, return 1
315 if(dec_current
>= dec_end
-1) return 1;
316 for(i
=dec_current
; i
<=dec_end
-2; i
++)
318 if(area(dec_chain
->getVertex(i
), dec_chain
->getVertex(i
+1), dec_chain
->getVertex(i
+2)) >0)
324 void monoTriangulationRecGenInU(Real
* topVertex
, Real
* botVertex
,
325 vertexArray
* inc_chain
, Int inc_current
, Int inc_end
,
326 vertexArray
* dec_chain
, Int dec_current
, Int dec_end
,
332 void monoTriangulationRecGenOpt(Real
* topVertex
, Real
* botVertex
,
333 vertexArray
* inc_chain
, Int inc_current
, Int inc_end
,
334 vertexArray
* dec_chain
, Int dec_current
, Int dec_end
,
338 //copy this to a polygon: directedLine Lioop
343 if(inc_current
<= inc_end
) //at least one vertex in inc_chain
345 sline
= new sampledLine(topVertex
, inc_chain
->getVertex(inc_current
));
346 poly
= new directedLine(INCREASING
, sline
);
347 for(i
=inc_current
; i
<=inc_end
-1; i
++)
349 sline
= new sampledLine(inc_chain
->getVertex(i
), inc_chain
->getVertex(i
+1));
350 dline
= new directedLine(INCREASING
, sline
);
353 sline
= new sampledLine(inc_chain
->getVertex(inc_end
), botVertex
);
354 dline
= new directedLine(INCREASING
, sline
);
357 else //inc_chian is empty
359 sline
= new sampledLine(topVertex
, botVertex
);
360 dline
= new directedLine(INCREASING
, sline
);
364 assert(poly
!= NULL
);
366 if(dec_current
<= dec_end
) //at least on vertex in dec_Chain
368 sline
= new sampledLine(botVertex
, dec_chain
->getVertex(dec_end
));
369 dline
= new directedLine(INCREASING
, sline
);
371 for(i
=dec_end
; i
>dec_current
; i
--)
373 sline
= new sampledLine(dec_chain
->getVertex(i
), dec_chain
->getVertex(i
-1));
374 dline
= new directedLine(INCREASING
, sline
);
377 sline
= new sampledLine(dec_chain
->getVertex(dec_current
), topVertex
);
378 dline
= new directedLine(INCREASING
, sline
);
381 else //dec_chain is empty
383 sline
= new sampledLine(botVertex
, topVertex
);
384 dline
= new directedLine(INCREASING
, sline
);
390 Int n_edges
= poly
->numEdges();
391 directedLine
** cusps
= (directedLine
**) malloc(sizeof(directedLine
*)*n_edges
);
393 findInteriorCuspsX(poly
, n_cusps
, cusps
);
395 if(n_cusps
==0) //u monotine
397 monoTriangulationFun(poly
, compV2InX
, pStream
);
399 else if(n_cusps
== 1) // one interior cusp
401 directedLine
* new_polygon
= polygonConvert(cusps
[0]);
402 directedLine
* other
= findDiagonal_singleCuspX(new_polygon
);
403 //<other> should NOT be null unless there are self-intersecting
404 //trim curves. In that case, we don't want to core dump, instead,
405 //we triangulate anyway, and print out error message.
408 monoTriangulationFun(poly
, compV2InX
, pStream
);
412 directedLine
* ret_p1
;
413 directedLine
* ret_p2
;
415 new_polygon
->connectDiagonal_2slines(new_polygon
, other
,
420 monoTriangulationFun(ret_p1
, compV2InX
, pStream
);
421 monoTriangulationFun(ret_p2
, compV2InX
, pStream
);
423 ret_p1
->deleteSinglePolygonWithSline();
424 ret_p2
->deleteSinglePolygonWithSline();
429 //we need a general partitionX funtion (supposed to be in partitionX.C,
430 //not implemented yet. XXX
431 //monoTriangulationFun(poly, compV2InY, pStream);
433 directedLine
* new_polygon
= polygonConvert(poly
);
434 directedLine
* list
= monoPolyPart(new_polygon
);
435 for(directedLine
* temp
= list
; temp
!= NULL
; temp
= temp
->getNextPolygon())
437 monoTriangulationFun(temp
, compV2InX
, pStream
);
440 list
->deletePolygonListWithSline();
446 if(numInteriorCuspsX(poly) == 0) //is u monotone
447 monoTriangulationFun(poly, compV2InX, pStream);
448 else //it is not u motone
449 monoTriangulationFun(poly, compV2InY, pStream);
452 poly
->deleteSinglePolygonWithSline();
456 //apparently the following code is not reachable,
457 //it is for test purpose
458 if(inc_current
> inc_end
|| dec_current
>dec_end
)
460 monoTriangulationRecGen(topVertex
, botVertex
, inc_chain
, inc_current
, inc_end
,
461 dec_chain
, dec_current
, dec_end
,
468 area(dec_chain
->getVertex(dec_current
),
470 inc_chain
->getVertex(inc_current
)) >=0
471 && chainConvex(inc_chain
, inc_current
, inc_end
)
472 && chainConcave(dec_chain
, dec_current
, dec_end
)
473 && area(inc_chain
->getVertex(inc_end
), botVertex
, dec_chain
->getVertex(dec_end
)) >=0
476 monoTriangulationRecFunGen(topVertex
, botVertex
,
477 inc_chain
, inc_current
, inc_end
,
478 dec_chain
, dec_current
, dec_end
,
483 monoTriangulationRecGen(topVertex
, botVertex
, inc_chain
, inc_current
, inc_end
,
484 dec_chain
, dec_current
, dec_end
,
489 /*if inc_current>inc_end, then inc_chain has no points to be considered
492 void monoTriangulationRecGen(Real
* topVertex
, Real
* botVertex
,
493 vertexArray
* inc_chain
, Int inc_current
, Int inc_end
,
494 vertexArray
* dec_chain
, Int dec_current
, Int dec_end
,
501 if(inc_current
> inc_end
&& dec_current
>dec_end
)
503 else if(inc_current
>inc_end
) /*no more vertices on inc_chain*/
505 dec_array
= dec_chain
->getArray();
506 reflexChain
rChain(100,0);
507 /*put the top vertex into the reflex chain*/
508 rChain
.processNewVertex(topVertex
, pStream
);
509 /*process all the vertices on the dec_chain*/
510 for(i
=dec_current
; i
<=dec_end
; i
++){
511 rChain
.processNewVertex(dec_array
[i
], pStream
);
513 /*process the bottom vertex*/
514 rChain
.processNewVertex(botVertex
, pStream
);
516 else if(dec_current
> dec_end
) /*no more vertices on dec_chain*/
518 inc_array
= inc_chain
->getArray();
520 reflexChain
rChain(100,1);
521 /*put the top vertex into the reflex chain*/
522 rChain
.processNewVertex(topVertex
, pStream
);
523 /*process all the vertices on the inc_chain*/
524 for(i
=inc_current
; i
<=inc_end
; i
++){
525 rChain
.processNewVertex(inc_array
[i
], pStream
);
527 /*process the bottom vertex*/
528 rChain
.processNewVertex(botVertex
, pStream
);
530 else /*neither chain is empty*/
532 inc_array
= inc_chain
-> getArray();
533 dec_array
= dec_chain
-> getArray();
535 /*if top of inc_chain is 'lower' than top of dec_chain, process all the
536 *vertices on the dec_chain which are higher than top of inc_chain
538 if(compV2InY(inc_array
[inc_current
], dec_array
[dec_current
]) <= 0)
541 reflexChain
rChain(100, 0);
542 rChain
.processNewVertex(topVertex
, pStream
);
543 for(i
=dec_current
; i
<=dec_end
; i
++)
545 if(compV2InY(inc_array
[inc_current
], dec_array
[i
]) <= 0)
546 rChain
.processNewVertex(dec_array
[i
], pStream
);
550 rChain
.outputFan(inc_array
[inc_current
], pStream
);
551 monoTriangulationRecGen(dec_array
[i
-1], botVertex
,
552 inc_chain
, inc_current
, inc_end
,
553 dec_chain
, i
, dec_end
,
556 else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
559 reflexChain
rChain(100, 1);
560 rChain
.processNewVertex(topVertex
, pStream
);
561 for(i
=inc_current
; i
<=inc_end
; i
++)
563 if(compV2InY(inc_array
[i
], dec_array
[dec_current
]) >0)
564 rChain
.processNewVertex(inc_array
[i
], pStream
);
568 rChain
.outputFan(dec_array
[dec_current
], pStream
);
569 monoTriangulationRecGen(inc_array
[i
-1], botVertex
,
570 inc_chain
, i
, inc_end
,
571 dec_chain
, dec_current
,dec_end
,
574 }/*end case neither is empty*/
577 void monoTriangulationFun(directedLine
* monoPolygon
, Int (*compFun
)(Real
*, Real
*), primStream
* pStream
)
580 /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
581 *then call monoTriangulationRec
586 topV
= botV
= monoPolygon
;
587 for(tempV
= monoPolygon
->getNext(); tempV
!= monoPolygon
; tempV
= tempV
->getNext())
589 if(compFun(topV
->head(), tempV
->head())<0) {
592 if(compFun(botV
->head(), tempV
->head())>0) {
597 /*creat increase and decrease chains*/
598 vertexArray
inc_chain(20); /*this is a dynamic array*/
599 for(i
=1; i
<=topV
->get_npoints()-2; i
++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
600 inc_chain
.appendVertex(topV
->getVertex(i
));
602 for(tempV
= topV
->getNext(); tempV
!= botV
; tempV
= tempV
->getNext())
604 for(i
=0; i
<=tempV
->get_npoints()-2; i
++){
605 inc_chain
.appendVertex(tempV
->getVertex(i
));
609 vertexArray
dec_chain(20);
610 for(tempV
= topV
->getPrev(); tempV
!= botV
; tempV
= tempV
->getPrev())
612 for(i
=tempV
->get_npoints()-2; i
>=0; i
--){
613 dec_chain
.appendVertex(tempV
->getVertex(i
));
616 for(i
=botV
->get_npoints()-2; i
>=1; i
--){
617 dec_chain
.appendVertex(tempV
->getVertex(i
));
620 if (!(0 == inc_chain
.getNumElements() && 0 == dec_chain
.getNumElements())) {
621 monoTriangulationRecFun(topV
->head(), botV
->head(), &inc_chain
, 0,
622 &dec_chain
, 0, compFun
, pStream
);
626 void monoTriangulation(directedLine
* monoPolygon
, primStream
* pStream
)
629 /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
630 *then call monoTriangulationRec
635 topV
= botV
= monoPolygon
;
636 for(tempV
= monoPolygon
->getNext(); tempV
!= monoPolygon
; tempV
= tempV
->getNext())
638 if(compV2InY(topV
->head(), tempV
->head())<0) {
641 if(compV2InY(botV
->head(), tempV
->head())>0) {
645 /*creat increase and decrease chains*/
646 vertexArray
inc_chain(20); /*this is a dynamic array*/
647 for(i
=1; i
<=topV
->get_npoints()-2; i
++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
648 inc_chain
.appendVertex(topV
->getVertex(i
));
650 for(tempV
= topV
->getNext(); tempV
!= botV
; tempV
= tempV
->getNext())
652 for(i
=0; i
<=tempV
->get_npoints()-2; i
++){
653 inc_chain
.appendVertex(tempV
->getVertex(i
));
657 vertexArray
dec_chain(20);
658 for(tempV
= topV
->getPrev(); tempV
!= botV
; tempV
= tempV
->getPrev())
660 for(i
=tempV
->get_npoints()-2; i
>=0; i
--){
661 dec_chain
.appendVertex(tempV
->getVertex(i
));
664 for(i
=botV
->get_npoints()-2; i
>=1; i
--){
665 dec_chain
.appendVertex(tempV
->getVertex(i
));
668 monoTriangulationRec(topV
->head(), botV
->head(), &inc_chain
, 0, &dec_chain
, 0, pStream
);
672 /*the chain could be increasing or decreasing, although we use the
674 *the argument is_increase_chain indicates whether this chain
675 *is increasing (left chain in V-monotone case) or decreaing (right chain
676 *in V-monotone case).
678 void monoTriangulation2(Real
* topVertex
, Real
* botVertex
,
679 vertexArray
* inc_chain
, Int inc_smallIndex
,
681 Int is_increase_chain
,
684 assert( inc_chain
!= NULL
);
687 if(inc_smallIndex
> inc_largeIndex
)
688 return; //no triangles
689 if(inc_smallIndex
== inc_largeIndex
)
691 if(is_increase_chain
)
692 pStream
->triangle(inc_chain
->getVertex(inc_smallIndex
), botVertex
, topVertex
);
694 pStream
->triangle(inc_chain
->getVertex(inc_smallIndex
), topVertex
, botVertex
);
699 if(is_increase_chain
&& botVertex
[1] == inc_chain
->getVertex(inc_largeIndex
)[1])
701 pStream
->triangle(botVertex
, inc_chain
->getVertex(inc_largeIndex
-1),
702 inc_chain
->getVertex(inc_largeIndex
));
703 monoTriangulation2(topVertex
, botVertex
, inc_chain
, inc_smallIndex
,
709 else if( (!is_increase_chain
) && topVertex
[1] == inc_chain
->getVertex(inc_smallIndex
)[1])
711 pStream
->triangle(topVertex
, inc_chain
->getVertex(inc_smallIndex
+1),
712 inc_chain
->getVertex(inc_smallIndex
));
713 monoTriangulation2(topVertex
, botVertex
, inc_chain
, inc_smallIndex
+1,
714 inc_largeIndex
, is_increase_chain
, pStream
);
718 inc_array
= inc_chain
->getArray();
720 reflexChain
rChain(20,is_increase_chain
); /*1 means the chain is increasing*/
722 rChain
.processNewVertex(topVertex
, pStream
);
724 for(i
=inc_smallIndex
; i
<=inc_largeIndex
; i
++){
725 rChain
.processNewVertex(inc_array
[i
], pStream
);
727 rChain
.processNewVertex(botVertex
, pStream
);
731 /*if compFun == compV2InY, top to bottom: V-monotone
732 *if compFun == compV2InX, right to left: U-monotone
734 void monoTriangulationRecFunGen(Real
* topVertex
, Real
* botVertex
,
735 vertexArray
* inc_chain
, Int inc_current
, Int inc_end
,
736 vertexArray
* dec_chain
, Int dec_current
, Int dec_end
,
737 Int (*compFun
)(Real
*, Real
*),
740 assert( inc_chain
!= NULL
&& dec_chain
!= NULL
);
741 assert( ! (inc_current
> inc_end
&&
742 dec_current
> dec_end
));
750 assert( ! ( (inc_chain
==NULL
) && (dec_chain
==NULL
)));
752 if(inc_current
> inc_end
) /*no more vertices on inc_chain*/
755 dec_array
= dec_chain
->getArray();
756 reflexChain
rChain(20,0);
757 /*put the top vertex into the reflex chain*/
758 rChain
.processNewVertex(topVertex
, pStream
);
759 /*process all the vertices on the dec_chain*/
760 for(i
=dec_current
; i
<=dec_end
; i
++){
761 rChain
.processNewVertex(dec_array
[i
], pStream
);
763 /*process the bottom vertex*/
764 rChain
.processNewVertex(botVertex
, pStream
);
767 else if(dec_current
> dec_end
) /*no more vertices on dec_chain*/
769 inc_array
= inc_chain
->getArray();
770 reflexChain
rChain(20,1);
771 /*put the top vertex into the reflex chain*/
772 rChain
.processNewVertex(topVertex
, pStream
);
773 /*process all the vertices on the inc_chain*/
774 for(i
=inc_current
; i
<=inc_end
; i
++){
775 rChain
.processNewVertex(inc_array
[i
], pStream
);
777 /*process the bottom vertex*/
778 rChain
.processNewVertex(botVertex
, pStream
);
780 else /*neither chain is empty*/
782 inc_array
= inc_chain
-> getArray();
783 dec_array
= dec_chain
-> getArray();
785 /*if top of inc_chain is 'lower' than top of dec_chain, process all the
786 *vertices on the dec_chain which are higher than top of inc_chain
788 if(compFun(inc_array
[inc_current
], dec_array
[dec_current
]) <= 0)
791 reflexChain
rChain(20, 0);
792 rChain
.processNewVertex(topVertex
, pStream
);
793 for(i
=dec_current
; i
<=dec_end
; i
++)
795 if(compFun(inc_array
[inc_current
], dec_array
[i
]) <= 0)
796 rChain
.processNewVertex(dec_array
[i
], pStream
);
800 rChain
.outputFan(inc_array
[inc_current
], pStream
);
801 monoTriangulationRecFunGen(dec_array
[i
-1], botVertex
,
802 inc_chain
, inc_current
, inc_end
,
803 dec_chain
, i
, dec_end
,
807 else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
810 reflexChain
rChain(20, 1);
811 rChain
.processNewVertex(topVertex
, pStream
);
812 for(i
=inc_current
; i
<=inc_end
; i
++)
814 if(compFun(inc_array
[i
], dec_array
[dec_current
]) >0)
815 rChain
.processNewVertex(inc_array
[i
], pStream
);
819 rChain
.outputFan(dec_array
[dec_current
], pStream
);
820 monoTriangulationRecFunGen(inc_array
[i
-1], botVertex
,
821 inc_chain
, i
,inc_end
,
822 dec_chain
, dec_current
,dec_end
,
826 }/*end case neither is empty*/
829 /*if compFun == compV2InY, top to bottom: V-monotone
830 *if compFun == compV2InX, right to left: U-monotone
832 void monoTriangulationRecFun(Real
* topVertex
, Real
* botVertex
,
833 vertexArray
* inc_chain
, Int inc_current
,
834 vertexArray
* dec_chain
, Int dec_current
,
835 Int (*compFun
)(Real
*, Real
*),
838 assert( inc_chain
!= NULL
&& dec_chain
!= NULL
);
839 assert( ! (inc_current
>=inc_chain
->getNumElements() &&
840 dec_current
>=dec_chain
->getNumElements()));
846 assert( ! ( (inc_chain
==NULL
) && (dec_chain
==NULL
)));
848 if(inc_current
>=inc_chain
->getNumElements()) /*no more vertices on inc_chain*/
851 dec_array
= dec_chain
->getArray();
852 dec_nVertices
= dec_chain
->getNumElements();
853 reflexChain
rChain(20,0);
854 /*put the top vertex into the reflex chain*/
855 rChain
.processNewVertex(topVertex
, pStream
);
856 /*process all the vertices on the dec_chain*/
857 for(i
=dec_current
; i
<dec_nVertices
; i
++){
858 rChain
.processNewVertex(dec_array
[i
], pStream
);
860 /*process the bottom vertex*/
861 rChain
.processNewVertex(botVertex
, pStream
);
864 else if(dec_current
>= dec_chain
->getNumElements()) /*no more vertices on dec_chain*/
866 inc_array
= inc_chain
->getArray();
867 inc_nVertices
= inc_chain
->getNumElements();
868 reflexChain
rChain(20,1);
869 /*put the top vertex into the reflex chain*/
870 rChain
.processNewVertex(topVertex
, pStream
);
871 /*process all the vertices on the inc_chain*/
872 for(i
=inc_current
; i
<inc_nVertices
; i
++){
873 rChain
.processNewVertex(inc_array
[i
], pStream
);
875 /*process the bottom vertex*/
876 rChain
.processNewVertex(botVertex
, pStream
);
878 else /*neither chain is empty*/
880 inc_array
= inc_chain
-> getArray();
881 dec_array
= dec_chain
-> getArray();
882 inc_nVertices
= inc_chain
->getNumElements();
883 dec_nVertices
= dec_chain
->getNumElements();
884 /*if top of inc_chain is 'lower' than top of dec_chain, process all the
885 *vertices on the dec_chain which are higher than top of inc_chain
887 if(compFun(inc_array
[inc_current
], dec_array
[dec_current
]) <= 0)
890 reflexChain
rChain(20, 0);
891 rChain
.processNewVertex(topVertex
, pStream
);
892 for(i
=dec_current
; i
<dec_nVertices
; i
++)
894 if(compFun(inc_array
[inc_current
], dec_array
[i
]) <= 0)
895 rChain
.processNewVertex(dec_array
[i
], pStream
);
899 rChain
.outputFan(inc_array
[inc_current
], pStream
);
900 monoTriangulationRecFun(dec_array
[i
-1], botVertex
,
901 inc_chain
, inc_current
,
906 else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
909 reflexChain
rChain(20, 1);
910 rChain
.processNewVertex(topVertex
, pStream
);
911 for(i
=inc_current
; i
<inc_nVertices
; i
++)
913 if(compFun(inc_array
[i
], dec_array
[dec_current
]) >0)
914 rChain
.processNewVertex(inc_array
[i
], pStream
);
918 rChain
.outputFan(dec_array
[dec_current
], pStream
);
919 monoTriangulationRecFun(inc_array
[i
-1], botVertex
,
921 dec_chain
, dec_current
,
925 }/*end case neither is empty*/
929 void monoTriangulationRec(Real
* topVertex
, Real
* botVertex
,
930 vertexArray
* inc_chain
, Int inc_current
,
931 vertexArray
* dec_chain
, Int dec_current
,
934 assert( inc_chain
!= NULL
&& dec_chain
!= NULL
);
935 assert( ! (inc_current
>=inc_chain
->getNumElements() &&
936 dec_current
>=dec_chain
->getNumElements()));
942 assert( ! ( (inc_chain
==NULL
) && (dec_chain
==NULL
)));
944 if(inc_current
>=inc_chain
->getNumElements()) /*no more vertices on inc_chain*/
947 dec_array
= dec_chain
->getArray();
948 dec_nVertices
= dec_chain
->getNumElements();
949 reflexChain
rChain(20,0);
950 /*put the top vertex into the reflex chain*/
951 rChain
.processNewVertex(topVertex
, pStream
);
952 /*process all the vertices on the dec_chain*/
953 for(i
=dec_current
; i
<dec_nVertices
; i
++){
954 rChain
.processNewVertex(dec_array
[i
], pStream
);
956 /*process the bottom vertex*/
957 rChain
.processNewVertex(botVertex
, pStream
);
960 else if(dec_current
>= dec_chain
->getNumElements()) /*no more vertices on dec_chain*/
962 inc_array
= inc_chain
->getArray();
963 inc_nVertices
= inc_chain
->getNumElements();
964 reflexChain
rChain(20,1);
965 /*put the top vertex into the reflex chain*/
966 rChain
.processNewVertex(topVertex
, pStream
);
967 /*process all the vertices on the inc_chain*/
968 for(i
=inc_current
; i
<inc_nVertices
; i
++){
969 rChain
.processNewVertex(inc_array
[i
], pStream
);
971 /*process the bottom vertex*/
972 rChain
.processNewVertex(botVertex
, pStream
);
974 else /*neither chain is empty*/
976 inc_array
= inc_chain
-> getArray();
977 dec_array
= dec_chain
-> getArray();
978 inc_nVertices
= inc_chain
->getNumElements();
979 dec_nVertices
= dec_chain
->getNumElements();
980 /*if top of inc_chain is 'lower' than top of dec_chain, process all the
981 *vertices on the dec_chain which are higher than top of inc_chain
983 if(compV2InY(inc_array
[inc_current
], dec_array
[dec_current
]) <= 0)
986 reflexChain
rChain(20, 0);
987 rChain
.processNewVertex(topVertex
, pStream
);
988 for(i
=dec_current
; i
<dec_nVertices
; i
++)
990 if(compV2InY(inc_array
[inc_current
], dec_array
[i
]) <= 0)
991 rChain
.processNewVertex(dec_array
[i
], pStream
);
995 rChain
.outputFan(inc_array
[inc_current
], pStream
);
996 monoTriangulationRec(dec_array
[i
-1], botVertex
,
997 inc_chain
, inc_current
,
1001 else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
1004 reflexChain
rChain(20, 1);
1005 rChain
.processNewVertex(topVertex
, pStream
);
1006 for(i
=inc_current
; i
<inc_nVertices
; i
++)
1008 if(compV2InY(inc_array
[i
], dec_array
[dec_current
]) >0)
1009 rChain
.processNewVertex(inc_array
[i
], pStream
);
1013 rChain
.outputFan(dec_array
[dec_current
], pStream
);
1014 monoTriangulationRec(inc_array
[i
-1], botVertex
,
1016 dec_chain
, dec_current
,
1019 }/*end case neither is empty*/
1024 /* the name here assumes that the polygon is Y-monotone, but
1025 *this function also works for X-monotone polygons.
1026 * a monotne polygon consists of two extrem verteices: topVertex and botVertex, and
1027 *two monotone chains: inc_chain, and dec_chain. The edges of the increasing chain (inc_chain)
1028 *is ordered by following pointer: next, while the edges of the decreasing chain (dec_chain)
1029 *is ordered by following pointer: prev
1030 * inc_index index the vertex which is the toppest of the inc_chain which we are handling currently.
1031 * dec_index index the vertex which is the toppest of the dec_chain which we are handling currently.
1033 void monoTriangulationRec(directedLine
* inc_chain
, Int inc_index
,
1034 directedLine
* dec_chain
, Int dec_index
,
1035 directedLine
* topVertex
, Int top_index
,
1036 directedLine
* botVertex
,
1037 primStream
* pStream
)
1040 directedLine
*temp
, *oldtemp
= NULL
;
1041 Int tempIndex
, oldtempIndex
= 0;
1043 assert(inc_chain
!= NULL
&& dec_chain
!= NULL
);
1045 if(inc_chain
== botVertex
) {
1046 reflexChain
rChain(20, 0);
1047 rChain
.processNewVertex(topVertex
->getVertex(top_index
), pStream
);
1048 for(i
=dec_index
; i
< dec_chain
->get_npoints(); i
++){
1049 rChain
.processNewVertex(dec_chain
->getVertex(i
), pStream
);
1051 for(temp
= dec_chain
->getPrev(); temp
!= botVertex
; temp
= temp
->getPrev())
1053 for(i
=0; i
<temp
->get_npoints(); i
++){
1054 rChain
.processNewVertex(temp
->getVertex(i
), pStream
);
1058 else if(dec_chain
==botVertex
) {
1059 reflexChain
rChain(20, 1);
1060 rChain
.processNewVertex(topVertex
->getVertex(top_index
), pStream
);
1061 for(i
=inc_index
; i
< inc_chain
->get_npoints(); i
++){
1062 rChain
.processNewVertex(inc_chain
->getVertex(i
), pStream
);
1064 for(temp
= inc_chain
->getPrev(); temp
!= botVertex
; temp
= temp
->getNext())
1066 for(i
=0; i
<temp
->get_npoints(); i
++){
1067 rChain
.processNewVertex(temp
->getVertex(i
), pStream
);
1071 else /*neither reached the bottom*/{
1072 if(compV2InY(inc_chain
->getVertex(inc_index
), dec_chain
->getVertex(dec_index
)) <=0) {
1073 reflexChain
rChain(20, 0);
1074 rChain
.processNewVertex(topVertex
-> getVertex(top_index
), pStream
);
1076 tempIndex
= dec_index
;
1077 while( compV2InY(inc_chain
->getVertex(inc_index
), temp
->getVertex(tempIndex
))<=0) {
1079 oldtempIndex
= tempIndex
;
1080 rChain
.processNewVertex(temp
->getVertex(tempIndex
), pStream
);
1082 if(tempIndex
== temp
->get_npoints()-1){
1084 temp
= temp
->getPrev();
1090 rChain
.outputFan(inc_chain
->getVertex(inc_index
), pStream
);
1091 monoTriangulationRec(inc_chain
, inc_index
, temp
, tempIndex
, oldtemp
, oldtempIndex
, botVertex
, pStream
);
1094 reflexChain
rChain(20, 1);
1095 rChain
.processNewVertex(topVertex
-> getVertex(top_index
), pStream
);
1097 tempIndex
= inc_index
;
1098 while( compV2InY(temp
->getVertex(tempIndex
), dec_chain
->getVertex(dec_index
))>0){
1100 oldtempIndex
= tempIndex
;
1101 rChain
.processNewVertex(temp
->getVertex(tempIndex
), pStream
);
1103 if(tempIndex
== temp
->get_npoints()-1){
1105 temp
= temp
->getNext();
1111 rChain
.outputFan(dec_chain
->getVertex(dec_index
), pStream
);
1112 monoTriangulationRec(temp
, tempIndex
, dec_chain
, dec_index
, oldtemp
, oldtempIndex
, botVertex
, pStream
);
1114 } /*end case neither reached the bottom*/
1117 /***************************vertexArray begin here**********************************/
1118 vertexArray::vertexArray(Real2
* vertices
, Int nVertices
)
1121 size
= index
= nVertices
;
1122 array
= (Real
**) malloc(sizeof(Real
*) * nVertices
);
1124 for(i
=0; i
<nVertices
; i
++)
1126 array
[i
] = vertices
[i
];
1127 array
[i
] = vertices
[i
];
1131 vertexArray::vertexArray(Int s
)
1134 array
= (Real
**) malloc(sizeof(Real
*) * s
);
1139 vertexArray::~vertexArray()
1144 void vertexArray::appendVertex(Real
* ptr
)
1148 Real
** temp
= (Real
**) malloc(sizeof(Real
*) * (2*size
+1));
1150 for(i
=0; i
<index
; i
++)
1156 array
[index
++] = ptr
;
1159 void vertexArray::print()
1161 printf("vertex Array:index=%i, size=%i\n", index
, size
);
1162 for(Int i
=0; i
<index
; i
++)
1164 printf("(%f,%f) ", array
[i
][0], array
[i
][1]);
1169 /*find the first i such that array[i][1] >= v
1170 * and array[i+1][1] <v
1171 * if index == 0 (the array is empty, return -1.
1172 * if v is above all, return -1.
1173 * if v is below all, return index-1.
1175 Int
vertexArray::findIndexAbove(Real v
)
1180 else if(array
[0][1] < v
)
1184 for(i
=1; i
<index
; i
++)
1193 /*find the first i<=endIndex such that array[i][1] <= v
1194 * and array[i-1][1] > v
1195 *if sartIndex>endIndex, then return endIndex+1.
1196 *otherwise, startIndex<=endIndex, it is assumed that
1197 * 0<=startIndex<=endIndex<index.
1198 * if v is below all, return endIndex+1
1199 * if v is above all, return startIndex.
1201 Int
vertexArray::findIndexBelowGen(Real v
, Int startIndex
, Int endIndex
)
1204 if(startIndex
> endIndex
)
1206 else if(array
[endIndex
][1] > v
)
1208 else //now array[endIndex][1] <= v
1210 for(i
=endIndex
-1; i
>=startIndex
; i
--)
1219 /*find the first i<=endIndex such that array[i-1][1] >= v
1220 * and array[i][1] < v
1221 *if sartIndex>endIndex, then return endIndex+1.
1222 *otherwise, startIndex<=endIndex, it is assumed that
1223 * 0<=startIndex<=endIndex<index.
1224 * if v is below or equal to all, return endIndex+1
1225 * if v is strictly above all, return startIndex.
1227 Int
vertexArray::findIndexStrictBelowGen(Real v
, Int startIndex
, Int endIndex
)
1230 if(startIndex
> endIndex
)
1232 else if(array
[endIndex
][1] >= v
)
1234 else //now array[endIndex][1] < v
1236 for(i
=endIndex
-1; i
>=startIndex
; i
--)
1238 if(array
[i
][1] >= v
)
1245 /*find the first i>startIndex such that array[i-1][1] > v
1246 * and array[i][1] >=v
1247 *if sartIndex>endIndex, then return startIndex-1.
1248 *otherwise, startIndex<=endIndex, it is assumed that
1249 * 0<=startIndex<=endIndex<index.
1250 * if v is strictly above all, return startIndex-1
1251 * if v is strictly below all, return endIndex.
1253 Int
vertexArray::findIndexFirstAboveEqualGen(Real v
, Int startIndex
, Int endIndex
)
1257 if(startIndex
> endIndex
)
1258 return startIndex
-1;
1259 else if(array
[startIndex
][1] < v
)
1260 return startIndex
-1;
1261 else //now array[startIndex][1] >= v
1264 for(i
=startIndex
; i
<=endIndex
; i
++)
1266 if(array
[i
][1] <= v
)
1269 if(i
>endIndex
) // v is strictly below all
1271 else if(array
[i
][1] == v
)
1280 /*find the first i>=startIndex such that array[i][1] >= v
1281 * and array[i+1][1] <v
1282 *if sartIndex>endIndex, then return startIndex-1.
1283 *otherwise, startIndex<=endIndex, it is assumed that
1284 * 0<=startIndex<=endIndex<index.
1285 * if v is above all, return startIndex-1
1286 * if v is below all, return endIndex.
1288 Int
vertexArray::findIndexAboveGen(Real v
, Int startIndex
, Int endIndex
)
1291 if(startIndex
> endIndex
)
1292 return startIndex
-1;
1293 else if(array
[startIndex
][1] < v
)
1294 return startIndex
-1;
1295 else //now array[startIndex][1] >= v
1297 for(i
=startIndex
+1; i
<=endIndex
; i
++)
1306 Int
vertexArray::findDecreaseChainFromEnd(Int begin
, Int end
)
1309 Real prevU
= array
[i
][0];
1311 for(i
=end
-1; i
>=begin
; i
--){
1312 thisU
= array
[i
][0];
1321 //if(V(start) == v, return start, other wise return the
1322 //last i so that V(i)==v
1323 Int
vertexArray::skipEqualityFromStart(Real v
, Int start
, Int end
)
1326 if(array
[start
][1] != v
)
1328 //now array[start][1] == v
1329 for(i
=start
+1; i
<= end
; i
++)
1330 if(array
[i
][1] != v
)
1336 /***************************vertexArray end****************************************/
1340 /***************************relfex chain stuff begin here*****************************/
1342 reflexChain::reflexChain(Int size
, Int is_increasing
)
1344 queue
= (Real2
*) malloc(sizeof(Real2
) * size
);
1348 isIncreasing
= is_increasing
;
1351 reflexChain::~reflexChain()
1356 /*put (u,v) at the end of the queue
1357 *pay attention to space
1359 void reflexChain::insert(Real u
, Real v
)
1362 if(index_queue
>= size_queue
) {
1363 Real2
*temp
= (Real2
*) malloc(sizeof(Real2
) * (2*size_queue
+1));
1367 for(i
=0; i
<index_queue
; i
++){
1368 temp
[i
][0] = queue
[i
][0];
1369 temp
[i
][1] = queue
[i
][1];
1374 size_queue
= 2*size_queue
+ 1;
1377 queue
[index_queue
][0] = u
;
1378 queue
[index_queue
][1] = v
;
1382 void reflexChain::insert(Real v
[2])
1388 static Real area(Real A[2], Real B[2], Real C[2])
1390 Real Bx, By, Cx, Cy;
1395 return Bx*Cy - Cx*By;
1399 /*the chain is reflex, and the vertex v is
1400 *on the other side of the chain, so that
1401 *we can outout the fan with v as the
1404 void reflexChain::outputFan(Real v
[2], primStream
* pStream
)
1410 for(i
=0; i
<index_queue
; i
++)
1411 pStream
->insert(queue
[i
]);
1414 for(i
=index_queue
-1; i
>=0; i
--)
1415 pStream
->insert(queue
[i
]);
1417 pStream
->end(PRIMITIVE_STREAM_FAN
);
1420 void reflexChain::processNewVertex(Real v
[2], primStream
* pStream
)
1424 /*if there are at most one vertex in the queue, then simply insert
1426 if(index_queue
<=1){
1431 /*there are at least two vertices in the queue*/
1434 for(i
=j
; i
>=1; i
--) {
1436 isReflex
= (area(queue
[i
-1], queue
[i
], v
) <= 0.0);
1438 else /*decreasing*/{
1439 isReflex
= (area(v
, queue
[i
], queue
[i
-1]) <= 0.0);
1447 *if i<j then vertices: i+1--j are convex
1448 * output triangle fan:
1449 * v, and queue[i], i+1, ..., j
1457 pStream
->insert(queue
[k
]);
1461 pStream
->insert(queue
[k
]);
1464 pStream
->end(PRIMITIVE_STREAM_FAN
);
1467 /*delete vertices i+1--j from the queue*/
1469 /*finally insert v at the end of the queue*/
1474 void reflexChain::print()
1477 printf("reflex chain: isIncreasing=%i\n", isIncreasing
);
1478 for(i
=0; i
<index_queue
; i
++) {
1479 printf("(%f,%f) ", queue
[i
][0], queue
[i
][1]);