aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glu/sgi/libnurbs/nurbtess
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2009-10-09 06:31:44 +0000
committermarha <marha@users.sourceforge.net>2009-10-09 06:31:44 +0000
commit06456f5db88b434c3634ede42bdbfdce78fc4249 (patch)
tree97f5174e2d3da40faee7f2ad8858233da3d0166e /mesalib/src/glu/sgi/libnurbs/nurbtess
parent7b230a3fe2d6c83488d9eec43067fe8ba8ac081b (diff)
parenta0c4815433ccd57322f4f7703ca35e9ccfa59250 (diff)
downloadvcxsrv-06456f5db88b434c3634ede42bdbfdce78fc4249.tar.gz
vcxsrv-06456f5db88b434c3634ede42bdbfdce78fc4249.tar.bz2
vcxsrv-06456f5db88b434c3634ede42bdbfdce78fc4249.zip
svn merge ^/branches/released . --username marha
Diffstat (limited to 'mesalib/src/glu/sgi/libnurbs/nurbtess')
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/definitions.h40
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.cc848
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.h171
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/glimports.h42
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc293
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.h137
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.cc934
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.h103
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc299
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h41
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc1482
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h184
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/mystdio.h60
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/mystdlib.h57
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.cc162
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.h54
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.cc836
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.h97
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc734
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.h68
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc90
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.h47
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc190
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h109
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.cc77
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.h42
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc196
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.h82
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc371
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.h86
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc844
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h138
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc644
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h117
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc1030
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h67
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc2427
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h184
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc179
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.h71
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.cc282
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.h61
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/zlassert.h34
43 files changed, 14010 insertions, 0 deletions
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/definitions.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/definitions.h
new file mode 100644
index 000000000..962921da1
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/definitions.h
@@ -0,0 +1,40 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _DEFINITIONS_H
+#define _DEFINITIONS_H
+
+typedef float Real;
+typedef int Int;
+typedef Real Real2[2];
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.cc
new file mode 100644
index 000000000..74450352d
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.cc
@@ -0,0 +1,848 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "quicksort.h"
+#include "directedLine.h"
+#include "polyDBG.h"
+
+#ifdef __WATCOMC__
+#pragma warning 726 10
+#endif
+
+//we must return the newLine
+directedLine* directedLine::deleteChain(directedLine* begin, directedLine* end)
+{
+ if(begin->head()[0] == end->tail()[0] &&
+ begin->head()[1] == end->tail()[1]
+ )
+ {
+ directedLine *ret = begin->prev;
+ begin->prev->next = end->next;
+ end->next->prev = begin->prev;
+ delete begin->sline;
+ delete end->sline;
+ delete begin;
+ delete end;
+
+ return ret;
+ }
+
+ directedLine* newLine;
+ sampledLine* sline = new sampledLine(begin->head(), end->tail());
+ newLine = new directedLine(INCREASING, sline);
+ directedLine *p = begin->prev;
+ directedLine *n = end->next;
+ p->next = newLine;
+ n->prev = newLine;
+ newLine->prev = p;
+ newLine->next = n;
+
+ delete begin->sline;
+ delete end->sline;
+ delete begin;
+ delete end;
+ return newLine;
+}
+
+
+void directedLine::deleteSingleLine(directedLine* dline)
+{
+ //make sure that dline->prev->tail is the same as
+ //dline->next->head. This is for numerical erros.
+ //for example, if we delete a line which is almost degeneate
+ //within (epsilon), then we want to make that the polygon after deletion
+ //is still a valid polygon
+
+ dline->next->head()[0] = dline->prev->tail()[0];
+ dline->next->head()[1] = dline->prev->tail()[1];
+
+ dline->prev->next = dline->next;
+ dline->next->prev = dline->prev;
+
+ delete dline;
+
+}
+
+static Int myequal(Real a[2], Real b[2])
+{
+ /*
+ if(a[0]==b[0] && a[1] == b[1])
+ return 1;
+ else
+ return 0;
+ */
+
+
+ if(fabs(a[0]-b[0]) < 0.00001 &&
+ fabs(a[1]-b[1]) < 0.00001)
+ return 1;
+ else
+ return 0;
+
+}
+
+directedLine* directedLine::deleteDegenerateLines()
+{
+ //if there is only one edge or two edges, don't do anything
+ if(this->next == this)
+ return this;
+ if(this->next == this->prev)
+ return this;
+
+ //find a nondegenerate line
+ directedLine* temp;
+ directedLine* first = NULL;
+ if(! myequal(head(), tail()))
+ /*
+ if(head()[0] != tail()[0] ||
+ head()[1] != tail()[1])
+ */
+ first = this;
+ else
+ {
+ for(temp = this->next; temp != this; temp = temp->next)
+ {
+ /*
+ if(temp->head()[0] != temp->tail()[0] ||
+ temp->head()[1] != temp->tail()[1])
+ */
+ if(! myequal(temp->head(), temp->tail()))
+ {
+ first = temp;
+ break;
+ }
+
+ }
+ }
+
+ //if there are no non-degenerate lines, then we simply return NULL.
+ if(first == NULL)
+ {
+ deleteSinglePolygonWithSline();
+ return NULL;
+ }
+
+ directedLine* tempNext = NULL;
+ for(temp =first->next; temp != first; temp = tempNext)
+ {
+ tempNext = temp->getNext();
+/*
+ if(temp->head()[0] == temp->tail()[0] &&
+ temp->head()[1] == temp->tail()[1])
+*/
+
+ if(myequal(temp->head(), temp->tail()))
+ deleteSingleLine(temp);
+ }
+ return first;
+}
+
+directedLine* directedLine::deleteDegenerateLinesAllPolygons()
+{
+ directedLine* temp;
+ directedLine *tempNext = NULL;
+ directedLine* ret= NULL;
+ directedLine* retEnd = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->nextPolygon = NULL;
+ if(ret == NULL)
+ {
+ ret = retEnd = temp->deleteDegenerateLines();
+
+ }
+ else
+ {
+ directedLine *newPolygon = temp->deleteDegenerateLines();
+ if(newPolygon != NULL)
+ {
+ retEnd->nextPolygon = temp->deleteDegenerateLines();
+ retEnd = retEnd->nextPolygon;
+ }
+ }
+ }
+ return ret;
+}
+
+directedLine* directedLine::cutIntersectionAllPoly(int &cutOccur)
+{
+ directedLine* temp;
+ directedLine *tempNext = NULL;
+ directedLine* ret= NULL;
+ directedLine* retEnd = NULL;
+ cutOccur = 0;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ int eachCutOccur=0;
+ tempNext = temp->nextPolygon;
+ temp->nextPolygon = NULL;
+ if(ret == NULL)
+ {
+
+ ret = retEnd = DBG_cutIntersectionPoly(temp, eachCutOccur);
+ if(eachCutOccur)
+ cutOccur = 1;
+ }
+ else
+ {
+
+ retEnd->nextPolygon = DBG_cutIntersectionPoly(temp, eachCutOccur);
+ retEnd = retEnd->nextPolygon;
+ if(eachCutOccur)
+ cutOccur = 1;
+ }
+ }
+ return ret;
+}
+
+
+void directedLine::deleteSinglePolygonWithSline()
+{
+ directedLine *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp->sline;
+ delete temp;
+ }
+}
+
+void directedLine::deletePolygonListWithSline()
+{
+ directedLine *temp, *tempNext;
+ for(temp=this; temp != NULL; temp=tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteSinglePolygonWithSline();
+ }
+}
+
+void directedLine::deleteSinglePolygon()
+{
+ directedLine *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+void directedLine::deletePolygonList()
+{
+ directedLine *temp, *tempNext;
+ for(temp=this; temp != NULL; temp=tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteSinglePolygon();
+ }
+}
+
+
+/*a loop by itself*/
+directedLine::directedLine(short dir, sampledLine* sl)
+{
+ direction = dir;
+ sline = sl;
+ next = this;
+ prev = this;
+ nextPolygon = NULL;
+// prevPolygon = NULL;
+ rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
+
+ rootLink = NULL;
+
+}
+
+void directedLine::init(short dir, sampledLine* sl)
+{
+ direction = dir;
+ sline = sl;
+}
+
+directedLine::directedLine()
+{
+ next = this;
+ prev = this;
+ nextPolygon = NULL;
+ rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
+ rootLink = NULL;
+}
+
+directedLine::~directedLine()
+{
+}
+
+Real* directedLine::head()
+{
+
+ return (direction==INCREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
+}
+
+/*inline*/ Real* directedLine::getVertex(Int i)
+{
+ return (direction==INCREASING)? (sline->get_points())[i] : (sline->get_points())[sline->get_npoints() - 1 -i];
+}
+
+Real* directedLine::tail()
+{
+ return (direction==DECREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
+}
+
+ /*insert a new line between prev and this*/
+void directedLine::insert(directedLine* nl)
+{
+ nl->next = this;
+ nl->prev = prev;
+ prev->next = nl;
+ prev = nl;
+ nl->rootLink = this; /*assuming that 'this' is the root!!!*/
+}
+
+Int directedLine::numEdges()
+{
+ Int ret=0;
+ directedLine* temp;
+ if(next == this) return 1;
+
+ ret = 1;
+ for(temp = next; temp != this; temp = temp->next)
+ ret++;
+ return ret;
+}
+
+Int directedLine::numEdgesAllPolygons()
+{
+ Int ret=0;
+ directedLine* temp;
+ for(temp=this; temp!= NULL; temp=temp->nextPolygon)
+ {
+ ret += temp->numEdges();
+ }
+ return ret;
+}
+
+/*return 1 if the double linked list forms a polygon.
+ */
+short directedLine::isPolygon()
+{
+ directedLine* temp;
+
+ /*a polygon contains at least 3 edges*/
+ if(numEdges() <=2) return 0;
+
+ /*check this edge*/
+ if(! isConnected()) return 0;
+
+ /*check all other edges*/
+ for(temp=next; temp != this; temp = temp->next){
+ if(!isConnected()) return 0;
+ }
+ return 1;
+}
+
+/*check if the head of this edge is connected to
+ *the tail of the prev
+ */
+short directedLine::isConnected()
+{
+ if( (head()[0] == prev->tail()[0]) && (head()[1] == prev->tail()[1]))
+ return 1;
+ else
+ return 0;
+}
+
+Int compV2InY(Real A[2], Real B[2])
+{
+ if(A[1] < B[1]) return -1;
+ if(A[1] == B[1] && A[0] < B[0]) return -1;
+ if(A[1] == B[1] && A[0] == B[0]) return 0;
+ return 1;
+}
+
+Int compV2InX(Real A[2], Real B[2])
+{
+ if(A[0] < B[0]) return -1;
+ if(A[0] == B[0] && A[1] < B[1]) return -1;
+ if(A[0] == B[0] && A[1] == B[1]) return 0;
+ return 1;
+}
+
+/*compare two vertices NOT lines!
+ *A vertex is the head of a directed line.
+ *(x_1, y_1) <= (x_2, y_2) if
+ *either y_1 < y_2
+ *or y_1 == y_2 && x_1 < x_2.
+ *return -1 if this->head() <= nl->head(),
+ *return 1 otherwise
+ */
+Int directedLine::compInY(directedLine* nl)
+{
+ if(head()[1] < nl->head()[1]) return -1;
+ if(head()[1] == nl->head()[1] && head()[0] < nl->head()[0]) return -1;
+ return 1;
+}
+
+/*compare two vertices NOT lines!
+ *A vertex is the head of a directed line.
+ *(x_1, y_1) <= (x_2, y_2) if
+ *either x_1 < x_2
+ *or x_1 == x_2 && y_1 < y_2.
+ *return -1 if this->head() <= nl->head(),
+ *return 1 otherwise
+ */
+Int directedLine::compInX(directedLine* nl)
+{
+ if(head()[0] < nl->head()[0]) return -1;
+ if(head()[0] == nl->head()[0] && head()[1] < nl->head()[1]) return -1;
+ return 1;
+}
+
+/*used by sort precedures
+ */
+static Int compInY2(directedLine* v1, directedLine* v2)
+{
+ return v1->compInY(v2);
+}
+#ifdef NOT_USED
+static Int compInX(directedLine* v1, directedLine* v2)
+{
+ return v1->compInX(v2);
+}
+#endif
+
+/*sort all the vertices NOT the lines!
+ *a vertex is the head of a directed line
+ */
+directedLine** directedLine::sortAllPolygons()
+{
+ Int total_num_edges = 0;
+ directedLine** array = toArrayAllPolygons(total_num_edges);
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void *, void *)) compInY2);
+
+ return array;
+}
+
+void directedLine::printSingle()
+{
+ if(direction == INCREASING)
+ printf("direction is INCREASING\n");
+ else
+ printf("direction is DECREASING\n");
+ printf("head=%f,%f)\n", head()[0], head()[1]);
+ sline->print();
+}
+
+/*print one polygon*/
+void directedLine::printList()
+{
+ directedLine* temp;
+ printSingle();
+ for(temp = next; temp!=this; temp=temp->next)
+ temp->printSingle();
+}
+
+/*print all the polygons*/
+void directedLine::printAllPolygons()
+{
+ directedLine *temp;
+ for(temp = this; temp!=NULL; temp = temp->nextPolygon)
+ {
+ printf("polygon:\n");
+ temp->printList();
+ }
+}
+
+/*insert this polygon into the head of the old polygon List*/
+directedLine* directedLine::insertPolygon(directedLine* oldList)
+{
+ /*this polygon is a root*/
+ setRootBit();
+ if(oldList == NULL) return this;
+ nextPolygon = oldList;
+/* oldList->prevPolygon = this;*/
+ return this;
+}
+
+/*cutoff means delete. but we don't deallocate any space,
+ *so we use cutoff instead of delete
+ */
+directedLine* directedLine::cutoffPolygon(directedLine *p)
+{
+ directedLine* temp;
+ directedLine* prev_polygon = NULL;
+ if(p == NULL) return this;
+
+ for(temp=this; temp != p; temp = temp->nextPolygon)
+ {
+ if(temp == NULL)
+ {
+ fprintf(stderr, "in cutoffPolygon, not found\n");
+ exit(1);
+ }
+ prev_polygon = temp;
+ }
+
+/* prev_polygon = p->prevPolygon;*/
+
+ p->resetRootBit();
+ if(prev_polygon == NULL) /*this is the one to cutoff*/
+ return nextPolygon;
+ else {
+ prev_polygon->nextPolygon = p->nextPolygon;
+ return this;
+ }
+}
+
+Int directedLine::numPolygons()
+{
+ if(nextPolygon == NULL) return 1;
+ else return 1+nextPolygon->numPolygons();
+}
+
+
+/*let array[index ...] denote
+ *all the edges in this polygon
+ *return the next available index of array.
+ */
+Int directedLine::toArraySinglePolygon(directedLine** array, Int index)
+{
+ directedLine *temp;
+ array[index++] = this;
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ array[index++] = temp;
+ }
+ return index;
+}
+
+/*the space is allocated. The caller is responsible for
+ *deallocate the space.
+ *total_num_edges is set to be the total number of edges of all polygons
+ */
+directedLine** directedLine::toArrayAllPolygons(Int& total_num_edges)
+{
+ total_num_edges=numEdgesAllPolygons();
+ directedLine** ret = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges);
+ assert(ret);
+
+ directedLine *temp;
+ Int index = 0;
+ for(temp=this; temp != NULL; temp=temp->nextPolygon) {
+ index = temp->toArraySinglePolygon(ret, index);
+ }
+ return ret;
+}
+
+/*assume the polygon is a simple polygon, return
+ *the area enclosed by it.
+ *if thee order is counterclock wise, the area is positive.
+ */
+Real directedLine::polyArea()
+{
+ directedLine* temp;
+ Real ret=0.0;
+ Real x1,y1,x2,y2;
+ x1 = this->head()[0];
+ y1 = this->head()[1];
+ x2 = this->next->head()[0];
+ y2 = this->next->head()[1];
+ ret = -(x2*y1-x1*y2);
+ for(temp=this->next; temp!=this; temp = temp->next)
+ {
+ x1 = temp->head()[0];
+ y1 = temp->head()[1];
+ x2 = temp->next->head()[0];
+ y2 = temp->next->head()[1];
+ ret += -( x2*y1-x1*y2);
+ }
+ return Real(0.5)*ret;
+}
+
+/*******************split or combine polygons begin********************/
+/*conect a diagonal of a single simple polygon or two simple polygons.
+ *If the two vertices v1 (head) and v2 (head) are in the same simple polygon,
+ *then we actually split the simple polygon into two polygons.
+ *If instead two vertices velong to two difference polygons,
+ *then we combine the two polygons into one polygon.
+ *It is upto the caller to decide whether this is a split or a
+ *combination.
+ *
+ *Case Split:
+ *split a single simple polygon into two simple polygons by
+ *connecting a diagonal (two vertices).
+ *v1, v2: the two vertices are the head() of the two directedLines.
+ * this routine generates one new sampledLine which is returned in
+ *generatedLine,
+ *and it generates two directedLines returned in ret_p1 and ret_p2.
+ *ret_p1 and ret_p2 are used as the entry to the two new polygons.
+ *Notice the caller should not deallocate the space of v2 and v2 after
+ *calling this function, since all of the edges are connected to
+ *ret_p1 or ret_p2.
+ *
+ *combine:
+ *combine two simpolygons into one by connecting one diagonal.
+ *the returned polygon is returned in ret_p1.
+ */
+/*ARGSUSED*/
+void directedLine::connectDiagonal(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ sampledLine** generatedLine,
+ directedLine* polygonList )
+{
+ sampledLine *nsline = new sampledLine(2);
+
+
+
+ nsline->setPoint(0, v1->head());
+ nsline->setPoint(1, v2->head());
+
+
+
+ /*the increasing line is from v1 head to v2 head*/
+ directedLine* newLineInc = new directedLine(INCREASING, nsline);
+
+
+
+ directedLine* newLineDec = new directedLine(DECREASING, nsline);
+
+
+ directedLine* v1Prev = v1->prev;
+ directedLine* v2Prev = v2->prev;
+
+ v1 ->prev = newLineDec;
+ v2Prev ->next = newLineDec;
+ newLineDec->next = v1;
+ newLineDec->prev = v2Prev;
+
+ v2 ->prev = newLineInc;
+ v1Prev ->next = newLineInc;
+ newLineInc->next = v2;
+ newLineInc->prev = v1Prev;
+
+ *ret_p1 = newLineDec;
+ *ret_p2 = newLineInc;
+ *generatedLine = nsline;
+}
+
+//see the function connectDiangle
+/*ARGSUSED*/
+void directedLine::connectDiagonal_2slines(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ directedLine* polygonList )
+{
+ sampledLine *nsline = new sampledLine(2);
+ sampledLine *nsline2 = new sampledLine(2);
+
+ nsline->setPoint(0, v1->head());
+ nsline->setPoint(1, v2->head());
+ nsline2->setPoint(0, v1->head());
+ nsline2->setPoint(1, v2->head());
+
+ /*the increasing line is from v1 head to v2 head*/
+ directedLine* newLineInc = new directedLine(INCREASING, nsline);
+
+ directedLine* newLineDec = new directedLine(DECREASING, nsline2);
+
+ directedLine* v1Prev = v1->prev;
+ directedLine* v2Prev = v2->prev;
+
+ v1 ->prev = newLineDec;
+ v2Prev ->next = newLineDec;
+ newLineDec->next = v1;
+ newLineDec->prev = v2Prev;
+
+ v2 ->prev = newLineInc;
+ v1Prev ->next = newLineInc;
+ newLineInc->next = v2;
+ newLineInc->prev = v1Prev;
+
+ *ret_p1 = newLineDec;
+ *ret_p2 = newLineInc;
+
+}
+
+Int directedLine::samePolygon(directedLine* v1, directedLine* v2)
+{
+ if(v1 == v2) return 1;
+ directedLine *temp;
+ for(temp = v1->next; temp != v1; temp = temp->next)
+ {
+ if(temp == v2) return 1;
+ }
+ return 0;
+}
+
+directedLine* directedLine::findRoot()
+{
+ if(rootBit) return this;
+ directedLine* temp;
+ for(temp = next; temp != this; temp = temp->next)
+ if(temp -> rootBit ) return temp;
+ return NULL; /*should not happen*/
+}
+
+directedLine* directedLine::rootLinkFindRoot()
+{
+ directedLine* tempRoot;
+ directedLine* tempLink;
+ tempRoot = this;
+ tempLink = rootLink;
+ while(tempLink != NULL){
+ tempRoot = tempLink;
+ tempLink = tempRoot->rootLink;
+ }
+ return tempRoot;
+}
+
+/*******************split or combine polygons end********************/
+
+/*****************IO stuff begin*******************/
+
+/*format:
+ *#polygons
+ * #vertices
+ * vertices
+ * #vertices
+ * vertices
+ *...
+ */
+void directedLine::writeAllPolygons(char* filename)
+{
+ FILE* fp = fopen(filename, "w");
+ assert(fp);
+ Int nPolygons = numPolygons();
+ directedLine *root;
+ fprintf(fp, "%i\n", nPolygons);
+ for(root = this; root != NULL; root = root->nextPolygon)
+ {
+ directedLine *temp;
+ Int npoints=0;
+ npoints = root->get_npoints()-1;
+ for(temp = root->next; temp != root; temp=temp->next)
+ npoints += temp->get_npoints()-1;
+ fprintf(fp, "%i\n", npoints/*root->numEdges()*/);
+
+
+ for(Int i=0; i<root->get_npoints()-1; i++){
+ fprintf(fp, "%f ", root->getVertex(i)[0]);
+ fprintf(fp, "%f ", root->getVertex(i)[1]);
+ }
+
+ for(temp=root->next; temp != root; temp = temp->next)
+ {
+ for(Int i=0; i<temp->get_npoints()-1; i++){
+
+ fprintf(fp, "%f ", temp->getVertex(i)[0]);
+ fprintf(fp, "%f ", temp->getVertex(i)[1]);
+ }
+ fprintf(fp,"\n");
+ }
+ fprintf(fp, "\n");
+ }
+ fclose(fp);
+}
+
+directedLine* readAllPolygons(char* filename)
+{
+ Int i,j;
+ FILE* fp = fopen(filename, "r");
+ assert(fp);
+ Int nPolygons;
+ fscanf(fp, "%i", &nPolygons);
+ directedLine *ret = NULL;
+
+ for(i=0; i<nPolygons; i++)
+ {
+ Int nEdges;
+ fscanf(fp, "%i", &nEdges);
+ Real vert[2][2];
+ Real VV[2][2];
+ /*the first two vertices*/
+ fscanf(fp, "%f", &(vert[0][0]));
+ fscanf(fp, "%f", &(vert[0][1]));
+ fscanf(fp, "%f", &(vert[1][0]));
+ fscanf(fp, "%f", &(vert[1][1]));
+ VV[1][0] = vert[0][0];
+ VV[1][1] = vert[0][1];
+ sampledLine *sLine = new sampledLine(2, vert);
+ directedLine *thisPoly = new directedLine(INCREASING, sLine);
+thisPoly->rootLinkSet(NULL);
+
+ directedLine *dLine;
+ for(j=2; j<nEdges; j++)
+ {
+ vert[0][0]=vert[1][0];
+ vert[0][1]=vert[1][1];
+ fscanf(fp, "%f", &(vert[1][0]));
+ fscanf(fp, "%f", &(vert[1][1]));
+ sLine = new sampledLine(2,vert);
+ dLine = new directedLine(INCREASING, sLine);
+dLine->rootLinkSet(thisPoly);
+ thisPoly->insert(dLine);
+ }
+
+ VV[0][0]=vert[1][0];
+ VV[0][1]=vert[1][1];
+ sLine = new sampledLine(2,VV);
+ dLine = new directedLine(INCREASING, sLine);
+dLine->rootLinkSet(thisPoly);
+ thisPoly->insert(dLine);
+
+ ret = thisPoly->insertPolygon(ret);
+ }
+ fclose(fp);
+ return ret;
+}
+
+
+
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.h
new file mode 100644
index 000000000..4ed0128ca
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.h
@@ -0,0 +1,171 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _DIRECTEDLINE_H
+#define _DIRECTEDLINE_H
+
+#include "definitions.h"
+#include "sampledLine.h"
+
+enum {INCREASING, DECREASING};
+
+class directedLine {
+ short direction; /*INCREASING or DECREASING*/
+ sampledLine* sline;
+ directedLine* next; /*double linked list*/
+ directedLine* prev; /*double linked list*/
+
+ /*in case we need a list of polygons each
+ *consisting of a double linked list
+ */
+ directedLine* nextPolygon;
+
+ /*optimization make cutoff polygon faster*/
+/* directedLine* prevPolygon;*/
+
+ Int rootBit; /*1 if this is a root of the polygon, set by setRootBit*/
+ /*and reset by resetRootBit()*/
+
+ directedLine* rootLink; /*fast root-finding*/
+
+
+
+public:
+ directedLine(short dir, sampledLine* sl);
+ directedLine();
+ ~directedLine();
+
+ void init(short dir, sampledLine* sl);
+
+ Real* head(); /*points[0] if INCREASING, points[n-1] otherwise*/
+ Real* tail(); /*points[n-1] if INCREASING, points[0] otherwise*/
+ Real* getVertex(Int i); /*points[i] if INCREASING, points[n-1-i] otherwise*/
+ Int get_npoints() {return sline->get_npoints();}
+ directedLine* getPrev() {return prev;}
+ directedLine* getNext() {return next;}
+ directedLine* getNextPolygon() {return nextPolygon;}
+ sampledLine* getSampledLine() {return sline;}
+
+ short getDirection(){return direction;}
+ void putDirection(short dir) {direction = dir;}
+ void putPrev(directedLine *p) {prev = p;}
+ void putNext(directedLine *p) {next = p;}
+
+ /*insert a new line between prev and this*/
+ void insert(directedLine* nl);
+
+ /*delete all the polygons following the link: nextPolygon.
+ *notice that sampledLine is not deleted. The caller is
+ *responsible for that
+ */
+ void deletePolygonList();
+ void deleteSinglePolygon();
+
+ void deleteSinglePolygonWithSline(); //also delete sanmpled line
+ void deletePolygonListWithSline(); //also delete sanmpled line
+
+ void deleteSingleLine(directedLine* dline);
+ directedLine* deleteDegenerateLines();
+ directedLine* deleteDegenerateLinesAllPolygons();
+ directedLine* cutIntersectionAllPoly(int& cutOccur);
+
+ /*check to see if the list forms a closed polygon
+ *return 1 if yes
+ */
+ short isPolygon();
+
+ Int compInY(directedLine* nl);
+ Int compInX(directedLine* nl);
+
+ /*return an array of pointers.
+ *the
+ */
+ directedLine** sortAllPolygons();
+
+ Int numEdges();
+ Int numEdgesAllPolygons();
+ Int numPolygons();
+
+ /*check if the head of this edge is connected to
+ *the tail of the prev
+ */
+ short isConnected();
+
+ Real polyArea();
+
+ void printSingle();
+ void printList();
+ void printAllPolygons();
+ void writeAllPolygons(char* filename);
+
+
+ /*insert a polygon: using nextPolygon*/
+ directedLine* insertPolygon(directedLine* newpolygon);
+ directedLine* cutoffPolygon(directedLine *p);
+
+ Int toArraySinglePolygon(directedLine** array, Int index);
+ directedLine** toArrayAllPolygons(Int& total_num_edges);
+
+ void connectDiagonal(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ sampledLine** generatedLine, directedLine* list);
+
+ /*generate two slines
+ */
+ void connectDiagonal_2slines(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ directedLine* list);
+
+ Int samePolygon(directedLine* v1, directedLine* v2);
+ void setRootBit() {rootBit = 1;}
+ void resetRootBit() {rootBit = 0;}
+ directedLine* findRoot();
+
+ void rootLinkSet(directedLine* r) {rootLink = r;}
+ directedLine* rootLinkFindRoot();
+
+ //the chain from begin to end is deleted (the space is deallocated)
+ //and a new edge(which connectes the head of begin and the tail of end)
+ // is inserted. The new polygon is returned.
+ //notice that "this" is arbitrary
+ directedLine* deleteChain(directedLine* begin, directedLine* end);
+};
+
+directedLine* readAllPolygons(char* filename);
+
+extern Int compV2InY(Real A[2], Real B[2]);
+extern Int compV2InX(Real A[2], Real B[2]);
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/glimports.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/glimports.h
new file mode 100644
index 000000000..6e69feb40
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/glimports.h
@@ -0,0 +1,42 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * glimports.h
+ *
+ */
+
+#ifndef __gluimports_h_
+#define __gluimports_h_
+
+#include "mystdlib.h"
+#include "mystdio.h"
+
+#endif /* __gluimports_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc
new file mode 100644
index 000000000..3c92039ba
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc
@@ -0,0 +1,293 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/gl.h>
+#include "zlassert.h"
+#include "gridWrap.h"
+
+
+/*******************grid structure****************************/
+void gridWrap::print()
+{
+ printf("n_ulines = %i\n", n_ulines);
+ printf("n_vlines = %i\n", n_vlines);
+ printf("u_min=%f, umax=%f, vmin=%f, vmax=%f\n", u_min, u_max, v_min, v_max);
+}
+
+gridWrap::gridWrap(Int nUlines, Real* uvals,
+ Int nVlines, Real* vvals)
+{
+ assert(nUlines>=2);
+ assert(nVlines>=2);
+
+ is_uniform = 0;
+ n_ulines = nUlines;
+ n_vlines = nVlines;
+ u_min = uvals[0];
+ u_max = uvals[nUlines-1];
+ v_min = vvals[0];
+ v_max = vvals[nVlines-1];
+ u_values = (Real*) malloc(sizeof(Real) * n_ulines);
+ assert(u_values);
+ v_values = (Real*) malloc(sizeof(Real) * n_vlines);
+ assert(v_values);
+
+ Int i;
+ for(i=0; i<n_ulines; i++)
+ u_values[i] = uvals[i];
+ for(i=0; i<n_vlines; i++)
+ v_values[i] = vvals[i];
+}
+
+gridWrap::gridWrap(Int nUlines, Int nVlines,
+ Real uMin, Real uMax,
+ Real vMin, Real vMax
+ )
+{
+ is_uniform = 1;
+ n_ulines = nUlines;
+ n_vlines = nVlines;
+ u_min = uMin;
+ u_max = uMax;
+ v_min = vMin;
+ v_max = vMax;
+ u_values = (Real*) malloc(sizeof(Real) * n_ulines);
+ assert(u_values);
+ v_values = (Real*) malloc(sizeof(Real) * n_vlines);
+ assert(v_values);
+
+ Int i;
+ assert(nUlines>=2);
+ assert(nVlines>=2);
+ Real du = (uMax-uMin)/(nUlines-1);
+ Real dv = (vMax-vMin)/(nVlines-1);
+
+ float tempu=uMin;
+ u_values[0] = tempu;
+ for(i=1; i<nUlines; i++)
+ {
+ tempu += du;
+ u_values[i] = tempu;
+ }
+ u_values[nUlines-1] = uMax;
+
+ float tempv=vMin;
+ v_values[0] = tempv;
+ for(i=1; i<nVlines; i++)
+ {
+ tempv += dv;
+ v_values[i] = tempv;
+ }
+ v_values[nVlines-1] = vMax;
+}
+
+gridWrap::~gridWrap()
+{
+ free(u_values);
+ free(v_values);
+}
+
+void gridWrap::draw()
+{
+ int i,j;
+ glBegin(GL_POINTS);
+ for(i=0; i<n_ulines; i++)
+ for(j=0; j<n_vlines; j++)
+ glVertex2f(get_u_value(i), get_v_value(j));
+ glEnd();
+}
+
+void gridWrap::outputFanWithPoint(Int v, Int uleft, Int uright, Real vert[2], primStream* pStream)
+{
+ Int i;
+ if(uleft >= uright)
+ return; //no triangles to output.
+
+ pStream->begin();
+ pStream->insert(vert);
+
+ assert(vert[1] != v_values[v]); //don't output degenerate triangles
+
+ if(vert[1] > v_values[v]) //vertex is above this grid line: notice the orientation
+ {
+ for(i=uleft; i<=uright; i++)
+ pStream->insert(u_values[i], v_values[v]);
+ }
+ else //vertex is below the grid line
+ {
+ for(i=uright; i>= uleft; i--)
+ pStream->insert(u_values[i], v_values[v]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+}
+
+
+
+/*each chain stores a number of consecutive
+ *V-lines within a grid.
+ *There is one grid vertex on each V-line.
+ * The total number of V-lines is:
+ * nVlines.
+ * with respect to the grid, the index of the first V-line is
+ * firstVlineIndex.
+ * So with respect to the grid, the index of the ith V-line is
+ * firstVlineIndex-i.
+ * the grid-index of the uline at the ith vline (recall that each vline has one grid point)
+ * is ulineIndices[i]. The u_value is cached in ulineValues[i], that is,
+ * ulineValues[i] = grid->get_u_value(ulineIndices[i])
+ */
+gridBoundaryChain::gridBoundaryChain(
+ gridWrap* gr,
+ Int first_vline_index,
+ Int n_vlines,
+ Int* uline_indices,
+ Int* inner_indices
+ )
+: grid(gr), firstVlineIndex(first_vline_index), nVlines(n_vlines)
+{
+ ulineIndices = (Int*) malloc(sizeof(Int) * n_vlines);
+ assert(ulineIndices);
+
+ innerIndices = (Int*) malloc(sizeof(Int) * n_vlines);
+ assert(innerIndices);
+
+ vertices = (Real2*) malloc(sizeof(Real2) * n_vlines);
+ assert(vertices);
+
+
+
+ Int i;
+ for(i=0; i<n_vlines; i++){
+ ulineIndices[i] = uline_indices[i];
+ innerIndices[i] = inner_indices[i];
+ }
+
+ for(i=0; i<n_vlines; i++){
+ vertices[i][0] = gr->get_u_value(ulineIndices[i]);
+ vertices[i][1] = gr->get_v_value(first_vline_index-i);
+ }
+}
+
+void gridBoundaryChain::draw()
+{
+ Int i;
+ glBegin(GL_LINE_STRIP);
+ for(i=0; i<nVlines; i++)
+ {
+ glVertex2fv(vertices[i]);
+ }
+ glEnd();
+}
+
+void gridBoundaryChain::drawInner()
+{
+ Int i;
+ for(i=1; i<nVlines; i++)
+ {
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(grid->get_u_value(innerIndices[i]), get_v_value(i-1) );
+ glVertex2f(grid->get_u_value(innerIndices[i]), get_v_value(i) );
+ glEnd();
+ }
+}
+
+Int gridBoundaryChain::lookfor(Real v, Int i1, Int i2)
+{
+ Int mid;
+ while(i1 < i2-1)
+ {
+ mid = (i1+i2)/2;
+ if(v > vertices[mid][1])
+ {
+ i2 = mid;
+ }
+ else
+ i1 = mid;
+ }
+ return i1;
+}
+
+/*output the fan of the right end between grid line i-1 and grid line i*/
+void gridBoundaryChain::rightEndFan(Int i, primStream* pStream)
+{
+ Int j;
+ if(getUlineIndex(i) > getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i-1));
+ for(j=getUlineIndex(i-1); j<= getUlineIndex(i); j++)
+ pStream->insert(grid->get_u_value(j), get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(getUlineIndex(i) < getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i));
+ for(j=getUlineIndex(i-1); j>= getUlineIndex(i); j--)
+ pStream->insert(grid->get_u_value(j), get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ //otherside, the two are equal, so there is no fan to output
+}
+
+
+/*output the fan of the left end between grid line i-1 and grid line i*/
+void gridBoundaryChain::leftEndFan(Int i, primStream* pStream)
+{
+ Int j;
+ if(getUlineIndex(i) < getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i-1));
+ for(j=getUlineIndex(i); j<= getUlineIndex(i-1); j++)
+ pStream->insert(grid->get_u_value(j), get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(getUlineIndex(i) > getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i));
+ for(j=getUlineIndex(i); j>= getUlineIndex(i-1); j--)
+ pStream->insert(grid->get_u_value(j), get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.h
new file mode 100644
index 000000000..b6428484f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.h
@@ -0,0 +1,137 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _GRIDWRAP_H
+#define _GRIDWRAP_H
+
+#include <stdio.h>
+#include "definitions.h"
+
+#include "primitiveStream.h"
+#include "zlassert.h"
+
+class gridWrap{
+ Int n_ulines;
+ Int n_vlines;
+ Real u_min, u_max;
+ Real v_min, v_max;
+
+ /*cache the coordinate values for efficiency.
+ *these are redundant information when
+ *the grid is uniform.
+ */
+ Real* u_values; /*size is n_ulines*/
+ Real* v_values; /*size is n_vlines*/
+
+ Int is_uniform;
+
+public:
+ //uniform grid constructor
+ gridWrap(Int nUlines, Int nVlines,
+ Real uMin, Real uMax,
+ Real vMin, Real vMax
+ );
+
+ //nonuniform grid constructor.
+ gridWrap(Int nUlines, Real *uvals,
+ Int nVlines, Real *vvlas
+ );
+ ~gridWrap();
+
+ void print();
+ Int get_n_ulines() {return n_ulines;}
+ Int get_n_vlines() {return n_vlines;}
+ Real get_u_min() {return u_min;}
+ Real get_u_max() {return u_max;}
+ Real get_v_min() {return v_min;}
+ Real get_v_max() {return v_max;}
+
+ Real get_u_value(Int i)
+ {
+ assert(i<n_ulines);
+ /*if(i>=n_ulines){printf("ERROR, n_ulines=%i,i=%i\n",n_ulines,i);exit(0);}*/
+ return u_values[i];}
+ Real get_v_value(Int j) {return v_values[j];}
+
+ Real* get_u_values() {return u_values;}
+ Real* get_v_values() {return v_values;}
+
+ void outputFanWithPoint(Int v, Int uleft, Int uright,
+ Real vert[2], primStream* pStream);
+
+ void draw();
+
+ Int isUniform() {return is_uniform;}
+};
+
+class gridBoundaryChain{
+ gridWrap* grid;
+ Int firstVlineIndex;
+ Int nVlines;
+ Int* ulineIndices; /*each v line has a boundary*/
+ Int* innerIndices; /*the segment of the vertical gridline from */
+ /*(innerIndices[i], i) to (innerIndices[i+1], i-1) */
+ /*is inside the polygon: i=1,...,nVlines-1*/
+
+ Real2* vertices; /*one grid point at each grid V-line, cached for efficiency*/
+
+public:
+ gridBoundaryChain(gridWrap* gr, Int first_vline_index, Int n_vlines, Int* uline_indices, Int* inner_indices);
+
+ ~gridBoundaryChain()
+ {
+ free(innerIndices);
+ free(ulineIndices);
+ free(vertices);
+ }
+
+ /*i indexes the vlines in this chain.
+ */
+ Int getVlineIndex(Int i) {return firstVlineIndex-i;}
+ Int getUlineIndex(Int i) {return ulineIndices[i];}
+ Real get_u_value(Int i) {return vertices[i][0];}
+ Real get_v_value(Int i) {return vertices[i][1];}
+ Int get_nVlines() {return nVlines;}
+ Int getInnerIndex(Int i) {return innerIndices[i];}
+ Real getInner_u_value(Int i) {return grid->get_u_value(innerIndices[i]);}
+
+ Real* get_vertex(Int i) {return vertices[i];}
+ gridWrap* getGrid() {return grid;}
+ void leftEndFan(Int i, primStream* pStream);
+ void rightEndFan(Int i, primStream* pStream);
+
+ Int lookfor(Real v, Int i1, Int i2); //find i in [i1,i2] so that vertices[i][1]>= v > vertices[i+1][1]
+ void draw();
+ void drawInner();
+};
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.cc
new file mode 100644
index 000000000..814bf32fa
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.cc
@@ -0,0 +1,934 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/gl.h>
+
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "monoChain.h"
+#include "quicksort.h"
+#include "searchTree.h"
+#include "polyUtil.h"
+
+#ifndef max
+#define max(a,b) ((a>b)? a:b)
+#endif
+#ifndef min
+#define min(a,b) ((a>b)? b:a)
+#endif
+
+extern Int isCusp(directedLine *v);
+extern Int deleteRepeatDiagonals(Int num_diagonals, directedLine** diagonal_vertices, directedLine** new_vertices);
+
+//for debug purpose only
+#if 0 // UNUSED
+static void drawDiagonals(Int num_diagonals, directedLine** diagonal_vertices)
+{
+ Int i;
+ for(i=0; i<num_diagonals; i++)
+ {
+ glBegin(GL_LINE);
+ glVertex2fv(diagonal_vertices[2*i]->head());
+ glVertex2fv(diagonal_vertices[2*i+1]->head());
+ glEnd();
+ }
+}
+#endif
+
+/*given (x_1, y_1) and (x_2, y_2), and y
+ *return x such that (x,y) is on the line
+ */
+inline Real intersectHoriz(Real x1, Real y1, Real x2, Real y2, Real y)
+{
+ return ((y2==y1)? (x1+x2)*0.5 : x1 + ((y-y1)/(y2-y1)) * (x2-x1));
+}
+
+//compare the heads of the two chains
+static int compChainHeadInY(monoChain* mc1, monoChain* mc2)
+{
+ return compV2InY(mc1->getHead()->head(), mc2->getHead()->head());
+}
+
+monoChain::monoChain(directedLine* cHead, directedLine* cTail)
+{
+ chainHead = cHead;
+ chainTail = cTail;
+ next = this;
+ prev = this;
+
+ nextPolygon = NULL;
+
+ //compute bounding box
+ directedLine* temp;
+ minX = maxX = chainTail->head()[0];
+ minY = maxY = chainTail->head()[1];
+
+ for(temp=chainHead; temp!=cTail; temp = temp->getNext())
+ {
+ if(temp->head()[0] < minX)
+ minX = temp->head()[0];
+ if(temp->head()[0] > maxX)
+ maxX = temp->head()[0];
+
+ if(temp->head()[1] < minY)
+ minY = temp->head()[1];
+ if(temp->head()[1] > maxY)
+ maxY = temp->head()[1];
+ }
+
+ //check whether the chain is increasing or decreasing
+ if(chainHead->compInY(chainTail) <0)
+ isIncrease = 1;
+ else
+ isIncrease = 0;
+
+ //initilize currrent, this is used for accelerating search
+ if(isIncrease)
+ current = chainHead;
+ else
+ current = chainTail;
+
+ isKey = 0;
+}
+
+//insert a new line between prev and this
+void monoChain::insert(monoChain* nc)
+{
+ nc->next = this;
+ nc->prev = prev;
+ prev->next = nc;
+ prev = nc;
+}
+
+void monoChain::deleteLoop()
+{
+ monoChain *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+void monoChain::deleteLoopList()
+{
+ monoChain *temp, *tempNext;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteLoop();
+ }
+}
+
+Int monoChain::toArraySingleLoop(monoChain** array, Int index)
+{
+ monoChain *temp;
+ array[index++] = this;
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ array[index++] = temp;
+ }
+ return index;
+}
+
+monoChain** monoChain::toArrayAllLoops(Int& num_chains)
+{
+ num_chains = numChainsAllLoops();
+ monoChain **ret = (monoChain**) malloc(sizeof(monoChain*) * num_chains);
+ assert(ret);
+ monoChain *temp;
+ Int index = 0;
+ for(temp = this; temp != NULL; temp=temp->nextPolygon){
+ index = temp->toArraySingleLoop(ret, index);
+ }
+ return ret;
+}
+
+Int monoChain::numChainsSingleLoop()
+{
+ Int ret=0;
+ monoChain* temp;
+ if(next == this) return 1;
+ ret = 1;
+ for(temp=next; temp != this; temp = temp->next)
+ ret++;
+ return ret;
+}
+
+Int monoChain::numChainsAllLoops()
+{
+ Int ret=0;
+ monoChain *temp;
+ for(temp =this; temp != NULL; temp = temp->nextPolygon)
+ ret += temp->numChainsSingleLoop();
+ return ret;
+}
+
+//update 'current'
+Real monoChain::chainIntersectHoriz(Real y)
+{
+ directedLine* temp;
+ if(isIncrease)
+ {
+ for(temp= current; temp != chainTail; temp = temp->getNext())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getPrev();
+ }
+ else
+ {
+ for(temp = current; temp != chainHead; temp = temp->getPrev())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getNext();
+ }
+ return intersectHoriz(current->head()[0], current->head()[1], current->tail()[0], current->tail()[1], y);
+}
+
+monoChain* directedLineLoopToMonoChainLoop(directedLine* loop)
+{
+ directedLine *temp;
+ monoChain *ret=NULL;
+
+ //find the first cusp
+ directedLine *prevCusp=NULL;
+ directedLine *firstCusp;
+
+ if(isCusp(loop))
+ prevCusp = loop;
+ else
+ {
+ for(temp = loop->getNext(); temp != loop; temp = temp->getNext())
+ if(isCusp(temp))
+ break;
+ prevCusp = temp;
+ }
+ firstCusp = prevCusp;
+//printf("first cusp is (%f,%f), (%f,%f), (%f,%f)\n", prevCusp->getPrev()->head()[0], prevCusp->getPrev()->head()[1], prevCusp->head()[0], prevCusp->head()[1], prevCusp->tail()[0], prevCusp->tail()[1]);
+
+ for(temp = prevCusp->getNext(); temp != loop; temp = temp->getNext())
+ {
+ if(isCusp(temp))
+ {
+//printf("the cusp is (%f,%f), (%f,%f), (%f,%f)\n", temp->getPrev()->head()[0], temp->getPrev()->head()[1], temp->head()[0], temp->head()[1], temp->tail()[0], temp->tail()[1]);
+ if(ret == NULL)
+ {
+ ret = new monoChain(prevCusp, temp);
+ }
+ else
+ ret->insert(new monoChain(prevCusp, temp));
+ prevCusp = temp;
+ }
+ }
+ ret->insert(new monoChain(prevCusp, firstCusp));
+
+ return ret;
+}
+
+monoChain* directedLineLoopListToMonoChainLoopList(directedLine* list)
+{
+ directedLine* temp;
+ monoChain* mc;
+ monoChain* mcEnd;
+ mc = directedLineLoopToMonoChainLoop(list);
+ mcEnd = mc;
+ for(temp = list->getNextPolygon(); temp != NULL; temp = temp->getNextPolygon())
+ {
+ monoChain *newLoop = directedLineLoopToMonoChainLoop(temp);
+ mcEnd->setNextPolygon(newLoop);
+ mcEnd = newLoop;
+ }
+ return mc;
+}
+
+/*compare two edges of a polygon.
+ *edge A < edge B if there is a horizontal line so that the intersection
+ *with A is to the left of the intersection with B.
+ *This function is used in sweepY for the dynamic search tree insertion to
+ *order the edges.
+ * Implementation: (x_1,y_1) and (x_2, y_2)
+ */
+static Int compEdges(directedLine *e1, directedLine *e2)
+{
+ Real* head1 = e1->head();
+ Real* tail1 = e1->tail();
+ Real* head2 = e2->head();
+ Real* tail2 = e2->tail();
+/*
+ Real h10 = head1[0];
+ Real h11 = head1[1];
+ Real t10 = tail1[0];
+ Real t11 = tail1[1];
+ Real h20 = head2[0];
+ Real h21 = head2[1];
+ Real t20 = tail2[0];
+ Real t21 = tail2[1];
+*/
+ Real e1_Ymax, e1_Ymin, e2_Ymax, e2_Ymin;
+/*
+ if(h11>t11) {
+ e1_Ymax= h11;
+ e1_Ymin= t11;
+ }
+ else{
+ e1_Ymax = t11;
+ e1_Ymin = h11;
+ }
+
+ if(h21>t21) {
+ e2_Ymax= h21;
+ e2_Ymin= t21;
+ }
+ else{
+ e2_Ymax = t21;
+ e2_Ymin = h21;
+ }
+*/
+
+ if(head1[1]>tail1[1]) {
+ e1_Ymax= head1[1];
+ e1_Ymin= tail1[1];
+ }
+ else{
+ e1_Ymax = tail1[1];
+ e1_Ymin = head1[1];
+ }
+
+ if(head2[1]>tail2[1]) {
+ e2_Ymax= head2[1];
+ e2_Ymin= tail2[1];
+ }
+ else{
+ e2_Ymax = tail2[1];
+ e2_Ymin = head2[1];
+ }
+
+
+ /*Real e1_Ymax = max(head1[1], tail1[1]);*/ /*max(e1->head()[1], e1->tail()[1]);*/
+ /*Real e1_Ymin = min(head1[1], tail1[1]);*/ /*min(e1->head()[1], e1->tail()[1]);*/
+ /*Real e2_Ymax = max(head2[1], tail2[1]);*/ /*max(e2->head()[1], e2->tail()[1]);*/
+ /*Real e2_Ymin = min(head2[1], tail2[1]);*/ /*min(e2->head()[1], e2->tail()[1]);*/
+
+ Real Ymax = min(e1_Ymax, e2_Ymax);
+ Real Ymin = max(e1_Ymin, e2_Ymin);
+
+ Real y = 0.5*(Ymax + Ymin);
+
+/* Real x1 = intersectHoriz(e1->head()[0], e1->head()[1], e1->tail()[0], e1->tail()[1], y);
+ Real x2 = intersectHoriz(e2->head()[0], e2->head()[1], e2->tail()[0], e2->tail()[1], y);
+*/
+/*
+ Real x1 = intersectHoriz(h10, h11, t10, t11, y);
+ Real x2 = intersectHoriz(h20, h21, t20, t21, y);
+*/
+ Real x1 = intersectHoriz(head1[0], head1[1], tail1[0], tail1[1], y);
+ Real x2 = intersectHoriz(head2[0], head2[1], tail2[0], tail2[1], y);
+
+ if(x1<= x2) return -1;
+ else return 1;
+}
+
+Int compChains(monoChain* mc1, monoChain* mc2)
+{
+ Real y;
+ assert(mc1->isKey || mc2->isKey);
+ if(mc1->isKey)
+ y = mc1->keyY;
+ else
+ y = mc2->keyY;
+ directedLine *d1 = mc1->find(y);
+ directedLine *d2 = mc2->find(y);
+ mc2->find(y);
+// Real x1 = mc1->chainIntersectHoriz(y);
+// Real x2 = mc2->chainIntersectHoriz(y);
+ return compEdges(d1, d2);
+}
+
+//this function modifies current for efficiency
+directedLine* monoChain::find(Real y)
+{
+ directedLine *ret;
+ directedLine *temp;
+ assert(current->head()[1] <= y);
+ if(isIncrease)
+ {
+ assert(chainTail->head()[1] >=y);
+ for(temp=current; temp!=chainTail; temp = temp->getNext())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getPrev();
+ ret = current;
+ }
+ else
+ {
+ for(temp=current; temp != chainHead; temp = temp->getPrev())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getNext();
+ ret = temp;
+ }
+ return ret;
+}
+
+void monoChain::printOneChain()
+{
+ directedLine* temp;
+ for(temp = chainHead; temp != chainTail; temp = temp->getNext())
+ {
+ printf("(%f,%f) ", temp->head()[0], temp->head()[1]);
+ }
+ printf("(%f,%f) \n", chainTail->head()[0], chainTail->head()[1]);
+}
+
+void monoChain::printChainLoop()
+{
+ monoChain* temp;
+ this->printOneChain();
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ temp->printOneChain();
+ }
+ printf("\n");
+}
+
+void monoChain::printAllLoops()
+{
+ monoChain* temp;
+ for(temp=this; temp != NULL; temp = temp->nextPolygon)
+ temp->printChainLoop();
+}
+
+//return 1 if error occures
+Int MC_sweepY(Int nVertices, monoChain** sortedVertices, sweepRange** ret_ranges)
+{
+ Int i;
+ Real keyY;
+ Int errOccur=0;
+//printf("enter MC_sweepY\n");
+//printf("nVertices=%i\n", nVertices);
+ /*for each vertex in the sorted list, update the binary search tree.
+ *and store the range information for each vertex.
+ */
+ treeNode* searchTree = NULL;
+//printf("nVertices=%i\n", nVertices);
+ for(i=0; i<nVertices; i++)
+ {
+ monoChain* vert = sortedVertices[i];
+ keyY = vert->getHead()->head()[1]; //the sweep line
+ directedLine *dline = vert->getHead();
+ directedLine *dlinePrev = dline->getPrev();
+ if(isBelow(dline, dline) && isBelow(dline, dlinePrev))
+ {
+//printf("case 1\n");
+ //this<v and prev < v
+ //delete both edges
+ vert->isKey = 1;
+ vert->keyY = keyY;
+ treeNode* thisNode = TreeNodeFind(searchTree, vert, (Int (*) (void *, void *))compChains);
+ vert->isKey = 0;
+
+ vert->getPrev()->isKey = 1;
+ vert->getPrev()->keyY = keyY;
+ treeNode* prevNode = TreeNodeFind(searchTree, vert->getPrev(), (Int (*) (void *, void *))compChains);
+ vert->getPrev()->isKey = 0;
+
+ if(cuspType(dline) == 1)//interior cusp
+ {
+
+ treeNode* leftEdge = TreeNodePredecessor(prevNode);
+ treeNode* rightEdge = TreeNodeSuccessor(thisNode);
+ if(leftEdge == NULL || rightEdge == NULL)
+ {
+ errOccur = 1;
+ goto JUMP_HERE;
+ }
+
+ directedLine* leftEdgeDline = ((monoChain* ) leftEdge->key)->find(keyY);
+
+
+
+ directedLine* rightEdgeDline = ((monoChain* ) rightEdge->key)->find(keyY);
+
+ ret_ranges[i] = sweepRangeMake(leftEdgeDline, 1, rightEdgeDline, 1);
+ }
+ else /*exterior cusp*/
+ {
+ ret_ranges[i] = sweepRangeMake( dline, 1, dlinePrev, 1);
+ }
+
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+
+ }
+ else if(isAbove(dline, dline) && isAbove(dline, dlinePrev))
+ {
+//printf("case 2\n");
+ //insert both edges
+ treeNode* thisNode = TreeNodeMake(vert);
+ treeNode* prevNode = TreeNodeMake(vert->getPrev());
+
+ vert->isKey = 1;
+ vert->keyY = keyY;
+ searchTree = TreeNodeInsert(searchTree, thisNode, (Int (*) (void *, void *))compChains);
+ vert->isKey = 0;
+
+ vert->getPrev()->isKey = 1;
+ vert->getPrev()->keyY = keyY;
+ searchTree = TreeNodeInsert(searchTree, prevNode, (Int (*) (void *, void *))compChains);
+ vert->getPrev()->isKey = 0;
+
+ if(cuspType(dline) == 1) //interior cusp
+ {
+//printf("cuspType is 1\n");
+ treeNode* leftEdge = TreeNodePredecessor(thisNode);
+ treeNode* rightEdge = TreeNodeSuccessor(prevNode);
+ if(leftEdge == NULL || rightEdge == NULL)
+ {
+ errOccur = 1;
+ goto JUMP_HERE;
+ }
+//printf("leftEdge is %i, rightEdge is %i\n", leftEdge, rightEdge);
+ directedLine* leftEdgeDline = ((monoChain*) leftEdge->key)->find(keyY);
+ directedLine* rightEdgeDline = ((monoChain*) rightEdge->key)->find(keyY);
+ ret_ranges[i] = sweepRangeMake( leftEdgeDline, 1, rightEdgeDline, 1);
+ }
+ else //exterior cusp
+ {
+//printf("cuspType is not 1\n");
+ ret_ranges[i] = sweepRangeMake(dlinePrev, 1, dline, 1);
+ }
+ }
+ else
+ {
+//printf("%i,%i\n", isAbove(dline, dline), isAbove(dline, dlinePrev));
+ errOccur = 1;
+ goto JUMP_HERE;
+
+ fprintf(stderr, "error in MC_sweepY\n");
+ exit(1);
+ }
+ }
+
+ JUMP_HERE:
+ //finally clean up space: delete the search tree
+ TreeNodeDeleteWholeTree(searchTree);
+ return errOccur;
+}
+
+void MC_findDiagonals(Int total_num_edges, monoChain** sortedVertices,
+ sweepRange** ranges, Int& num_diagonals,
+ directedLine** diagonal_vertices)
+{
+ Int i,j,k;
+ k=0;
+ //reset 'current' of all the monoChains
+ for(i=0; i<total_num_edges; i++)
+ sortedVertices[i]->resetCurrent();
+
+ for(i=0; i<total_num_edges; i++)
+ {
+ directedLine* vert = sortedVertices[i]->getHead();
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+ if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge) && compEdges(prevEdge, thisEdge)<0)
+ {
+ //this is an upward interior cusp
+ diagonal_vertices[k++] = vert;
+
+ directedLine* leftEdge = ranges[i]->left;
+ directedLine* rightEdge = ranges[i]->right;
+
+ directedLine* leftVert = leftEdge;
+ directedLine* rightVert = rightEdge->getNext();
+ assert(leftVert->head()[1] >= vert->head()[1]);
+ assert(rightVert->head()[1] >= vert->head()[1]);
+ directedLine* minVert = (leftVert->head()[1] <= rightVert->head()[1])?leftVert:rightVert;
+ Int found = 0;
+ for(j=i+1; j<total_num_edges; j++)
+ {
+ if(sortedVertices[j]->getHead()->head()[1] > minVert->head()[1])
+ break;
+
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if(found)
+ diagonal_vertices[k++] = sortedVertices[j]->getHead();
+ else
+ diagonal_vertices[k++] = minVert;
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge) && compEdges(prevEdge, thisEdge)>0)
+ {
+ //downward interior cusp
+ diagonal_vertices[k++] = vert;
+ directedLine* leftEdge = ranges[i]->left;
+ directedLine* rightEdge = ranges[i]->right;
+ directedLine* leftVert = leftEdge->getNext();
+ directedLine* rightVert = rightEdge;
+ assert(leftVert->head()[1] <= vert->head()[1]);
+ assert(rightVert->head()[1] <= vert->head()[1]);
+ directedLine* maxVert = (leftVert->head()[1] > rightVert->head()[1])? leftVert:rightVert;
+ Int found=0;
+ for(j=i-1; j>=0; j--)
+ {
+ if(sortedVertices[j]->getHead()->head()[1] < maxVert->head()[1])
+ break;
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ found = 1;
+ break;
+ }
+ }
+ if(found)
+ diagonal_vertices[k++] = sortedVertices[j]->getHead();
+ else
+ diagonal_vertices[k++] = maxVert;
+ }
+ }
+ num_diagonals = k/2;
+}
+
+
+
+
+directedLine* MC_partitionY(directedLine *polygons, sampledLine **retSampledLines)
+{
+//printf("enter mc_partitionY\n");
+ Int total_num_chains = 0;
+ monoChain* loopList = directedLineLoopListToMonoChainLoopList(polygons);
+ monoChain** array = loopList->toArrayAllLoops(total_num_chains);
+
+ if(total_num_chains<=2) //there is just one single monotone polygon
+ {
+ loopList->deleteLoopList();
+ free(array);
+ *retSampledLines = NULL;
+ return polygons;
+ }
+
+//loopList->printAllLoops();
+//printf("total_num_chains=%i\n", total_num_chains);
+ quicksort( (void**)array, 0, total_num_chains-1, (Int (*)(void*, void*))compChainHeadInY);
+//printf("after quicksort\n");
+
+ sweepRange** ranges = (sweepRange**)malloc(sizeof(sweepRange*) * (total_num_chains));
+ assert(ranges);
+
+ if(MC_sweepY(total_num_chains, array, ranges))
+ {
+ loopList->deleteLoopList();
+ free(array);
+ *retSampledLines = NULL;
+ return NULL;
+ }
+//printf("after MC_sweepY\n");
+
+
+ Int num_diagonals;
+ /*number diagonals is < total_num_edges*total_num_edges*/
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_chains*2/*total_num_edges*/);
+ assert(diagonal_vertices);
+
+//printf("before call MC_findDiagonales\n");
+
+ MC_findDiagonals(total_num_chains, array, ranges, num_diagonals, diagonal_vertices);
+//printf("after call MC_findDia, num_diagnla=%i\n", num_diagonals);
+
+ directedLine* ret_polygons = polygons;
+ sampledLine* newSampledLines = NULL;
+ Int i,k;
+
+ num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+
+
+
+//drawDiagonals(num_diagonals, diagonal_vertices);
+//printf("diagoanls are \n");
+//for(i=0; i<num_diagonals; i++)
+// {
+// printf("(%f,%f)\n", diagonal_vertices[2*i]->head()[0], diagonal_vertices[2*i]->head()[1]);
+// printf("**(%f,%f)\n", diagonal_vertices[2*i+1]->head()[0], diagonal_vertices[2*i+1]->head()[1]);
+// }
+
+ Int *removedDiagonals=(Int*)malloc(sizeof(Int) * num_diagonals);
+ for(i=0; i<num_diagonals; i++)
+ removedDiagonals[i] = 0;
+// printf("first pass\n");
+
+
+ for(i=0,k=0; i<num_diagonals; i++,k+=2)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+/*
+ directedLine *root1 = v1->findRoot();
+ directedLine *root2 = v2->findRoot();
+ assert(root1);
+ assert(root2);
+*/
+
+directedLine* root1 = v1->rootLinkFindRoot();
+directedLine* root2 = v2->rootLinkFindRoot();
+
+ if(root1 != root2)
+ {
+
+ removedDiagonals[i] = 1;
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+
+
+
+ newSampledLines = generatedLine->insert(newSampledLines);
+/*
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+root1->rootLinkSet(ret_p1);
+root2->rootLinkSet(ret_p1);
+ret_p1->rootLinkSet(NULL);
+ret_p2->rootLinkSet(ret_p1);
+*/
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+
+
+
+root2->rootLinkSet(root1);
+ret_p1->rootLinkSet(root1);
+ret_p2->rootLinkSet(root1);
+
+ /*now that we have connected the diagonal v1 and v2,
+ *we have to check those unprocessed diagonals which
+ *have v1 or v2 as an end point. Notice that the head of v1
+ *has the same coodinates as the head of v2->prev, and the head of
+ *v2 has the same coordinate as the head of v1->prev.
+ *Suppose these is a diagonal (v1, x). If (v1,x) is still a valid
+ *diagonal, then x should be on the left hand side of the directed line: *v1->prev->head -- v1->head -- v1->tail. Otherwise, (v1,x) should be
+ *replaced by (v2->prev, x), that is, x is on the left of
+ * v2->prev->prev->head, v2->prev->head, v2->prev->tail.
+ */
+ Int ii, kk;
+ for(ii=0, kk=0; ii<num_diagonals; ii++, kk+=2)
+ if( removedDiagonals[ii]==0)
+ {
+ directedLine* d1=diagonal_vertices[kk];
+ directedLine* d2=diagonal_vertices[kk+1];
+ /*check d1, and replace diagonal_vertices[kk] if necessary*/
+ if(d1 == v1) {
+ /*check if d2 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v2->getPrev();
+ }
+ }
+ if(d1 == v2) {
+ /*check if d2 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v1->getPrev();
+ }
+ }
+ /*check d2 and replace diagonal_vertices[k+1] if necessary*/
+ if(d2 == v1) {
+ /*check if d1 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v2->getPrev();
+ }
+ }
+ if(d2 == v2) {
+ /*check if d1 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v1->getPrev();
+ }
+ }
+ }
+}/*end if (root1 not equal to root 2)*/
+}
+
+ /*second pass, now all diagoals should belong to the same polygon*/
+//printf("second pass: \n");
+
+// for(i=0; i<num_diagonals; i++)
+// printf("%i ", removedDiagonals[i]);
+
+
+ for(i=0,k=0; i<num_diagonals; i++, k += 2)
+ if(removedDiagonals[i] == 0)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+
+
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+ directedLine *root1 = v1->findRoot();
+/*
+ directedLine *root2 = v2->findRoot();
+
+
+
+ assert(root1);
+ assert(root2);
+ assert(root1 == root2);
+ */
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+ newSampledLines = generatedLine->insert(newSampledLines);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+
+ ret_polygons = ret_p2->insertPolygon(ret_polygons);
+
+
+
+ for(Int j=i+1; j<num_diagonals; j++)
+ {
+ if(removedDiagonals[j] ==0)
+ {
+
+ directedLine* temp1=diagonal_vertices[2*j];
+ directedLine* temp2=diagonal_vertices[2*j+1];
+ if(temp1==v1 || temp1==v2 || temp2==v1 || temp2==v2)
+ if(! temp1->samePolygon(temp1, temp2))
+ {
+ /*if temp1 and temp2 are in different polygons,
+ *then one of them must be v1 or v2.
+ */
+
+
+
+ assert(temp1==v1 || temp1 == v2 || temp2==v1 || temp2 ==v2);
+ if(temp1==v1)
+ {
+ diagonal_vertices[2*j] = v2->getPrev();
+ }
+ if(temp2==v1)
+ {
+ diagonal_vertices[2*j+1] = v2->getPrev();
+ }
+ if(temp1==v2)
+ {
+ diagonal_vertices[2*j] = v1->getPrev();
+ }
+ if(temp2==v2)
+ {
+ diagonal_vertices[2*j+1] = v1->getPrev();
+ }
+ }
+ }
+ }
+
+ }
+
+
+ //clean up
+ loopList->deleteLoopList();
+ free(array);
+ free(ranges);
+ free(diagonal_vertices);
+ free(removedDiagonals);
+
+ *retSampledLines = newSampledLines;
+ return ret_polygons;
+}
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.h
new file mode 100644
index 000000000..999f16319
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.h
@@ -0,0 +1,103 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _MONO_CHAIN_H
+#define _MONO_CHAIN_H
+
+#include "directedLine.h"
+#include "partitionY.h"
+
+class monoChain;
+
+class monoChain{
+ directedLine* chainHead;
+ directedLine* chainTail;
+ monoChain* next;
+ monoChain* prev;
+ monoChain* nextPolygon; //a list of polygons
+
+ //cached informatin
+ //bounding box
+ Real minX, maxX, minY, maxY;
+ Int isIncrease;
+
+ //for efficiently comparing two chains
+
+ directedLine* current;
+
+public:
+ monoChain(directedLine* cHead, directedLine* cTail);
+ ~monoChain() {}
+
+ inline void setNext(monoChain* n) {next = n;}
+ inline void setPrev(monoChain* p) {prev = p;}
+ inline void setNextPolygon(monoChain* np) {nextPolygon = np;}
+ inline monoChain* getNext() {return next;}
+ inline monoChain* getPrev() {return prev;}
+ inline directedLine* getHead() {return chainHead;}
+ inline directedLine* getTail() {return chainTail;}
+
+ inline void resetCurrent() { current = ((isIncrease==1)? chainHead:chainTail);}
+
+ void deleteLoop();
+ void deleteLoopList();
+
+ //insert a new chain between prev and this
+ void insert(monoChain* nc);
+
+ Int numChainsSingleLoop();
+ Int numChainsAllLoops();
+ monoChain** toArrayAllLoops(Int& num_chains);
+ Int toArraySingleLoop(monoChain** array, Int index);
+
+ Int isKey;
+ Real keyY; //the current horizotal line
+ Real chainIntersectHoriz(Real y); //updates current incrementally for efficiency
+ directedLine* find(Real y);//find dline so that y intersects dline.
+
+ void printOneChain();
+ void printChainLoop();
+ void printAllLoops();
+
+};
+
+monoChain* directedLineLoopToMonoChainLoop(directedLine* loop);
+monoChain* directedLineLoopListToMonoChainLoopList(directedLine* list);
+Int MC_sweepY(Int nVertices, monoChain** sortedVertices, sweepRange** ret_ranges);
+
+void MC_findDiagonals(Int total_num_edges, monoChain** sortedVertices,
+ sweepRange** ranges, Int& num_diagonals,
+ directedLine** diagonal_vertices);
+
+directedLine* MC_partitionY(directedLine *polygons, sampledLine **retSampledLines);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc
new file mode 100644
index 000000000..8391205bf
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc
@@ -0,0 +1,299 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+ *monoPolyPart.C
+ *
+ *To partition a v-monotone polygon into some uv-monotone polygons.
+ *The algorithm is different from the general monotone partition algorithm.
+ *while the general monotone partition algorithm works for this special case,
+ *but it is more expensive (O(nlogn)). The algorithm implemented here takes
+ *advantage of the fact that the input is a v-monotone polygon and it is
+ *conceptually simpler and computationally cheaper (a linear time algorithm).
+ *The algorithm is described in Zicheng Liu's paper
+ * "Quality-Oriented Linear Time Tessellation".
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "directedLine.h"
+#include "monoPolyPart.h"
+
+/*a vertex is u_maximal if both of its two neightbors are to the left of this
+ *vertex
+ */
+static Int is_u_maximal(directedLine* v)
+{
+ if (compV2InX(v->getPrev()->head(), v->head()) == -1 &&
+ compV2InX(v->getNext()->head(), v->head()) == -1)
+ return 1;
+ else
+ return 0;
+}
+
+/*a vertex is u_minimal if both of its two neightbors are to the right of this
+ *vertex
+ */
+static Int is_u_minimal(directedLine* v)
+{
+ if (compV2InX(v->getPrev()->head(), v->head()) == 1 &&
+ compV2InX(v->getNext()->head(), v->head()) == 1)
+ return 1;
+ else
+ return 0;
+}
+
+/*poly: a v-monotone polygon
+ *return: a linked list of uv-monotone polygons.
+ */
+directedLine* monoPolyPart(directedLine* polygon)
+{
+ //handle special cases:
+ if(polygon == NULL)
+ return NULL;
+ if(polygon->getPrev() == polygon)
+ return polygon;
+ if(polygon->getPrev() == polygon->getNext())
+ return polygon;
+ if(polygon->getPrev()->getPrev() == polygon->getNext())
+ return polygon;
+
+ //find the top and bottom vertexes
+ directedLine *tempV, *topV, *botV;
+ topV = botV = polygon;
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+
+ //initilization
+ directedLine *A, *B, *C, *D, *G, *H;
+ //find A:the first u_maximal vertex on the left chain
+ //and C: the left most vertex between top and A
+ A = NULL;
+ C = topV;
+ for(tempV=topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ if(tempV->head()[0] < C->head()[0])
+ C = tempV;
+
+ if(is_u_maximal(tempV))
+ {
+ A = tempV;
+ break;
+ }
+ }
+ if(A == NULL)
+ {
+ A = botV;
+ if(A->head()[0] < C->head()[0])
+ C = A;
+ }
+
+ //find B: the first u_minimal vertex on the right chain
+ //and D: the right most vertex between top and B
+ B = NULL;
+ D = topV;
+ for(tempV=topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] > D->head()[0])
+ D = tempV;
+ if(is_u_minimal(tempV))
+ {
+ B = tempV;
+ break;
+ }
+ }
+ if(B == NULL)
+ {
+ B = botV;
+ if(B->head()[0] > D->head()[0])
+ D = B;
+ }
+
+ //error checking XXX
+ if(C->head()[0] >= D->head()[0])
+ return polygon;
+
+ //find G on the left chain that is right above B
+ for(tempV=topV; compV2InY(tempV->head(), B->head()) == 1; tempV=tempV->getNext());
+ G = tempV->getPrev();
+ //find H on the right chain that is right above A
+ for(tempV=topV; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev());
+ H = tempV->getNext();
+
+ //Main Loop
+ directedLine* ret = NULL;
+ directedLine* currentPolygon = polygon;
+ while(1)
+ {
+ //if both B and D are equal to botV, then this polygon is already
+ //u-monotone
+ if(A == botV && B == botV)
+ {
+ ret = currentPolygon->insertPolygon(ret);
+ return ret;
+ }
+ else //not u-monotone
+ {
+ directedLine *ret_p1, *ret_p2;
+ if(compV2InY(A->head(),B->head()) == 1) //A is above B
+ {
+ directedLine* E = NULL;
+ for(tempV = C; tempV != D; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] >= A->head()[0])
+ {
+ E = tempV;
+ break;
+ }
+ }
+
+ if(E == NULL)
+ E = D;
+ if(E->head()[0]> H->head()[0])
+ E = H;
+ //connect AE and output polygon ECA
+ polygon->connectDiagonal_2slines(A, E,
+ &ret_p1,
+ &ret_p2,
+ NULL);
+ ret = ret_p2->insertPolygon(ret);
+ currentPolygon = ret_p1;
+
+ if(E == D)
+ D = ret_p1;
+ if(E == H)
+ H = ret_p1;
+ if(G->head()[1] >= A->head()[1])
+ G = A;
+ //update A to be the next u-maxiaml vertex on left chain
+ //and C the leftmost vertex between the old A and the new A
+ C = A;
+ for(tempV = A->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+
+ if(tempV->head()[0] < C->head()[0])
+ C = tempV;
+ if(is_u_maximal(tempV))
+ {
+ A = tempV;
+ break;
+ }
+ }
+
+ if(tempV == botV)
+ {
+ A = botV;
+ if(botV->head()[0] < C->head()[0])
+ C = botV;
+ }
+ //update H
+
+ if(A == botV)
+ H = botV;
+ else
+ {
+ for(tempV = H; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev());
+ H = tempV->getNext();
+ }
+
+ }
+ else //A is below B
+ {
+
+ directedLine* F = NULL;
+ for(tempV = D; tempV != C; tempV = tempV->getNext())
+ {
+ if(tempV->head()[0] <= B->head()[0])
+ {
+ F = tempV;
+ break;
+ }
+ }
+ if(F == NULL)
+ F = C;
+ if(F->head()[0] < G->head()[0])
+ F = G;
+
+ //connect FB
+ polygon->connectDiagonal_2slines(F, B,
+ &ret_p1,
+ &ret_p2,
+ NULL);
+ ret = ret_p2->insertPolygon(ret);
+ currentPolygon = ret_p1;
+ B = ret_p1;
+ if(H ->head()[1] >= B->head()[1])
+ H = ret_p1;
+
+ //update B to be the next u-minimal vertex on right chain
+ //and D the rightmost vertex between the old B and the new B
+ D = B;
+ for(tempV = B->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] > D->head()[0])
+ D = tempV;
+ if(is_u_minimal(tempV))
+ {
+ B = tempV;
+ break;
+ }
+ }
+ if(tempV == botV)
+ {
+ B = botV;
+ if(botV->head()[0] > D->head()[0])
+ D = botV;
+ }
+ //update G
+ if(B == botV)
+ G = botV;
+ else
+ {
+ for(tempV = G; compV2InY(tempV->head(), B->head()) == 1; tempV = tempV->getNext());
+ G = tempV->getPrev();
+ }
+ } //end of A is below B
+ } //end not u-monotone
+ } //end of main loop
+}
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h
new file mode 100644
index 000000000..6877a59c2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h
@@ -0,0 +1,41 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+ *monoPolyPart.h
+ */
+
+#ifndef _MONO_POLY_PART_H
+#define _MONO_POLY_PART_H
+
+class directedLine;
+
+directedLine* monoPolyPart(directedLine* polygon);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc
new file mode 100644
index 000000000..8e8d49dda
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc
@@ -0,0 +1,1482 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gluos.h"
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "monoTriangulation.h"
+#include "polyUtil.h" /*for area*/
+#include "partitionX.h"
+#include "monoPolyPart.h"
+
+
+
+extern directedLine* polygonConvert(directedLine* polygon);
+
+/*poly is NOT deleted
+ */
+void monoTriangulationOpt(directedLine* poly, primStream* pStream)
+{
+ Int n_cusps;
+ Int n_edges = poly->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
+ assert(cusps);
+ findInteriorCuspsX(poly, n_cusps, cusps);
+ if(n_cusps ==0) //u monotine
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else if(n_cusps == 1) // one interior cusp
+ {
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+ directedLine* other = findDiagonal_singleCuspX(new_polygon);
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else
+ {
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+ }
+ }
+ else
+ {
+ //we need a general partitionX funtion (supposed to be in partitionX.C,
+ //not implemented yet. XXX
+ monoTriangulationFun(poly, compV2InY, pStream);
+ }
+
+ free(cusps);
+}
+
+void monoTriangulationRecOpt(Real* topVertex, Real* botVertex,
+ vertexArray* left_chain, Int left_current,
+ vertexArray* right_chain, Int right_current,
+ primStream* pStream)
+{
+ Int i,j;
+ Int n_left = left_chain->getNumElements();
+ Int n_right = right_chain->getNumElements();
+ if(left_current>= n_left-1 ||
+ right_current>= n_right-1)
+ {
+ monoTriangulationRec(topVertex, botVertex, left_chain, left_current,
+ right_chain, right_current, pStream);
+ return;
+ }
+ //now both left and right have at least two vertices each.
+ Real left_v = left_chain->getVertex(left_current)[1];
+ Real right_v = right_chain->getVertex(right_current)[1];
+
+ if(left_v <= right_v) //first left vertex is below right
+ {
+ //find the last vertex of right which is above or equal to left
+ for(j=right_current; j<=n_right-1; j++)
+ {
+ if(right_chain->getVertex(j)[1] < left_v)
+ break;
+ }
+ monoTriangulationRecGen(topVertex, left_chain->getVertex(left_current),
+ left_chain, left_current, left_current,
+ right_chain, right_current, j-1,
+ pStream);
+ monoTriangulationRecOpt(right_chain->getVertex(j-1),
+ botVertex,
+ left_chain, left_current,
+ right_chain, j,
+ pStream);
+ }
+ else //first right vertex is strictly below left
+ {
+ //find the last vertex of left which is strictly above right
+ for(i=left_current; i<=n_left-1; i++)
+ {
+ if(left_chain->getVertex(i)[1] <= right_v)
+ break;
+ }
+ monoTriangulationRecGen(topVertex, right_chain->getVertex(right_current),
+ left_chain, left_current, i-1,
+ right_chain, right_current, right_current,
+ pStream);
+ monoTriangulationRecOpt(left_chain->getVertex(i-1),
+ botVertex,
+ left_chain, i,
+ right_chain, right_current,
+ pStream);
+ }
+}
+
+
+void monoTriangulationRecGenTBOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ pStream->triangle(topVertex, inc_chain->getVertex(inc_current), dec_chain->getVertex(dec_current));
+
+/*printf("**(%f,%f)\n", inc_chain->getArray()[0][0],inc_chain->getArray()[0][1]);*/
+ triangulateXYMonoTB(inc_end-inc_current+1, inc_chain->getArray()+inc_current, dec_end-dec_current+1, dec_chain->getArray()+dec_current, pStream);
+
+ pStream->triangle(botVertex, dec_chain->getVertex(dec_end), inc_chain->getVertex(inc_end));
+}
+
+
+/*n_left>=1
+ *n_right>=1
+ *the strip is going top to bottom. compared to the funtion
+ * triangulateXYmono()
+ */
+void triangulateXYMonoTB(Int n_left, Real** leftVerts,
+ Int n_right, Real** rightVerts,
+ primStream* pStream)
+{
+
+
+ Int i,j,k,l;
+ Real* topMostV;
+
+ assert(n_left>=1 && n_right>=1);
+ if(leftVerts[0][1] >= rightVerts[0][1])
+ {
+ i=1;
+ j=0;
+ topMostV = leftVerts[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+ topMostV = rightVerts[0];
+ }
+
+ while(1)
+ {
+ if(i >= n_left) /*case1: no more in left*/
+ {
+
+ if(j<n_right-1) /*at least two vertices in right*/
+ {
+ pStream->begin();
+ pStream->insert(topMostV);
+ for(k=n_right-1; k>=j; k--)
+ pStream->insert(rightVerts[j]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+
+ }
+
+ break;
+ }
+ else if(j>= n_right) /*case2: no more in right*/
+ {
+
+ if(i<n_left-1) /*at least two vertices in left*/
+ {
+ pStream->begin();
+ pStream->insert(topMostV);
+
+ for(k=i; k<n_left; k++)
+ pStream->insert(leftVerts[k]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else /* case3: neither is empty, plus the topMostV, there is at least one triangle to output*/
+ {
+
+ if(leftVerts[i][1] >= rightVerts[j][1])
+ {
+ pStream->begin();
+ pStream->insert(rightVerts[j]); /*the origin of this fan*/
+
+ pStream->insert(topMostV);
+
+ /*find the last k>=i such that
+ *leftverts[k][1] >= rightverts[j][1]
+ */
+ k=i;
+ while(k<n_left)
+ {
+ if(leftVerts[k][1] < rightVerts[j][1])
+ break;
+ k++;
+ }
+ k--;
+ for(l=i; l<=k; l++)
+ {
+ pStream->insert(leftVerts[l]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ //update i for next loop
+ i = k+1;
+ topMostV = leftVerts[k];
+
+ }
+ else /*leftVerts[i][1] < rightVerts[j][1]*/
+ {
+ pStream->begin();
+ pStream->insert(leftVerts[i]);/*the origion of this fan*/
+
+ /*find the last k>=j such that
+ *rightverts[k][1] > leftverts[i][1]*/
+ k=j;
+ while(k< n_right)
+ {
+ if(rightVerts[k][1] <= leftVerts[i][1])
+ break;
+ k++;
+ }
+ k--;
+
+ for(l=k; l>= j; l--)
+ pStream->insert(rightVerts[l]);
+
+ pStream->insert(topMostV);
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ j=k+1;
+ topMostV = rightVerts[j-1];
+ }
+ }
+ }
+}
+
+static int chainConvex(vertexArray* inc_chain, Int inc_current, Int inc_end)
+{
+ Int i;
+ //if there are no more than 2 vertices, return 1
+ if(inc_current >= inc_end-1) return 1;
+ for(i=inc_current; i<= inc_end-2; i++)
+ {
+ if(area(inc_chain->getVertex(i), inc_chain->getVertex(i+1), inc_chain->getVertex(i+2)) <0)
+ return 0;
+ }
+ return 1;
+}
+
+static int chainConcave(vertexArray* dec_chain, Int dec_current, Int dec_end)
+{
+ Int i;
+ //if there are no more than 2 vertices, return 1
+ if(dec_current >= dec_end -1) return 1;
+ for(i=dec_current; i<=dec_end-2; i++)
+ {
+ if(area(dec_chain->getVertex(i), dec_chain->getVertex(i+1), dec_chain->getVertex(i+2)) >0)
+ return 0;
+ }
+ return 1;
+}
+
+void monoTriangulationRecGenInU(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+
+}
+
+void monoTriangulationRecGenOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ Int i;
+ //copy this to a polygon: directedLine Lioop
+ sampledLine* sline;
+ directedLine* dline;
+ directedLine* poly;
+
+ if(inc_current <= inc_end) //at least one vertex in inc_chain
+ {
+ sline = new sampledLine(topVertex, inc_chain->getVertex(inc_current));
+ poly = new directedLine(INCREASING, sline);
+ for(i=inc_current; i<=inc_end-1; i++)
+ {
+ sline = new sampledLine(inc_chain->getVertex(i), inc_chain->getVertex(i+1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ sline = new sampledLine(inc_chain->getVertex(inc_end), botVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ else //inc_chian is empty
+ {
+ sline = new sampledLine(topVertex, botVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly = dline;
+ }
+
+ assert(poly != NULL);
+
+ if(dec_current <= dec_end) //at least on vertex in dec_Chain
+ {
+ sline = new sampledLine(botVertex, dec_chain->getVertex(dec_end));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ for(i=dec_end; i>dec_current; i--)
+ {
+ sline = new sampledLine(dec_chain->getVertex(i), dec_chain->getVertex(i-1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ sline = new sampledLine(dec_chain->getVertex(dec_current), topVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ else //dec_chain is empty
+ {
+ sline = new sampledLine(botVertex, topVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ {
+ Int n_cusps;
+ Int n_edges = poly->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
+ assert(cusps);
+ findInteriorCuspsX(poly, n_cusps, cusps);
+
+ if(n_cusps ==0) //u monotine
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else if(n_cusps == 1) // one interior cusp
+ {
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+ directedLine* other = findDiagonal_singleCuspX(new_polygon);
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else
+ {
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+ }
+ }
+ else
+ {
+ //we need a general partitionX funtion (supposed to be in partitionX.C,
+ //not implemented yet. XXX
+ //monoTriangulationFun(poly, compV2InY, pStream);
+
+ directedLine* new_polygon = polygonConvert(poly);
+ directedLine* list = monoPolyPart(new_polygon);
+ for(directedLine* temp = list; temp != NULL; temp = temp->getNextPolygon())
+ {
+ monoTriangulationFun(temp, compV2InX, pStream);
+ }
+ //clean up
+ list->deletePolygonListWithSline();
+
+ }
+
+ free(cusps);
+ /*
+ if(numInteriorCuspsX(poly) == 0) //is u monotone
+ monoTriangulationFun(poly, compV2InX, pStream);
+ else //it is not u motone
+ monoTriangulationFun(poly, compV2InY, pStream);
+ */
+ //clean up space
+ poly->deleteSinglePolygonWithSline();
+ return;
+ }
+
+ //apparently the following code is not reachable,
+ //it is for test purpose
+ if(inc_current > inc_end || dec_current>dec_end)
+ {
+ monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+
+
+ if(
+ area(dec_chain->getVertex(dec_current),
+ topVertex,
+ inc_chain->getVertex(inc_current)) >=0
+ && chainConvex(inc_chain, inc_current, inc_end)
+ && chainConcave(dec_chain, dec_current, dec_end)
+ && area(inc_chain->getVertex(inc_end), botVertex, dec_chain->getVertex(dec_end)) >=0
+ )
+ {
+ monoTriangulationRecFunGen(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ compV2InX, pStream);
+ }
+ else
+ {
+ monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ }
+}
+
+/*if inc_current>inc_end, then inc_chain has no points to be considered
+ *same for dec_chain
+ */
+void monoTriangulationRecGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+
+ if(inc_current > inc_end && dec_current>dec_end)
+ return;
+ else if(inc_current>inc_end) /*no more vertices on inc_chain*/
+ {
+ dec_array = dec_chain->getArray();
+ reflexChain rChain(100,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<=dec_end; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else if(dec_current> dec_end) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+
+ reflexChain rChain(100,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<=inc_end; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(100, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<=dec_end; i++)
+ {
+ if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecGen(dec_array[i-1], botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, i, dec_end,
+ pStream);
+ }
+ else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(100, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<=inc_end; i++)
+ {
+ if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecGen(inc_array[i-1], botVertex,
+ inc_chain, i, inc_end,
+ dec_chain, dec_current,dec_end,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+void monoTriangulationFun(directedLine* monoPolygon, Int (*compFun)(Real*, Real*), primStream* pStream)
+{
+ Int i;
+ /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
+ *then call monoTriangulationRec
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = monoPolygon;
+ for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
+ {
+ if(compFun(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compFun(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+
+ /*creat increase and decrease chains*/
+ vertexArray inc_chain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ inc_chain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ inc_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray dec_chain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+
+ if (!(0 == inc_chain.getNumElements() && 0 == dec_chain.getNumElements())) {
+ monoTriangulationRecFun(topV->head(), botV->head(), &inc_chain, 0,
+ &dec_chain, 0, compFun, pStream);
+ }
+}
+
+void monoTriangulation(directedLine* monoPolygon, primStream* pStream)
+{
+ Int i;
+ /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
+ *then call monoTriangulationRec
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = monoPolygon;
+ for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+ /*creat increase and decrease chains*/
+ vertexArray inc_chain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ inc_chain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ inc_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray dec_chain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+
+ monoTriangulationRec(topV->head(), botV->head(), &inc_chain, 0, &dec_chain, 0, pStream);
+
+}
+
+/*the chain could be increasing or decreasing, although we use the
+ * name inc_chain.
+ *the argument is_increase_chain indicates whether this chain
+ *is increasing (left chain in V-monotone case) or decreaing (right chain
+ *in V-monotone case).
+ */
+void monoTriangulation2(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_smallIndex,
+ Int inc_largeIndex,
+ Int is_increase_chain,
+ primStream* pStream)
+{
+ assert( inc_chain != NULL);
+ Real** inc_array ;
+
+ if(inc_smallIndex > inc_largeIndex)
+ return; //no triangles
+ if(inc_smallIndex == inc_largeIndex)
+ {
+ if(is_increase_chain)
+ pStream->triangle(inc_chain->getVertex(inc_smallIndex), botVertex, topVertex);
+ else
+ pStream->triangle(inc_chain->getVertex(inc_smallIndex), topVertex, botVertex);
+ return;
+ }
+ Int i;
+
+ if(is_increase_chain && botVertex[1] == inc_chain->getVertex(inc_largeIndex)[1])
+ {
+ pStream->triangle(botVertex, inc_chain->getVertex(inc_largeIndex-1),
+ inc_chain->getVertex(inc_largeIndex));
+ monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex,
+ inc_largeIndex-1,
+ is_increase_chain,
+ pStream);
+ return;
+ }
+ else if( (!is_increase_chain) && topVertex[1] == inc_chain->getVertex(inc_smallIndex)[1])
+ {
+ pStream->triangle(topVertex, inc_chain->getVertex(inc_smallIndex+1),
+ inc_chain->getVertex(inc_smallIndex));
+ monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex+1,
+ inc_largeIndex, is_increase_chain, pStream);
+ return ;
+ }
+
+ inc_array = inc_chain->getArray();
+
+ reflexChain rChain(20,is_increase_chain); /*1 means the chain is increasing*/
+
+ rChain.processNewVertex(topVertex, pStream);
+
+ for(i=inc_smallIndex; i<=inc_largeIndex; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ rChain.processNewVertex(botVertex, pStream);
+
+}
+
+/*if compFun == compV2InY, top to bottom: V-monotone
+ *if compFun == compV2InX, right to left: U-monotone
+ */
+void monoTriangulationRecFunGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current> inc_end &&
+ dec_current> dec_end));
+ /*
+ Int inc_nVertices;
+ Int dec_nVertices;
+ */
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current> inc_end) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<=dec_end; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current> dec_end) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<=inc_end; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<=dec_end; i++)
+ {
+ if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecFunGen(dec_array[i-1], botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, i, dec_end,
+ compFun,
+ pStream);
+ }
+ else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<=inc_end; i++)
+ {
+ if(compFun(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecFunGen(inc_array[i-1], botVertex,
+ inc_chain, i,inc_end,
+ dec_chain, dec_current,dec_end,
+ compFun,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+/*if compFun == compV2InY, top to bottom: V-monotone
+ *if compFun == compV2InX, right to left: U-monotone
+ */
+void monoTriangulationRecFun(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecFun(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ compFun,
+ pStream);
+ }
+ else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compFun(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecFun(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ compFun,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRec(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ pStream);
+ }
+ else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRec(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+
+
+/* the name here assumes that the polygon is Y-monotone, but
+ *this function also works for X-monotone polygons.
+ * a monotne polygon consists of two extrem verteices: topVertex and botVertex, and
+ *two monotone chains: inc_chain, and dec_chain. The edges of the increasing chain (inc_chain)
+ *is ordered by following pointer: next, while the edges of the decreasing chain (dec_chain)
+ *is ordered by following pointer: prev
+ * inc_index index the vertex which is the toppest of the inc_chain which we are handling currently.
+ * dec_index index the vertex which is the toppest of the dec_chain which we are handling currently.
+ */
+void monoTriangulationRec(directedLine* inc_chain, Int inc_index,
+ directedLine* dec_chain, Int dec_index,
+ directedLine* topVertex, Int top_index,
+ directedLine* botVertex,
+ primStream* pStream)
+{
+ Int i;
+ directedLine *temp, *oldtemp = NULL;
+ Int tempIndex, oldtempIndex = 0;
+
+ assert(inc_chain != NULL && dec_chain != NULL);
+
+ if(inc_chain == botVertex) {
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
+ for(i=dec_index; i< dec_chain->get_npoints(); i++){
+ rChain.processNewVertex(dec_chain->getVertex(i), pStream);
+ }
+ for(temp = dec_chain->getPrev(); temp != botVertex; temp = temp->getPrev())
+ {
+ for(i=0; i<temp->get_npoints(); i++){
+ rChain.processNewVertex(temp->getVertex(i), pStream);
+ }
+ }
+ }
+ else if(dec_chain==botVertex) {
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
+ for(i=inc_index; i< inc_chain->get_npoints(); i++){
+ rChain.processNewVertex(inc_chain->getVertex(i), pStream);
+ }
+ for(temp = inc_chain->getPrev(); temp != botVertex; temp = temp->getNext())
+ {
+ for(i=0; i<temp->get_npoints(); i++){
+ rChain.processNewVertex(temp->getVertex(i), pStream);
+ }
+ }
+ }
+ else /*neither reached the bottom*/{
+ if(compV2InY(inc_chain->getVertex(inc_index), dec_chain->getVertex(dec_index)) <=0) {
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
+ temp = dec_chain;
+ tempIndex = dec_index;
+ while( compV2InY(inc_chain->getVertex(inc_index), temp->getVertex(tempIndex))<=0) {
+ oldtemp = temp;
+ oldtempIndex = tempIndex;
+ rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
+
+ if(tempIndex == temp->get_npoints()-1){
+ tempIndex = 0;
+ temp = temp->getPrev();
+ }
+ else{
+ tempIndex++;
+ }
+ }
+ rChain.outputFan(inc_chain->getVertex(inc_index), pStream);
+ monoTriangulationRec(inc_chain, inc_index, temp, tempIndex, oldtemp, oldtempIndex, botVertex, pStream);
+ }
+ else /* >0*/ {
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
+ temp = inc_chain;
+ tempIndex = inc_index;
+ while( compV2InY(temp->getVertex(tempIndex), dec_chain->getVertex(dec_index))>0){
+ oldtemp = temp;
+ oldtempIndex = tempIndex;
+ rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
+
+ if(tempIndex == temp->get_npoints()-1){
+ tempIndex = 0;
+ temp = temp->getNext();
+ }
+ else{
+ tempIndex++;
+ }
+ }
+ rChain.outputFan(dec_chain->getVertex(dec_index), pStream);
+ monoTriangulationRec(temp, tempIndex, dec_chain, dec_index, oldtemp, oldtempIndex, botVertex, pStream);
+ }
+ } /*end case neither reached the bottom*/
+}
+
+/***************************vertexArray begin here**********************************/
+vertexArray::vertexArray(Real2* vertices, Int nVertices)
+{
+ Int i;
+ size = index = nVertices;
+ array = (Real**) malloc(sizeof(Real*) * nVertices);
+ assert(array);
+ for(i=0; i<nVertices; i++)
+ {
+ array[i] = vertices[i];
+ array[i] = vertices[i];
+ }
+}
+
+vertexArray::vertexArray(Int s)
+{
+ size = s;
+ array = (Real**) malloc(sizeof(Real*) * s);
+ assert(array);
+ index = 0;
+}
+
+vertexArray::~vertexArray()
+{
+ free(array);
+}
+
+void vertexArray::appendVertex(Real* ptr)
+{
+ Int i;
+ if(index >= size){
+ Real** temp = (Real**) malloc(sizeof(Real*) * (2*size +1));
+ assert(temp);
+ for(i=0; i<index; i++)
+ temp[i] = array[i];
+ free(array);
+ array = temp;
+ size = 2*size+1;
+ }
+ array[index++] = ptr;
+}
+
+void vertexArray::print()
+{
+ printf("vertex Array:index=%i, size=%i\n", index, size);
+ for(Int i=0; i<index; i++)
+ {
+ printf("(%f,%f) ", array[i][0], array[i][1]);
+ }
+ printf("\n");
+}
+
+/*find the first i such that array[i][1] >= v
+ * and array[i+1][1] <v
+ * if index == 0 (the array is empty, return -1.
+ * if v is above all, return -1.
+ * if v is below all, return index-1.
+ */
+Int vertexArray::findIndexAbove(Real v)
+{
+ Int i;
+ if(index == 0)
+ return -1;
+ else if(array[0][1] < v)
+ return -1;
+ else
+ {
+ for(i=1; i<index; i++)
+ {
+ if(array[i][1] < v)
+ break;
+ }
+ return i-1;
+ }
+}
+
+/*find the first i<=endIndex such that array[i][1] <= v
+ * and array[i-1][1] > v
+ *if sartIndex>endIndex, then return endIndex+1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is below all, return endIndex+1
+ * if v is above all, return startIndex.
+ */
+Int vertexArray::findIndexBelowGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return endIndex+1;
+ else if(array[endIndex][1] > v)
+ return endIndex+1;
+ else //now array[endIndex][1] <= v
+ {
+ for(i=endIndex-1; i>=startIndex; i--)
+ {
+ if(array[i][1] > v)
+ break;
+ }
+ return i+1;
+ }
+}
+
+/*find the first i<=endIndex such that array[i-1][1] >= v
+ * and array[i][1] < v
+ *if sartIndex>endIndex, then return endIndex+1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is below or equal to all, return endIndex+1
+ * if v is strictly above all, return startIndex.
+ */
+Int vertexArray::findIndexStrictBelowGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return endIndex+1;
+ else if(array[endIndex][1] >= v)
+ return endIndex+1;
+ else //now array[endIndex][1] < v
+ {
+ for(i=endIndex-1; i>=startIndex; i--)
+ {
+ if(array[i][1] >= v)
+ break;
+ }
+ return i+1;
+ }
+}
+
+/*find the first i>startIndex such that array[i-1][1] > v
+ * and array[i][1] >=v
+ *if sartIndex>endIndex, then return startIndex-1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is strictly above all, return startIndex-1
+ * if v is strictly below all, return endIndex.
+ */
+Int vertexArray::findIndexFirstAboveEqualGen(Real v, Int startIndex, Int endIndex)
+{
+
+ Int i;
+ if(startIndex > endIndex)
+ return startIndex-1;
+ else if(array[startIndex][1] < v)
+ return startIndex-1;
+ else //now array[startIndex][1] >= v
+ {
+
+ for(i=startIndex; i<=endIndex; i++)
+ {
+ if(array[i][1] <= v)
+ break;
+ }
+ if(i>endIndex) // v is strictly below all
+ return endIndex;
+ else if(array[i][1] == v)
+ return i;
+ else
+ return i-1;
+ }
+
+}
+
+
+/*find the first i>=startIndex such that array[i][1] >= v
+ * and array[i+1][1] <v
+ *if sartIndex>endIndex, then return startIndex-1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is above all, return startIndex-1
+ * if v is below all, return endIndex.
+ */
+Int vertexArray::findIndexAboveGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return startIndex-1;
+ else if(array[startIndex][1] < v)
+ return startIndex-1;
+ else //now array[startIndex][1] >= v
+ {
+ for(i=startIndex+1; i<=endIndex; i++)
+ {
+ if(array[i][1] < v)
+ break;
+ }
+ return i-1;
+ }
+}
+
+Int vertexArray::findDecreaseChainFromEnd(Int begin, Int end)
+{
+ Int i = end;
+ Real prevU = array[i][0];
+ Real thisU;
+ for(i=end-1; i>=begin; i--){
+ thisU = array[i][0];
+ if(thisU < prevU)
+ prevU = thisU;
+ else
+ break;
+ }
+ return i;
+}
+
+//if(V(start) == v, return start, other wise return the
+//last i so that V(i)==v
+Int vertexArray::skipEqualityFromStart(Real v, Int start, Int end)
+{
+ Int i;
+ if(array[start][1] != v)
+ return start;
+ //now array[start][1] == v
+ for(i=start+1; i<= end; i++)
+ if(array[i][1] != v)
+ break;
+ return i-1;
+}
+
+
+/***************************vertexArray end****************************************/
+
+
+
+/***************************relfex chain stuff begin here*****************************/
+
+reflexChain::reflexChain(Int size, Int is_increasing)
+{
+ queue = (Real2*) malloc(sizeof(Real2) * size);
+ assert(queue);
+ index_queue = 0;
+ size_queue = size;
+ isIncreasing = is_increasing;
+}
+
+reflexChain::~reflexChain()
+{
+ free(queue);
+}
+
+/*put (u,v) at the end of the queue
+ *pay attention to space
+ */
+void reflexChain::insert(Real u, Real v)
+{
+ Int i;
+ if(index_queue >= size_queue) {
+ Real2 *temp = (Real2*) malloc(sizeof(Real2) * (2*size_queue+1));
+ assert(temp);
+
+ /*copy*/
+ for(i=0; i<index_queue; i++){
+ temp[i][0] = queue[i][0];
+ temp[i][1] = queue[i][1];
+ }
+
+ free(queue);
+ queue = temp;
+ size_queue = 2*size_queue + 1;
+ }
+
+ queue[index_queue][0] = u;
+ queue[index_queue][1] = v;
+ index_queue ++;
+}
+
+void reflexChain::insert(Real v[2])
+{
+ insert(v[0], v[1]);
+}
+
+/*
+static Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+}
+*/
+
+/*the chain is reflex, and the vertex v is
+ *on the other side of the chain, so that
+ *we can outout the fan with v as the
+ *the center
+ */
+void reflexChain::outputFan(Real v[2], primStream* pStream)
+{
+ Int i;
+ pStream->begin();
+ pStream->insert(v);
+ if(isIncreasing) {
+ for(i=0; i<index_queue; i++)
+ pStream->insert(queue[i]);
+ }
+ else {
+ for(i=index_queue-1; i>=0; i--)
+ pStream->insert(queue[i]);
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+}
+
+void reflexChain::processNewVertex(Real v[2], primStream* pStream)
+{
+ Int i,j,k;
+ Int isReflex;
+ /*if there are at most one vertex in the queue, then simply insert
+ */
+ if(index_queue <=1){
+ insert(v);
+ return;
+ }
+
+ /*there are at least two vertices in the queue*/
+ j=index_queue-1;
+
+ for(i=j; i>=1; i--) {
+ if(isIncreasing) {
+ isReflex = (area(queue[i-1], queue[i], v) <= 0.0);
+ }
+ else /*decreasing*/{
+ isReflex = (area(v, queue[i], queue[i-1]) <= 0.0);
+ }
+ if(isReflex) {
+ break;
+ }
+ }
+
+ /*
+ *if i<j then vertices: i+1--j are convex
+ * output triangle fan:
+ * v, and queue[i], i+1, ..., j
+ */
+ if(i<j)
+ {
+ pStream->begin();
+ pStream->insert(v);
+ if(isIncreasing) {
+ for(k=i; k<=j; k++)
+ pStream->insert(queue[k]);
+ }
+ else {
+ for(k=j; k>=i; k--)
+ pStream->insert(queue[k]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ /*delete vertices i+1--j from the queue*/
+ index_queue = i+1;
+ /*finally insert v at the end of the queue*/
+ insert(v);
+
+}
+
+void reflexChain::print()
+{
+ Int i;
+ printf("reflex chain: isIncreasing=%i\n", isIncreasing);
+ for(i=0; i<index_queue; i++) {
+ printf("(%f,%f) ", queue[i][0], queue[i][1]);
+ }
+ printf("\n");
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h
new file mode 100644
index 000000000..f78b8f402
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h
@@ -0,0 +1,184 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _MONO_TRIANGULATION_H
+#define _MONO_TRIANGULATION_H
+
+#include "definitions.h"
+#include "primitiveStream.h"
+#include "directedLine.h"
+#include "arc.h"
+
+class Backend;
+
+class reflexChain{
+ Real2 *queue;
+ /*the order of the polygon vertices: either q[0],q[1].., or
+ * q[n-1], q[n-2], ..., q[0]
+ *this order determines the interior of the polygon, so it
+ *also used to determines whether a chain is reflex or convex
+ */
+ Int isIncreasing;
+ Int index_queue;
+ Int size_queue; /*allocated size*/
+
+public:
+ reflexChain(Int size, Int isIncreasing);
+ ~reflexChain();
+
+ void insert(Real u, Real v);
+ void insert(Real v[2]);
+
+ void processNewVertex(Real v[2], primStream* pStream);
+ void outputFan(Real v[2], primStream* pStream);
+
+ void processNewVertex(Real v[2], Backend* backend);
+ void outputFan(Real v[2], Backend* backend);
+
+ void print();
+};
+
+/*dynamic array of pointers to reals.
+ *Intended to store an array of (u,v).
+ *Notice that it doesn't allocate or dealocate the space
+ *for the (u,v) themselfs. So it assums that someone else
+ *is taking care of them, while this class only plays with
+ *the pointers.
+ */
+class vertexArray{
+ Real** array;
+ Int index;
+ Int size;
+public:
+ vertexArray(Int s);
+ vertexArray(Real vertices[][2], Int nVertices);
+ ~vertexArray();
+ void appendVertex(Real* ptr); /*the content (pointed by ptr is NOT copied*/
+ Real* getVertex(Int i) {return array[i];}
+ Real** getArray() {return array;}
+ Int getNumElements() {return index;}
+ Int findIndexAbove(Real v);
+ Int findIndexAboveGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexBelowGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexStrictBelowGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexFirstAboveEqualGen(Real v, Int startIndex, Int endIndex);
+ Int skipEqualityFromStart(Real v, Int start, Int end);
+ //return i such that fron [i+1, end] is strictly U-monotone (left to right
+ Int findDecreaseChainFromEnd(Int begin, Int end);
+ void print();
+};
+
+void monoTriangulation(directedLine* monoPolygon, primStream* pStream);
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ primStream* pStream);
+
+void monoTriangulationRec(directedLine* inc_chain, Int inc_index,
+ directedLine* dec_chain, Int dec_index,
+ directedLine* topVertex, Int top_index,
+ directedLine* botVertex,
+ primStream* pStream);
+
+/*the chain could be increasing or decreasing, although we use the
+ * name inc_chain.
+ *the argument is_increase_chain indicates whether this chain
+ *is increasing (left chain in V-monotone case) or decreaing (right chain
+ *in V-monotone case).
+ */
+void monoTriangulation2(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_smallIndex,
+ Int inc_largeIndex,
+ Int is_increase_chain,
+ primStream* pStream);
+void monoTriangulationRecGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void monoTriangulationRecGenOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void triangulateXYMonoTB(Int n_left, Real** leftVerts,
+ Int n_right, Real** rightVerts,
+ primStream* pStream);
+
+void monoTriangulationRecGenTBOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void monoTriangulationRecOpt(Real* topVertex, Real* botVertex,
+ vertexArray* left_chain, Int left_current,
+ vertexArray* right_chain, Int right_current,
+ primStream* pStream);
+
+void monoTriangulationRecFunGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream);
+
+void monoTriangulationRecFun(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream);
+void monoTriangulationFun(directedLine* monoPolygon,
+ Int (*compFun)(Real*, Real*), primStream* pStream);
+
+
+
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Backend* backend);
+
+void monoTriangulationFunBackend(Arc_ptr loop, Int (*compFun)(Real*, Real*), Backend* backend);
+
+void monoTriangulationRecFunBackend(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ Backend* backend);
+
+void monoTriangulationOpt(directedLine* poly, primStream* pStream);
+
+#endif
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdio.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdio.h
new file mode 100644
index 000000000..a394e0ff9
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdio.h
@@ -0,0 +1,60 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mystdio.h
+ *
+ */
+
+#ifndef __glumystdio_h_
+#define __glumystdio_h_
+
+#ifdef STANDALONE
+inline void _glu_dprintf( char *, ... ) { }
+#endif
+
+#ifdef LIBRARYBUILD
+#ifndef NDEBUG
+#include <stdio.h>
+#define _glu_dprintf printf
+#else
+inline void _glu_dprintf( char *, ... ) { }
+#endif
+#endif
+
+#ifdef GLBUILD
+inline void _glu_dprintf( char *, ... ) { }
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif /* __glumystdio_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdlib.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdlib.h
new file mode 100644
index 000000000..ab7a3b273
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdlib.h
@@ -0,0 +1,57 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mystdlib.h
+ *
+ */
+
+#ifndef __glumystdlib_h_
+#define __glumystdlib_h_
+
+#ifdef STANDALONE
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#ifdef LIBRARYBUILD
+#include <stdlib.h>
+#endif
+
+#ifdef GLBUILD
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#endif /* __glumystdlib_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.cc
new file mode 100644
index 000000000..e25e30b0f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.cc
@@ -0,0 +1,162 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "partitionX.h"
+
+#define CONCAVITY_ZERO 1.0e-6 //this number is used to test whether a vertex is concave (refelx)
+ //or not. The test needs to compute the area of the three adjacent
+ //vertices to see if the are is positive or negative.
+
+Int isCuspX(directedLine *v)
+{
+ //if v->prev <= v && v->next <= v
+ //|| v->prev >= v && v->next >= v
+ Real* T = v->head();
+ Real* P = v->getPrev()->head();
+ Real* N = v->getNext()->head();
+ if(
+ (compV2InX(T,P) != -1 &&
+ compV2InX(T,N) != -1
+ ) ||
+ (compV2InX(T,P) != 1 &&
+ compV2InX(T,N) != 1
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+Int isReflexX(directedLine* v)
+{
+ Real* A = v->getPrev()->head();
+ Real* B = v->head();
+ Real* C = v->tail();
+ Real Bx,By, Cx, Cy;
+ //scale them in case they are too small
+ Bx = 10*(B[0] - A[0]);
+ By = 10*(B[1] - A[1]);
+ Cx = 10*(C[0] - A[0]);
+ Cy = 10*(C[1] - A[1]);
+
+ if(Bx*Cy - Cx*By < -CONCAVITY_ZERO) return 1;
+ else return 0;
+}
+
+
+/*return
+ *0: not-cusp
+ *1: interior cusp
+ *2: exterior cusp
+ */
+Int cuspTypeX(directedLine *v)
+{
+ if(! isCuspX(v)) return 0;
+ else
+ {
+//printf("isCusp,%f,%f\n", v->head()[0], v->head()[1]);
+ if(isReflexX(v))
+ {
+// printf("isReflex\n");
+ return 1;
+ }
+ else
+ {
+// printf("not isReflex\n");
+ return 2;
+ }
+ }
+}
+
+Int numInteriorCuspsX(directedLine *polygon)
+{
+ directedLine *temp;
+ int ret = 0;
+ if(cuspTypeX(polygon) == 1)
+ ret++;
+ for(temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ if(cuspTypeX(temp) == 1)
+ ret++;
+ return ret;
+}
+
+
+void findInteriorCuspsX(directedLine *polygon, Int& ret_n_interior_cusps,
+ directedLine** ret_interior_cusps)
+{
+ directedLine *temp;
+ ret_n_interior_cusps = 0;
+ if(cuspTypeX(polygon) == 1)
+ {
+ ret_interior_cusps[ret_n_interior_cusps++] = polygon;
+ }
+ for(temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ if(cuspTypeX(temp) == 1)
+ {
+ ret_interior_cusps[ret_n_interior_cusps++] = temp;
+ }
+}
+
+directedLine* findDiagonal_singleCuspX(directedLine* cusp)
+{
+ directedLine* temp;
+ Int is_minimal = ((compV2InX(cusp->head(), cusp->tail()) == -1)? 1:0);
+
+ if(is_minimal)
+ for(temp = cusp->getNext(); temp != cusp; temp = temp->getNext())
+ {
+ if(compV2InX(cusp->head(), temp->head()) == 1)
+ {
+ return temp;
+ }
+ }
+ else //is maxmal
+ for(temp = cusp->getNext(); temp != cusp; temp = temp->getNext())
+ {
+ if(compV2InX(cusp->head(), temp->head()) == -1)
+ {
+ return temp;
+ }
+ }
+ return NULL;
+}
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.h
new file mode 100644
index 000000000..69f2b2df2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.h
@@ -0,0 +1,54 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _PARTITIONX_H
+#define _PARTITIONX_H
+
+#include "directedLine.h"
+
+Int isCuspX(directedLine *v);
+Int isReflexX(directedLine *v);
+Int cuspTypeX(directedLine *v);
+
+//assuming the array of ret_interior_cusps has been allocated
+void findInteriorCuspsX(directedLine* polygon, Int& ret_n_interior_cusps,
+ directedLine** ret_interior_cusps);
+
+Int numInteriorCuspsX(directedLine* polygon);
+
+/*a single polygon with a single cusp
+ *return the diagonal vertex corresponding to this cusp
+ */
+directedLine* findDiagonal_singleCuspX(directedLine* cusp);
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.cc
new file mode 100644
index 000000000..297c62997
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.cc
@@ -0,0 +1,836 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "zlassert.h"
+#include "partitionY.h"
+#include "searchTree.h"
+#include "quicksort.h"
+#include "polyUtil.h"
+
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+
+/*retrurn
+ *-1: if A < B (Ya<Yb) || (Ya==Yb)
+ * 0: if A == B
+ * 1: if A>B
+ */
+static Int compVertInY(Real A[2], Real B[2])
+{
+ if( (A[1] < B[1]) || (A[1]==B[1] && A[0]<B[0]))
+ return -1;
+ else if
+ ( A[1] == B[1] && A[0] == B[0]) return 0;
+ else
+ return 1;
+}
+
+/*v is a vertex: the head of en edge,
+ *e is an edge,
+ *return 1 if e is below v: assume v1 and v2 are the two endpoints of e:
+ * v1<= v, v2<=v.
+ */
+Int isBelow(directedLine *v, directedLine *e)
+{
+ Real* vert = v->head();
+ if( compVertInY(e->head(), vert) != 1
+ && compVertInY(e->tail(), vert) != 1
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*v is a vertex: the head of en edge,
+ *e is an edge,
+ *return 1 if e is below v: assume v1 and v2 are the two endpoints of e:
+ * v1>= v, v2>=v.
+ */
+Int isAbove(directedLine *v, directedLine *e)
+{
+ Real* vert = v->head();
+ if( compVertInY(e->head(), vert) != -1
+ && compVertInY(e->tail(), vert) != -1
+ )
+ return 1;
+ else
+ return 0;
+}
+
+Int isCusp(directedLine *v)
+{
+ Real *A=v->getPrev()->head();
+ Real *B=v->head();
+ Real *C=v->tail();
+ if(A[1] < B[1] && B[1] < C[1])
+ return 0;
+ else if(A[1] > B[1] && B[1] > C[1])
+ return 0;
+ else if(A[1] < B[1] && C[1] < B[1])
+ return 1;
+ else if(A[1] > B[1] && C[1] > B[1])
+ return 1;
+
+ if(isAbove(v, v) && isAbove(v, v->getPrev()) ||
+ isBelow(v, v) && isBelow(v, v->getPrev()))
+ return 1;
+ else
+ return 0;
+}
+
+/*crossproduct is strictly less than 0*/
+Int isReflex(directedLine *v)
+{
+ Real* A = v->getPrev()->head();
+ Real* B = v->head();
+ Real* C = v->tail();
+ Real Bx,By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+
+ if(Bx*Cy - Cx*By < 0) return 1;
+ else return 0;
+}
+
+ /*return
+ *0: not-cusp
+ *1: interior cusp
+ *2: exterior cusp
+ */
+Int cuspType(directedLine *v)
+{
+ if(! isCusp(v)) return 0;
+ else if(isReflex(v)) return 1;
+ else
+ return 2;
+}
+
+sweepRange* sweepRangeMake(directedLine* left, Int leftType,
+ directedLine* right, Int rightType)
+{
+ sweepRange* ret = (sweepRange*)malloc(sizeof(sweepRange));
+ assert(ret);
+ ret->left = left;
+ ret->leftType = leftType;
+ ret->right = right;
+ ret->rightType = rightType;
+ return ret;
+}
+
+void sweepRangeDelete(sweepRange* range)
+{
+ free(range);
+}
+
+Int sweepRangeEqual(sweepRange* src1, sweepRange* src2)
+{
+ Int leftEqual;
+ Int rightEqual;
+
+
+ /*The case when both are vertices should not happen*/
+ assert(! (src1->leftType == 0 && src2->leftType == 0));
+ if(src1->leftType == 0 && src2->leftType == 1){
+ if(src1->left == src2->left ||
+ src1->left->getPrev() == src2->left
+ )
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+ else if(src1->leftType == 1 && src2->leftType == 1){
+ if(src1->left == src2->left)
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+ else /*src1->leftType == 1 && src2->leftType == 0*/{
+ if(src1->left == src2->left ||
+ src1->left == src2->left->getPrev()
+ )
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+
+ /*the same thing for right*/
+ /*The case when both are vertices should not happen*/
+ assert(! (src1->rightType == 0 && src2->rightType == 0));
+ if(src1->rightType == 0 && src2->rightType == 1){
+ if(src1->right == src2->right ||
+ src1->right->getPrev() == src2->right
+ )
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+ else if(src1->rightType == 1 && src2->rightType == 1){
+ if(src1->right == src2->right)
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+ else /*src1->rightType == 1 && src2->rightType == 0*/{
+ if(src1->right == src2->right ||
+ src1->right == src2->right->getPrev()
+ )
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+
+ return (leftEqual == 1 || rightEqual == 1);
+}
+
+/*given (x_1, y_1) and (x_2, y_2), and y
+ *return x such that (x,y) is on the line
+ */
+inline/*static*/ Real intersectHoriz(Real x1, Real y1, Real x2, Real y2, Real y)
+{
+ return ((y2==y1)? (x1+x2)*Real(0.5) : x1 + ((y-y1)/(y2-y1)) * (x2-x1));
+/*
+ if(y2 == y1) return (x1+x2)*0.5;
+ else return x1 + ((y-y1)/(y2-y1)) * (x2-x1);
+*/
+}
+
+/*compare two edges of a polygon.
+ *edge A < edge B if there is a horizontal line so that the intersection
+ *with A is to the left of the intersection with B.
+ *This function is used in sweepY for the dynamic search tree insertion to
+ *order the edges.
+ * Implementation: (x_1,y_1) and (x_2, y_2)
+ */
+static Int compEdges(directedLine *e1, directedLine *e2)
+{
+ Real* head1 = e1->head();
+ Real* tail1 = e1->tail();
+ Real* head2 = e2->head();
+ Real* tail2 = e2->tail();
+/*
+ Real h10 = head1[0];
+ Real h11 = head1[1];
+ Real t10 = tail1[0];
+ Real t11 = tail1[1];
+ Real h20 = head2[0];
+ Real h21 = head2[1];
+ Real t20 = tail2[0];
+ Real t21 = tail2[1];
+*/
+ Real e1_Ymax, e1_Ymin, e2_Ymax, e2_Ymin;
+/*
+ if(h11>t11) {
+ e1_Ymax= h11;
+ e1_Ymin= t11;
+ }
+ else{
+ e1_Ymax = t11;
+ e1_Ymin = h11;
+ }
+
+ if(h21>t21) {
+ e2_Ymax= h21;
+ e2_Ymin= t21;
+ }
+ else{
+ e2_Ymax = t21;
+ e2_Ymin = h21;
+ }
+*/
+
+ if(head1[1]>tail1[1]) {
+ e1_Ymax= head1[1];
+ e1_Ymin= tail1[1];
+ }
+ else{
+ e1_Ymax = tail1[1];
+ e1_Ymin = head1[1];
+ }
+
+ if(head2[1]>tail2[1]) {
+ e2_Ymax= head2[1];
+ e2_Ymin= tail2[1];
+ }
+ else{
+ e2_Ymax = tail2[1];
+ e2_Ymin = head2[1];
+ }
+
+
+ /*Real e1_Ymax = max(head1[1], tail1[1]);*/ /*max(e1->head()[1], e1->tail()[1]);*/
+ /*Real e1_Ymin = min(head1[1], tail1[1]);*/ /*min(e1->head()[1], e1->tail()[1]);*/
+ /*Real e2_Ymax = max(head2[1], tail2[1]);*/ /*max(e2->head()[1], e2->tail()[1]);*/
+ /*Real e2_Ymin = min(head2[1], tail2[1]);*/ /*min(e2->head()[1], e2->tail()[1]);*/
+
+ Real Ymax = min(e1_Ymax, e2_Ymax);
+ Real Ymin = max(e1_Ymin, e2_Ymin);
+
+ Real y = Real(0.5)*(Ymax + Ymin);
+
+/* Real x1 = intersectHoriz(e1->head()[0], e1->head()[1], e1->tail()[0], e1->tail()[1], y);
+ Real x2 = intersectHoriz(e2->head()[0], e2->head()[1], e2->tail()[0], e2->tail()[1], y);
+*/
+/*
+ Real x1 = intersectHoriz(h10, h11, t10, t11, y);
+ Real x2 = intersectHoriz(h20, h21, t20, t21, y);
+*/
+ Real x1 = intersectHoriz(head1[0], head1[1], tail1[0], tail1[1], y);
+ Real x2 = intersectHoriz(head2[0], head2[1], tail2[0], tail2[1], y);
+
+ if(x1<= x2) return -1;
+ else return 1;
+}
+
+/*used by sort precedures
+ */
+static Int compInY(directedLine* v1, directedLine* v2)
+{
+ return v1->compInY(v2);
+}
+
+void findDiagonals(Int total_num_edges, directedLine** sortedVertices, sweepRange** ranges, Int& num_diagonals, directedLine** diagonal_vertices)
+{
+ Int i,j,k;
+
+ k=0;
+
+ for(i=0; i<total_num_edges; i++)
+ {
+ directedLine* vert =sortedVertices[i];
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+/*
+printf("find i=%i\n", i);
+printf("the vertex is\n");
+vert->printSingle();
+*/
+ if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge) && compEdges(prevEdge, thisEdge)<0)
+ {
+ /*this is an upward interior cusp*/
+ diagonal_vertices[k++] = vert;
+
+ for(j=i+1; j<total_num_edges; j++)
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ diagonal_vertices[k++] = sortedVertices[j];
+ break;
+ }
+ assert(j<total_num_edges);
+
+
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge) && compEdges(prevEdge, thisEdge)>0)
+ {
+ /*this is an downward interior cusp*/
+ diagonal_vertices[k++] = vert;
+ for(j=i-1; j>=0; j--)
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ diagonal_vertices[k++] = sortedVertices[j];
+ break;
+ }
+/* printf("j=%i\n", j);*/
+ assert(j>=0);
+
+
+
+ }
+ }
+ num_diagonals = k/2;
+}
+
+/*get rid of repeated diagonlas so that each diagonal appears only once in the array
+ */
+Int deleteRepeatDiagonals(Int num_diagonals, directedLine** diagonal_vertices, directedLine** new_vertices)
+{
+ Int i,k;
+ Int j,l;
+ Int index;
+ index=0;
+ for(i=0,k=0; i<num_diagonals; i++, k+=2)
+ {
+ Int isRepeated=0;
+ /*check the diagonla (diagonal_vertice[k], diagonal_vertices[k+1])
+ *is repeated or not
+ */
+ for(j=0,l=0; j<index; j++, l+=2)
+ {
+ if(
+ (diagonal_vertices[k] == new_vertices[l] &&
+ diagonal_vertices[k+1] == new_vertices[l+1]
+ )
+ ||
+ (
+ diagonal_vertices[k] == new_vertices[l+1] &&
+ diagonal_vertices[k+1] == new_vertices[l]
+ )
+ )
+ {
+ isRepeated=1;
+ break;
+ }
+ }
+ if(! isRepeated)
+ {
+ new_vertices[index+index] = diagonal_vertices[k];
+ new_vertices[index+index+1] = diagonal_vertices[k+1];
+ index++;
+ }
+ }
+ return index;
+}
+
+/*for debug only*/
+directedLine** DBGfindDiagonals(directedLine *polygons, Int& num_diagonals)
+{
+ Int total_num_edges = 0;
+ directedLine** array = polygons->toArrayAllPolygons(total_num_edges);
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void*, void*)) compInY);
+ sweepRange** ranges = (sweepRange**) malloc(sizeof(sweepRange*) * total_num_edges);
+ assert(ranges);
+
+ sweepY(total_num_edges, array, ranges);
+
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges);
+ assert(diagonal_vertices);
+ findDiagonals(total_num_edges, array, ranges, num_diagonals, diagonal_vertices);
+
+ num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+ return diagonal_vertices;
+
+}
+
+
+/*partition into Y-monotone polygons*/
+directedLine* partitionY(directedLine *polygons, sampledLine **retSampledLines)
+{
+ Int total_num_edges = 0;
+ directedLine** array = polygons->toArrayAllPolygons(total_num_edges);
+
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void*, void*)) compInY);
+
+ sweepRange** ranges = (sweepRange**) malloc(sizeof(sweepRange*) * (total_num_edges));
+ assert(ranges);
+
+
+
+ sweepY(total_num_edges, array, ranges);
+
+
+
+ /*the diagonal vertices are stored as:
+ *v0-v1: 1st diagonal
+ *v2-v3: 2nd diagonal
+ *v5-v5: 3rd diagonal
+ *...
+ */
+
+
+ Int num_diagonals;
+ /*number diagonals is < total_num_edges*total_num_edges*/
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges*2/*total_num_edges*/);
+ assert(diagonal_vertices);
+
+
+
+ findDiagonals(total_num_edges, array, ranges, num_diagonals, diagonal_vertices);
+
+
+
+ directedLine* ret_polygons = polygons;
+ sampledLine* newSampledLines = NULL;
+ Int i,k;
+
+num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+
+
+
+ Int *removedDiagonals=(Int*)malloc(sizeof(Int) * num_diagonals);
+ for(i=0; i<num_diagonals; i++)
+ removedDiagonals[i] = 0;
+
+
+
+
+
+ for(i=0,k=0; i<num_diagonals; i++,k+=2)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+/*
+ directedLine *root1 = v1->findRoot();
+ directedLine *root2 = v2->findRoot();
+ assert(root1);
+ assert(root2);
+*/
+
+directedLine* root1 = v1->rootLinkFindRoot();
+directedLine* root2 = v2->rootLinkFindRoot();
+
+ if(root1 != root2)
+ {
+
+ removedDiagonals[i] = 1;
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+
+
+
+ newSampledLines = generatedLine->insert(newSampledLines);
+/*
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+root1->rootLinkSet(ret_p1);
+root2->rootLinkSet(ret_p1);
+ret_p1->rootLinkSet(NULL);
+ret_p2->rootLinkSet(ret_p1);
+*/
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+
+
+
+root2->rootLinkSet(root1);
+ret_p1->rootLinkSet(root1);
+ret_p2->rootLinkSet(root1);
+
+ /*now that we have connected the diagonal v1 and v2,
+ *we have to check those unprocessed diagonals which
+ *have v1 or v2 as an end point. Notice that the head of v1
+ *has the same coodinates as the head of v2->prev, and the head of
+ *v2 has the same coordinate as the head of v1->prev.
+ *Suppose these is a diagonal (v1, x). If (v1,x) is still a valid
+ *diagonal, then x should be on the left hand side of the directed line: *v1->prev->head -- v1->head -- v1->tail. Otherwise, (v1,x) should be
+ *replaced by (v2->prev, x), that is, x is on the left of
+ * v2->prev->prev->head, v2->prev->head, v2->prev->tail.
+ */
+ Int ii, kk;
+ for(ii=0, kk=0; ii<num_diagonals; ii++, kk+=2)
+ if( removedDiagonals[ii]==0)
+ {
+ directedLine* d1=diagonal_vertices[kk];
+ directedLine* d2=diagonal_vertices[kk+1];
+ /*check d1, and replace diagonal_vertices[kk] if necessary*/
+ if(d1 == v1) {
+ /*check if d2 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v2->getPrev();
+ }
+ }
+ if(d1 == v2) {
+ /*check if d2 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v1->getPrev();
+ }
+ }
+ /*check d2 and replace diagonal_vertices[k+1] if necessary*/
+ if(d2 == v1) {
+ /*check if d1 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v2->getPrev();
+ }
+ }
+ if(d2 == v2) {
+ /*check if d1 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v1->getPrev();
+ }
+ }
+ }
+}/*end if (root1 not equal to root 2)*/
+}
+
+ /*second pass, now all diagoals should belong to the same polygon*/
+
+
+
+ for(i=0,k=0; i<num_diagonals; i++, k += 2)
+ if(removedDiagonals[i] == 0)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+
+
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+ directedLine *root1 = v1->findRoot();
+/*
+ directedLine *root2 = v2->findRoot();
+
+
+
+ assert(root1);
+ assert(root2);
+ assert(root1 == root2);
+ */
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+ newSampledLines = generatedLine->insert(newSampledLines);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+
+ ret_polygons = ret_p2->insertPolygon(ret_polygons);
+
+
+
+ for(Int j=i+1; j<num_diagonals; j++)
+ {
+ if(removedDiagonals[j] ==0)
+ {
+
+ directedLine* temp1=diagonal_vertices[2*j];
+ directedLine* temp2=diagonal_vertices[2*j+1];
+ if(temp1==v1 || temp1==v2 || temp2==v1 || temp2==v2)
+ if(! temp1->samePolygon(temp1, temp2))
+ {
+ /*if temp1 and temp2 are in different polygons,
+ *then one of them must be v1 or v2.
+ */
+
+
+
+ assert(temp1==v1 || temp1 == v2 || temp2==v1 || temp2 ==v2);
+ if(temp1==v1)
+ {
+ diagonal_vertices[2*j] = v2->getPrev();
+ }
+ if(temp2==v1)
+ {
+ diagonal_vertices[2*j+1] = v2->getPrev();
+ }
+ if(temp1==v2)
+ {
+ diagonal_vertices[2*j] = v1->getPrev();
+ }
+ if(temp2==v2)
+ {
+ diagonal_vertices[2*j+1] = v1->getPrev();
+ }
+ }
+ }
+ }
+
+ }
+
+ /*clean up spaces*/
+ free(array);
+ free(ranges);
+ free(diagonal_vertices);
+ free(removedDiagonals);
+
+ *retSampledLines = newSampledLines;
+ return ret_polygons;
+}
+
+/*given a set of simple polygons where the interior
+ *is decided by left-hand principle,
+ *return a range (sight) for each vertex. This is called
+ *Trapezoidalization.
+ */
+void sweepY(Int nVertices, directedLine** sortedVertices, sweepRange** ret_ranges)
+{
+ Int i;
+ /*for each vertex in the sorted list, update the binary search tree.
+ *and store the range information for each vertex.
+ */
+ treeNode* searchTree = NULL;
+ for(i=0; i<nVertices;i++)
+ {
+
+ directedLine* vert = sortedVertices[i];
+
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+
+ if(isBelow(vert, thisEdge) && isAbove(vert, prevEdge))
+ {
+
+ /*case 1: this < v < prev
+ *the polygon is going down at v, the interior is to
+ *the right hand side.
+ * find the edge to the right of thisEdge for right range.
+ * delete thisEdge
+ * insert prevEdge
+ */
+ treeNode* thisNode = TreeNodeFind(searchTree, thisEdge, ( Int (*) (void *, void *))compEdges);
+ assert(thisNode);
+
+ treeNode* succ = TreeNodeSuccessor(thisNode);
+ assert(succ);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeInsert(searchTree, TreeNodeMake(prevEdge), ( Int (*) (void *, void *))compEdges);
+
+
+ ret_ranges[i] = sweepRangeMake(vert, 0, (directedLine*) (succ->key), 1);
+
+ }
+ else if(isAbove(vert, thisEdge) && isBelow(vert, prevEdge))
+ {
+
+ /*case 2: this > v > prev
+ *the polygon is going up at v, the interior is to
+ *the left hand side.
+ * find the edge to the left of thisEdge for left range.
+ * delete prevEdge
+ * insert thisEdge
+ */
+ treeNode* prevNode = TreeNodeFind(searchTree, prevEdge, ( Int (*) (void *, void *))compEdges);
+ assert(prevNode);
+ treeNode* pred = TreeNodePredecessor(prevNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+ searchTree = TreeNodeInsert(searchTree, TreeNodeMake(thisEdge), ( Int (*) (void *, void *))compEdges);
+ ret_ranges[i] = sweepRangeMake((directedLine*)(pred->key), 1, vert, 0);
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge))
+ {
+
+ /*case 3: insert both edges*/
+ treeNode* thisNode = TreeNodeMake(thisEdge);
+ treeNode* prevNode = TreeNodeMake(prevEdge);
+ searchTree = TreeNodeInsert(searchTree, thisNode, ( Int (*) (void *, void *))compEdges);
+ searchTree = TreeNodeInsert(searchTree, prevNode, ( Int (*) (void *, void *))compEdges);
+ if(compEdges(thisEdge, prevEdge)<0) /*interior cusp*/
+ {
+
+ treeNode* leftEdge = TreeNodePredecessor(thisNode);
+ treeNode* rightEdge = TreeNodeSuccessor(prevNode);
+ ret_ranges[i] = sweepRangeMake( (directedLine*) leftEdge->key, 1,
+ (directedLine*) rightEdge->key, 1
+ );
+ }
+ else /*exterior cusp*/
+ {
+
+ ret_ranges[i] = sweepRangeMake( prevEdge, 1, thisEdge, 1);
+ }
+ }
+ else if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge))
+ {
+
+ /*case 4: delete both edges*/
+ treeNode* thisNode = TreeNodeFind(searchTree, thisEdge, ( Int (*) (void *, void *))compEdges);
+ treeNode* prevNode = TreeNodeFind(searchTree, prevEdge, ( Int (*) (void *, void *))compEdges);
+ if(compEdges(thisEdge, prevEdge)>0) /*interior cusp*/
+ {
+ treeNode* leftEdge = TreeNodePredecessor(prevNode);
+ treeNode* rightEdge = TreeNodeSuccessor(thisNode);
+ ret_ranges[i] = sweepRangeMake( (directedLine*) leftEdge->key, 1,
+ (directedLine*) rightEdge->key, 1
+ );
+ }
+ else /*exterior cusp*/
+ {
+ ret_ranges[i] = sweepRangeMake( thisEdge, 1, prevEdge, 1);
+ }
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+ }
+ else
+ {
+ fprintf(stderr,"error in partitionY.C, invalid case\n");
+ printf("vert is\n");
+ vert->printSingle();
+ printf("thisEdge is\n");
+ thisEdge->printSingle();
+ printf("prevEdge is\n");
+ prevEdge->printSingle();
+
+ exit(1);
+ }
+ }
+
+ /*finaly clean up space: delete the search tree*/
+ TreeNodeDeleteWholeTree(searchTree);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.h
new file mode 100644
index 000000000..8dda409de
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.h
@@ -0,0 +1,97 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+ *partitionY.h:
+ *partition a polygon into a Y-monotone polygon:
+ * A polygon is Y-monotone if the boundary can be split into two polygon chains
+ *A and B such that each chain is Y-monotonic that is the intersection of any
+ *horizontal line intersects each chain has at most one connected componenets
+ * (empty, single point or a single line).
+ *
+ * A vertex is a cusp if both its ajacent vertices are either at or above v,
+ *or both at or below v. In addition, at least one of the ajacent verteces is
+ *strictly below or above v.
+ * A vertex is a relex vertex if the internals angle is strictly greater than
+ *180. In other words, if the the signed area is negative:
+ *(x1, y1), (x2, y2), (x3, y3) are the three vertices along a polygon, the
+ *order is such that left hand side is inside the polygon. Then (x2,y2) is
+ *reflex if:
+ * (x2-x1, y2-y1) cross (x3-x1, y3-y1) <0.
+ *A vertex is an interior cusp if it is a cusp and a reflex.
+ *A vertex is an exterior cusp if it is a cusp but not a reflex.
+ *
+ */
+
+#ifndef _PARTITIONY_H
+#define _PARTITIONY_H
+
+#include "directedLine.h"
+
+/*whether an edge is below a vertex*/
+Int isBelow(directedLine *v, directedLine *e);
+
+/*whether an edge is above a vertex*/
+Int isAbove(directedLine *v, directedLine *e);
+
+/*not-cusp,
+ *inerior cusp
+ *exterior cusp
+ */
+Int cuspType(directedLine *v);
+
+/*used in trapezoidalization*/
+typedef struct sweepRange{
+ directedLine *left;
+ Int leftType; /*either a vertex (leftType=0) or an edge (leftType =1) */
+ directedLine *right;
+ Int rightType; /*either a vertex (rightType=0) or an edge (rightType =1) */
+} sweepRange;
+
+sweepRange* sweepRangeMake(directedLine* left, Int leftType,
+ directedLine* right, Int rightType);
+
+void sweepRangeDelete(sweepRange* range);
+Int sweepRangeEqual(sweepRange* sr1, sweepRange* sr2);
+
+/*given a set of simple polygons where the interior
+ *is decided by left-hand principle,
+ *return a range (sight) for each vertex. This is called
+ *Trapezoidalization.
+ */
+void sweepY(Int nVertices, directedLine **sortedVerteces, sweepRange** ret_ranges);
+
+
+directedLine* partitionY(directedLine *polygons, sampledLine **retSampledLines);
+
+void findDiagonals(Int total_num_edges, directedLine** sortedVertices, sweepRange** ranges, Int& num_diagonals, directedLine** diagonal_vertices);
+
+directedLine** DBGfindDiagonals(directedLine *polygons, Int& num_diagonals);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc
new file mode 100644
index 000000000..4d04df73f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc
@@ -0,0 +1,734 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "zlassert.h"
+#include "polyDBG.h"
+
+#ifdef __WATCOMC__
+#pragma warning 14 10
+#pragma warning 391 10
+#pragma warning 726 10
+#endif
+
+static Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+}
+
+Int DBG_isConvex(directedLine *poly)
+{
+ directedLine* temp;
+ if(area(poly->head(), poly->tail(), poly->getNext()->tail()) < 0.00000)
+ return 0;
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ if(area(temp->head(), temp->tail(), temp->getNext()->tail()) < 0.00000)
+ return 0;
+ }
+ return 1;
+}
+
+Int DBG_is_U_monotone(directedLine* poly)
+{
+ Int n_changes = 0;
+ Int prev_sign;
+ Int cur_sign;
+ directedLine* temp;
+ cur_sign = compV2InX(poly->tail(), poly->head());
+
+ n_changes = (compV2InX(poly->getPrev()->tail(), poly->getPrev()->head())
+ != cur_sign);
+
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ prev_sign = cur_sign;
+ cur_sign = compV2InX(temp->tail(), temp->head());
+
+ if(cur_sign != prev_sign)
+ n_changes++;
+ }
+
+ if(n_changes ==2) return 1;
+ else return 0;
+}
+
+/*if u-monotone, and there is a long horizontal edge*/
+Int DBG_is_U_direction(directedLine* poly)
+{
+/*
+ if(! DBG_is_U_monotone(poly))
+ return 0;
+*/
+ Int V_count = 0;
+ Int U_count = 0;
+ directedLine* temp;
+ if( fabs(poly->head()[0] - poly->tail()[0]) <= fabs(poly->head()[1]-poly->tail()[1]))
+ V_count += poly->get_npoints();
+ else
+ U_count += poly->get_npoints();
+ /*
+ else if(poly->head()[1] == poly->tail()[1])
+ U_count += poly->get_npoints();
+ */
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ if( fabs(temp->head()[0] - temp->tail()[0]) <= fabs(temp->head()[1]-temp->tail()[1]))
+ V_count += temp->get_npoints();
+ else
+ U_count += temp->get_npoints();
+ /*
+ if(temp->head()[0] == temp->tail()[0])
+ V_count += temp->get_npoints();
+ else if(temp->head()[1] == temp->tail()[1])
+ U_count += temp->get_npoints();
+ */
+ }
+
+ if(U_count > V_count) return 1;
+ else return 0;
+}
+
+/*given two line segments, determine whether
+ *they intersect each other or not.
+ *return 1 if they do,
+ *return 0 otherwise
+ */
+Int DBG_edgesIntersect(directedLine* l1, directedLine* l2)
+{
+ if(l1->getNext() == l2)
+ {
+ if(area(l1->head(), l1->tail(), l2->tail()) == 0) //colinear
+ {
+ if( (l1->tail()[0] - l1->head()[0])*(l2->tail()[0]-l2->head()[0]) +
+ (l1->tail()[1] - l1->head()[1])*(l2->tail()[1]-l2->head()[1]) >=0)
+ return 0; //not intersect
+ else
+ return 1;
+ }
+ //else we use the normal code
+ }
+ else if(l1->getPrev() == l2)
+ {
+ if(area(l2->head(), l2->tail(), l1->tail()) == 0) //colinear
+ {
+ if( (l2->tail()[0] - l2->head()[0])*(l1->tail()[0]-l1->head()[0]) +
+ (l2->tail()[1] - l2->head()[1])*(l1->tail()[1]-l1->head()[1]) >=0)
+ return 0; //not intersect
+ else
+ return 1;
+ }
+ //else we use the normal code
+ }
+ else //the two edges are not connected
+ {
+ if((l1->head()[0] == l2->head()[0] &&
+ l1->head()[1] == l2->head()[1]) ||
+ (l1->tail()[0] == l2->tail()[0] &&
+ l1->tail()[1] == l2->tail()[1]))
+ return 1;
+
+ }
+
+
+ if(
+ (
+ area(l1->head(), l1->tail(), l2->head())
+ *
+ area(l1->head(), l1->tail(), l2->tail())
+ < 0
+ )
+ &&
+ (
+ area(l2->head(), l2->tail(), l1->head())
+ *area(l2->head(), l2->tail(), l1->tail())
+ < 0
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*whether AB and CD intersect
+ *return 1 if they do
+ *retur 0 otheriwse
+ */
+Int DBG_edgesIntersectGen(Real A[2], Real B[2], Real C[2], Real D[2])
+{
+ if(
+ (
+ area(A, B, C) * area(A,B,D) <0
+ )
+ &&
+ (
+ area(C,D,A) * area(C,D,B) < 0
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*determien whether (A,B) interesect chain[start] to [end]
+ */
+Int DBG_intersectChain(vertexArray* chain, Int start, Int end, Real A[2], Real B[2])
+{
+ Int i;
+ for(i=start; i<=end-2; i++)
+ if(DBG_edgesIntersectGen(chain->getVertex(i), chain->getVertex(i+1), A, B))
+ return 1;
+
+ return 0;
+}
+
+/*determine whether a polygon intersect itself or not
+ *return 1 is it does,
+ * 0 otherwise
+ */
+Int DBG_polygonSelfIntersect(directedLine* poly)
+{
+ directedLine* temp1;
+ directedLine* temp2;
+ temp1=poly;
+ for(temp2=temp1->getNext(); temp2 != temp1; temp2=temp2->getNext())
+ {
+ if(DBG_edgesIntersect(temp1, temp2))
+ {
+ return 1;
+ }
+
+ }
+
+ for(temp1=poly->getNext(); temp1 != poly; temp1 = temp1->getNext())
+ for(temp2=temp1->getNext(); temp2 != temp1; temp2=temp2->getNext())
+ {
+ if(DBG_edgesIntersect(temp1, temp2))
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*check whether a line segment intersects a polygon
+ */
+Int DBG_edgeIntersectPoly(directedLine* edge, directedLine* poly)
+{
+ directedLine* temp;
+ if(DBG_edgesIntersect(edge, poly))
+ return 1;
+ for(temp=poly->getNext(); temp != poly; temp=temp->getNext())
+ if(DBG_edgesIntersect(edge, temp))
+ return 1;
+ return 0;
+}
+
+/*check whether two polygons intersect
+ */
+Int DBG_polygonsIntersect(directedLine* p1, directedLine* p2)
+{
+ directedLine* temp;
+ if(DBG_edgeIntersectPoly(p1, p2))
+ return 1;
+ for(temp=p1->getNext(); temp!= p1; temp = temp->getNext())
+ if(DBG_edgeIntersectPoly(temp, p2))
+ return 1;
+ return 0;
+}
+
+/*check whether there are polygons intersecting each other in
+ *a list of polygons
+ */
+Int DBG_polygonListIntersect(directedLine* pList)
+{
+ directedLine *temp;
+ for(temp=pList; temp != NULL; temp = temp->getNextPolygon())
+ if(DBG_polygonSelfIntersect(temp))
+ return 1;
+ directedLine* temp2;
+ for(temp=pList; temp!=NULL; temp=temp->getNextPolygon())
+ {
+ for(temp2=temp->getNextPolygon(); temp2 != NULL; temp2=temp2->getNextPolygon())
+ if(DBG_polygonsIntersect(temp, temp2))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+Int DBG_isCounterclockwise(directedLine* poly)
+{
+ return (poly->polyArea() > 0);
+}
+
+/*ray: v0 with direction (dx,dy).
+ *edge: v1-v2.
+ * the extra point v10[2] is given for the information at
+ *v1. Basically this edge is connectd to edge
+ * v10-v1. If v1 is on the ray,
+ * then we need v10 to determine whether this ray intersects
+ * the edge or not (that is, return 1 or return 0).
+ * If v1 is on the ray, then if v2 and v10 are on the same side of the ray,
+ * we return 0, otherwise return 1.
+ *For v2, if v2 is on the ray, we always return 0.
+ *Notice that v1 and v2 are not symmetric. So the edge is directed!!!
+ * The purpose for this convention is such that: a point is inside a polygon
+ * if and only if it intersets with odd number of edges.
+ */
+Int DBG_rayIntersectEdge(Real v0[2], Real dx, Real dy, Real v10[2], Real v1[2], Real v2[2])
+{
+/*
+if( (v1[1] >= v0[1] && v2[1]<= v0[1] )
+ ||(v2[1] >= v0[1] && v1[1]<= v0[1] )
+ )
+ printf("rayIntersectEdge, *********\n");
+*/
+
+ Real denom = (v2[0]-v1[0])*(-dy) - (v2[1]-v1[1]) * (-dx);
+ Real nomRay = (v2[0]-v1[0]) * (v0[1] - v1[1]) - (v2[1]-v1[1])*(v0[0]-v1[0]);
+ Real nomEdge = (v0[0]-v1[0]) * (-dy) - (v0[1]-v1[1])*(-dx);
+
+
+ /*if the ray is parallel to the edge, return 0: not intersect*/
+ if(denom == 0.0)
+ return 0;
+
+ /*if v0 is on the edge, return 0: not intersect*/
+ if(nomRay == 0.0)
+ return 0;
+
+ /*if v1 is on the positive ray, and the neighbor of v1 crosses the ray
+ *return 1: intersect
+ */
+ if(nomEdge == 0)
+ { /*v1 is on the positive or negative ray*/
+
+/*
+ printf("v1 is on the ray\n");
+*/
+
+ if(dx*(v1[0]-v0[0])>=0 && dy*(v1[1]-v0[1])>=0) /*v1 on positive ray*/
+ {
+ if(area(v0, v1, v10) * area(v0, v1, v2) >0)
+ return 0;
+ else
+ return 1;
+ }
+ else /*v1 on negative ray*/
+ return 0;
+ }
+
+ /*if v2 is on the ray, always return 0: not intersect*/
+ if(nomEdge == denom) {
+/* printf("v2 is on the ray\n");*/
+ return 0;
+ }
+
+ /*finally */
+ if(denom*nomRay>0 && denom*nomEdge>0 && nomEdge/denom <=1.0)
+ return 1;
+ return 0;
+}
+
+
+/*return the number of intersections*/
+Int DBG_rayIntersectPoly(Real v0[2], Real dx, Real dy, directedLine* poly)
+{
+ directedLine* temp;
+ Int count=0;
+ if(DBG_rayIntersectEdge(v0, dx, dy, poly->getPrev()->head(), poly->head(), poly->tail()))
+ count++;
+
+ for(temp=poly->getNext(); temp != poly; temp = temp->getNext())
+ if(DBG_rayIntersectEdge(v0, dx, dy, temp->getPrev()->head(), temp->head(), temp->tail()))
+ count++;
+/*printf("ray intersect poly: count=%i\n", count);*/
+ return count;
+}
+
+Int DBG_pointInsidePoly(Real v[2], directedLine* poly)
+{
+/*
+printf("enter pointInsidePoly , v=(%f,%f)\n", v[0], v[1]);
+printf("the polygon is\n");
+poly->printList();
+*/
+ /*for debug purpose*/
+ assert( (DBG_rayIntersectPoly(v,1,0,poly) % 2 )
+ == (DBG_rayIntersectPoly(v,1,Real(0.1234), poly) % 2 )
+ );
+ if(DBG_rayIntersectPoly(v, 1, 0, poly) % 2 == 1)
+ return 1;
+ else
+ return 0;
+}
+
+/*return the number of polygons which contain thie polygon
+ * as a subset
+ */
+Int DBG_enclosingPolygons(directedLine* poly, directedLine* list)
+{
+ directedLine* temp;
+ Int count=0;
+/*
+printf("%i\n", DBG_pointInsidePoly(poly->head(),
+ list->getNextPolygon()
+ ->getNextPolygon()
+ ->getNextPolygon()
+ ->getNextPolygon()
+));
+*/
+
+ for(temp = list; temp != NULL; temp = temp->getNextPolygon())
+ {
+ if(poly != temp)
+ if(DBG_pointInsidePoly(poly->head(), temp))
+ count++;
+/* printf("count=%i\n", count);*/
+ }
+ return count;
+}
+
+void DBG_reverse(directedLine* poly)
+{
+ if(poly->getDirection() == INCREASING)
+ poly->putDirection(DECREASING);
+ else
+ poly->putDirection(INCREASING);
+
+ directedLine* oldNext = poly->getNext();
+ poly->putNext(poly->getPrev());
+ poly->putPrev(oldNext);
+
+ directedLine* temp;
+ for(temp=oldNext; temp!=poly; temp = oldNext)
+ {
+ if(temp->getDirection() == INCREASING)
+ temp->putDirection(DECREASING);
+ else
+ temp->putDirection(INCREASING);
+
+ oldNext = temp->getNext();
+ temp->putNext(temp->getPrev());
+ temp->putPrev(oldNext);
+ }
+ printf("reverse done\n");
+}
+
+Int DBG_checkConnectivity(directedLine *polygon)
+{
+ if(polygon == NULL) return 1;
+ directedLine* temp;
+ if(polygon->head()[0] != polygon->getPrev()->tail()[0] ||
+ polygon->head()[1] != polygon->getPrev()->tail()[1])
+ return 0;
+ for(temp=polygon->getNext(); temp != polygon; temp=temp->getNext())
+ {
+ if(temp->head()[0] != temp->getPrev()->tail()[0] ||
+ temp->head()[1] != temp->getPrev()->tail()[1])
+ return 0;
+ }
+ return 1;
+}
+
+/*print out error message.
+ *If it cannot modify the polygon list to make it satify the
+ *requirements, return 1.
+ *otherwise modify the polygon list, and return 0
+ */
+Int DBG_check(directedLine *polyList)
+{
+ directedLine* temp;
+ if(polyList == NULL) return 0;
+
+ /*if there are intersections, print out error message
+ */
+ if(DBG_polygonListIntersect(polyList))
+ {
+ fprintf(stderr, "DBG_check: there are self intersections, don't know to modify the polygons\n");
+ return 1;
+ }
+
+ /*check the connectivity of each polygon*/
+ for(temp = polyList; temp!= NULL; temp = temp ->getNextPolygon())
+ {
+ if(! DBG_checkConnectivity(temp))
+ {
+ fprintf(stderr, "DBG_check, polygon not connected\n");
+ return 1;
+ }
+ }
+
+ /*check the orientation of each polygon*/
+ for(temp = polyList; temp!= NULL; temp = temp ->getNextPolygon())
+ {
+
+
+ Int correctDir;
+
+ if( DBG_enclosingPolygons(temp, polyList) % 2 == 0)
+ correctDir = 1; /*counterclockwise*/
+ else
+ correctDir = 0; /*clockwise*/
+
+ Int actualDir = DBG_isCounterclockwise(temp);
+
+ if(correctDir != actualDir)
+ {
+ fprintf(stderr, "DBG_check: polygon with incorrect orientations. reversed\n");
+
+ DBG_reverse(temp);
+ }
+
+ }
+ return 0;
+}
+
+/**************handle self intersections*****************/
+//determine whether e interects [begin, end] or not
+static directedLine* DBG_edgeIntersectChainD(directedLine *e,
+ directedLine *begin, directedLine *end)
+{
+ directedLine *temp;
+ for(temp=begin; temp != end; temp = temp->getNext())
+ {
+ if(DBG_edgesIntersect(e, temp))
+ return temp;
+ }
+ if(DBG_edgesIntersect(e, end))
+ return end;
+ return NULL;
+}
+
+//given a polygon, cut the edges off and finally obtain a
+//a polygon without intersections. The cut-off edges are
+//dealloated. The new polygon is returned.
+directedLine* DBG_cutIntersectionPoly(directedLine *polygon, int& cutOccur)
+{
+ directedLine *begin, *end, *next;
+ begin = polygon;
+ end = polygon;
+ cutOccur = 0;
+ while( (next = end->getNext()) != begin)
+ {
+ directedLine *interc = NULL;
+ if( (interc = DBG_edgeIntersectChainD(next, begin, end)))
+ {
+ int fixed = 0;
+ if(DBG_edgesIntersect(next, interc->getNext()))
+ {
+ //trying to fix it
+ Real buf[2];
+ int i;
+ Int n=5;
+ buf[0] = interc->tail()[0];
+ buf[1] = interc->tail()[1];
+
+ for(i=1; i<n; i++)
+ {
+ Real r = ((Real)i) / ((Real) n);
+ Real u = (1-r) * interc->head()[0] + r * interc->tail()[0];
+ Real v = (1-r) * interc->head()[1] + r * interc->tail()[1];
+ interc->tail()[0] = interc->getNext()->head()[0] = u;
+ interc->tail()[1] = interc->getNext()->head()[1] = v;
+ if( (! DBG_edgesIntersect(next, interc)) &&
+ (! DBG_edgesIntersect(next, interc->getNext())))
+ break; //we fixed it
+ }
+ if(i==n) // we didn't fix it
+ {
+ fixed = 0;
+ //back to original
+ interc->tail()[0] = interc->getNext()->head()[0] = buf[0];
+ interc->tail()[1] = interc->getNext()->head()[1] = buf[1];
+ }
+ else
+ {
+ fixed = 1;
+ }
+ }
+ if(fixed == 0)
+ {
+ cutOccur = 1;
+ begin->deleteSingleLine(next);
+
+ if(begin != end)
+ {
+ if(DBG_polygonSelfIntersect(begin))
+ {
+ directedLine* newEnd = end->getPrev();
+ begin->deleteSingleLine(end);
+ end = newEnd;
+ }
+ }
+ }
+ else
+ {
+ end = end->getNext();
+ }
+ }
+ else
+ {
+ end = end->getNext();
+ }
+ }
+ return begin;
+}
+
+//given a polygon, cut the edges off and finally obtain a
+//a polygon without intersections. The cut-off edges are
+//dealloated. The new polygon is returned.
+#if 0 // UNUSED
+static directedLine* DBG_cutIntersectionPoly_notwork(directedLine *polygon)
+{
+ directedLine *crt;//current polygon
+ directedLine *begin;
+ directedLine *end;
+ directedLine *temp;
+ crt = polygon;
+ int find=0;
+ while(1)
+ {
+//printf("loop\n");
+ //if there are less than 3 edges, we should stop
+ if(crt->getPrev()->getPrev() == crt)
+ return NULL;
+
+ if(DBG_edgesIntersect(crt, crt->getNext()) ||
+ (crt->head()[0] == crt->getNext()->tail()[0] &&
+ crt->head()[1] == crt->getNext()->tail()[1])
+ )
+ {
+ find = 1;
+ crt=crt->deleteChain(crt, crt->getNext());
+ }
+ else
+ {
+ //now we know crt and crt->getNext do not intersect
+ begin = crt;
+ end = crt->getNext();
+//printf("begin=(%f,%f)\n", begin->head()[0], begin->head()[1]);
+//printf("end=(%f,%f)\n", end->head()[0], end->head()[1]);
+ for(temp=end->getNext(); temp!=begin; temp= temp->getNext())
+ {
+//printf("temp=(%f,%f)\n", temp->head()[0], temp->head()[1]);
+ directedLine *intersect = DBG_edgeIntersectChainD(temp, begin, end);
+ if(intersect != NULL)
+ {
+ crt = crt->deleteChain(intersect, temp);
+ find=1;
+ break; //the for loop
+ }
+ else
+ {
+ end = temp;
+ }
+ }
+ }
+ if(find == 0)
+ return crt;
+ else
+ find = 0; //go to next loop
+}
+}
+#endif
+
+directedLine* DBG_cutIntersectionAllPoly(directedLine* list)
+{
+ directedLine* temp;
+ directedLine* tempNext=NULL;
+ directedLine* ret = NULL;
+ int cutOccur=0;
+ for(temp=list; temp != NULL; temp = tempNext)
+ {
+ directedLine *left;
+ tempNext = temp->getNextPolygon();
+
+ left = DBG_cutIntersectionPoly(temp, cutOccur);
+ if(left != NULL)
+ ret=left->insertPolygon(ret);
+ }
+ return ret;
+}
+
+sampledLine* DBG_collectSampledLinesAllPoly(directedLine *polygonList)
+{
+ directedLine *temp;
+ sampledLine* tempHead = NULL;
+ sampledLine* tempTail = NULL;
+ sampledLine* cHead = NULL;
+ sampledLine* cTail = NULL;
+
+ if(polygonList == NULL)
+ return NULL;
+
+ DBG_collectSampledLinesPoly(polygonList, cHead, cTail);
+
+ assert(cHead);
+ assert(cTail);
+ for(temp = polygonList->getNextPolygon(); temp != NULL; temp = temp->getNextPolygon())
+ {
+ DBG_collectSampledLinesPoly(temp, tempHead, tempTail);
+ cTail->insert(tempHead);
+ cTail = tempTail;
+ }
+ return cHead;
+}
+
+void DBG_collectSampledLinesPoly(directedLine *polygon, sampledLine*& retHead, sampledLine*& retTail)
+{
+ directedLine *temp;
+ retHead = NULL;
+ retTail = NULL;
+ if(polygon == NULL)
+ return;
+
+ retHead = retTail = polygon->getSampledLine();
+ for(temp = polygon->getNext(); temp != polygon; temp=temp->getNext())
+ {
+ retHead = temp->getSampledLine()->insert(retHead);
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.h
new file mode 100644
index 000000000..74843d888
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.h
@@ -0,0 +1,68 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _POLYDBG_H
+#define _POLYDBG_H
+
+#include "definitions.h"
+#include "directedLine.h"
+#include "monoTriangulation.h"
+
+Int DBG_edgesIntersectGen(Real A[2], Real B[2], Real C[2], Real D[2]);
+Int DBG_intersectChain(vertexArray* chain, Int start, Int end, Real A[2], Real B[2]);
+
+
+Int DBG_edgesIntersect(directedLine* l1, directedLine* l2);
+Int DBG_polygonSelfIntersect(directedLine* poly);
+Int DBG_edgeIntersectPoly(directedLine* edge, directedLine* poly);
+Int DBG_polygonsIntersect(directedLine* p1, directedLine* p2);
+Int DBG_polygonListIntersect(directedLine* pList);
+
+Int DBG_isCounterclockwise(directedLine* poly);
+Int DBG_rayIntersectEdge(Real v0[2], Real dx, Real dy, Real v10[2], Real v1[2], Real v2[2]);
+Int DBG_pointInsidePoly(Real v[2], directedLine* poly);
+Int DBG_enclosingPolygons(directedLine* poly, directedLine* list);
+void DBG_reverse(directedLine* poly);
+Int DBG_check(directedLine *polyList);
+
+Int DBG_isConvex(directedLine *poly);
+Int DBG_is_U_direction(directedLine *poly);
+Int DBG_is_U_monotone(directedLine* poly);
+
+directedLine* DBG_cutIntersectionAllPoly(directedLine* list);
+directedLine* DBG_cutIntersectionPoly(directedLine *polygon, int& cutOccur);
+
+sampledLine* DBG_collectSampledLinesAllPoly(directedLine *polygonList);
+
+void DBG_collectSampledLinesPoly(directedLine *polygon, sampledLine*& retHead, sampledLine*& retTail);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc
new file mode 100644
index 000000000..f9a27f402
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc
@@ -0,0 +1,90 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "polyUtil.h"
+
+Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+
+/* return (B[0]-A[0])*(C[1]-A[1]) - (C[0]-A[0])*(B[1]-A[1]);*/
+}
+
+/*given a directed line A->B, and a point P,
+ *determine whether P is to the left of AB.
+ *the line A->B (imagine it has beedn extended both
+ *end to the infinity) divides the plan into two
+ *half planes. When we walk from A to B, one
+ *half is to the left and the other half is to the right.
+ *return 1 if P is to the left.
+ *if P is on AB, 0 is returned.
+ */
+Int pointLeftLine(Real A[2], Real B[2], Real P[2])
+{
+ if(area(A, B, P) >0) return 1;
+ else return 0;
+}
+
+/*given two directed line: A -> B -> C, and another point P.
+ *determine whether P is to the left hand side of A->B->C.
+ *Think of BA and BC extended as two rays. So that the plane is
+ * divided into two parts. One part is to the left we walk from A
+ *to B and to C, the other part is to the right.
+ * In order for P to be the left, P must be either to the left
+ *of
+ */
+Int pointLeft2Lines(Real A[2], Real B[2], Real C[2], Real P[2])
+{
+ Int C_left_AB = (area(A, B, C)>0);
+ Int P_left_AB = (area(A, B, P)>0);
+ Int P_left_BC = (area(B, C, P)>0);
+
+ if(C_left_AB)
+ {
+ return (P_left_AB && P_left_BC);
+ }
+ else
+ return (P_left_AB || P_left_BC);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.h
new file mode 100644
index 000000000..1ca2ebcc0
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.h
@@ -0,0 +1,47 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _POLYUTIL_H
+#define _POLYUTIL_H
+
+#include "definitions.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+Real area(Real A[2], Real B[2], Real C[2]);
+
+Int pointLeftLine(Real A[2], Real B[2], Real P[2]);
+Int pointLeft2Lines(Real A[2], Real B[2], Real C[2], Real P[2]);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc
new file mode 100644
index 000000000..26d05342f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc
@@ -0,0 +1,190 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <GL/gl.h>
+
+#include "primitiveStream.h"
+
+Int primStream::num_triangles()
+{
+ Int i;
+ Int ret=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ ret += lengths[i]-2;
+ }
+ return ret;
+}
+
+
+
+/*the begining of inserting a new primitive.
+ *reset counter to be 0.
+ */
+void primStream::begin()
+{
+ counter = 0;
+}
+
+void primStream::insert(Real u, Real v)
+{
+ /*if the space cannot hold u and v,
+ *we have to expand the array
+ */
+ if(index_vertices+1 >= size_vertices) {
+ Real* temp = (Real*) malloc (sizeof(Real) * (2*size_vertices + 2));
+ assert(temp);
+
+ /*copy*/
+ for(Int i=0; i<index_vertices; i++)
+ temp[i] = vertices[i];
+
+ free(vertices);
+ vertices = temp;
+ size_vertices = 2*size_vertices + 2;
+ }
+
+ vertices[index_vertices++] = u;
+ vertices[index_vertices++] = v;
+ counter++;
+}
+
+/*the end of a primitive.
+ *increase index_lengths
+ */
+void primStream::end(Int type)
+{
+ Int i;
+ /*if there is no vertex in this primitive,
+ *nothing needs to be done
+ */
+ if(counter == 0) return ;
+
+ if(index_lengths >= size_lengths){
+ Int* temp = (Int*) malloc(sizeof(Int) * (2*size_lengths + 2));
+ assert(temp);
+ Int* tempTypes = (Int*) malloc(sizeof(Int) * (2*size_lengths + 2));
+ assert(tempTypes);
+
+ /*copy*/
+ for(i=0; i<index_lengths; i++){
+ temp[i] = lengths[i];
+ tempTypes[i] = types[i];
+ }
+
+ free(lengths);
+ free(types);
+ lengths = temp;
+ types = tempTypes;
+ size_lengths = 2*size_lengths + 2;
+ }
+ lengths[index_lengths] = counter;
+ types[index_lengths] = type;
+ index_lengths++;
+}
+
+void primStream::print()
+{
+ Int i,j,k;
+ printf("index_lengths=%i,size_lengths=%i\n", index_lengths, size_lengths);
+ printf("index_vertices=%i,size_vertices=%i\n", index_vertices, size_vertices);
+ k=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ if(types[i] == PRIMITIVE_STREAM_FAN)
+ printf("primitive-FAN:\n");
+ else
+ printf("primitive-STRIP:\n");
+ for(j=0; j<lengths[i]; j++)
+ {
+ printf("(%f,%f) ", vertices[k], vertices[k+1]);
+ k += 2;
+ }
+ printf("\n");
+ }
+}
+
+primStream::primStream(Int sizeLengths, Int sizeVertices)
+{
+ lengths = (Int*)malloc (sizeof(Int) * sizeLengths);
+ assert(lengths);
+ types = (Int*)malloc (sizeof(Int) * sizeLengths);
+ assert(types);
+
+ vertices = (Real*) malloc(sizeof(Real) * sizeVertices);
+ assert(vertices);
+
+ index_lengths = 0;
+ index_vertices = 0;
+ size_lengths = sizeLengths;
+ size_vertices = sizeVertices;
+}
+
+primStream::~primStream()
+{
+ free(lengths);
+ free(types);
+ free(vertices);
+}
+
+void primStream::draw()
+{
+ Int i,j,k;
+ k=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ switch(types[i]){
+ case PRIMITIVE_STREAM_FAN:
+ glBegin(GL_TRIANGLE_FAN);
+ break;
+ case PRIMITIVE_STREAM_STRIP:
+ glBegin(GL_TRIANGLE_STRIP);
+ break;
+ }
+
+ for(j=0; j<lengths[i]; j++){
+ glVertex2fv(vertices+k);
+ k += 2;
+ }
+ glEnd();
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h
new file mode 100644
index 000000000..b4174f146
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h
@@ -0,0 +1,109 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+/*we do not use the constans GL_... so that this file is independent of
+ *<GL/gl.h>
+ */
+
+#ifndef _PRIMITIVE_STREAM_H
+#define _PRIMITIVE_STREAM_H
+
+enum {PRIMITIVE_STREAM_FAN, PRIMITIVE_STREAM_STRIP};
+
+#include "definitions.h"
+
+class primStream {
+ Int *lengths; /*length[i]=number of vertices of ith primitive*/
+ Int *types; /*each primive has a type: FAN or STREAM*/
+ Real *vertices; /*the size >= 2 * num_vertices, each vertex (u,v)*/
+
+ /*the following size information are used for dynamic arrays*/
+ Int index_lengths; /*the current available entry*/
+ Int size_lengths; /*the allocated size of the array: lengths*/
+ Int index_vertices;
+ Int size_vertices;
+
+ /*the vertex is inserted one by one. counter is used to
+ *count the number of vertices which have been inserted so far in
+ *the current primitive
+ */
+ Int counter;
+
+public:
+ primStream(Int sizeLengths, Int sizeVertices);
+ ~primStream();
+
+ Int get_n_prims() //num of primitives
+ {
+ return index_lengths;
+ }
+ Int get_type(Int i) //the type of ith primitive
+ {
+ return types[i];
+ }
+ Int get_length(Int i) //the length of the ith primitive
+ {
+ return lengths[i];
+ }
+ Real* get_vertices() {return vertices;}
+
+ /*the begining of inserting a new primitive.
+ *reset counter to be 0.
+ */
+ void begin();
+ void insert(Real u, Real v);
+ void insert(Real v[2]) {insert(v[0], v[1]);}
+ void end(Int type);
+
+ Int num_triangles();
+
+ void triangle(Real A[2], Real B[2], Real C[2])
+ {
+ begin();
+ insert(A);
+ insert(B);
+ insert(C);
+ end(PRIMITIVE_STREAM_FAN);
+ }
+ void print();
+ void draw(); /*using GL to draw the primitives*/
+};
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.cc
new file mode 100644
index 000000000..9d0b290b3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.cc
@@ -0,0 +1,77 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+static void swap(void *v[], int i, int j)
+{
+ void *temp;
+ temp = v[i];
+ v[i] = v[j];
+ v[j] = temp;
+}
+
+/*as an example to use this function to
+ *sort integers, you need to supply the function
+ *int comp(int *i1, int *i2)
+ *{
+ * if( *i1 < * i2) return -1;
+ * else return 1;
+ *}
+ *and an array of pointers to integers:
+ * int *v[100] (allocate space for where each v[i] points to).
+ *then you can call:
+ * quicksort( (void**)v, left, right, (int (*)(void *, void *))comp)
+ */
+void quicksort(void *v[], int left, int right,
+ int (*comp) (void *, void *))
+{
+ int i, last;
+ if(left >= right) /*do nothing if array contains */
+ return; /*fewer than two elements*/
+
+ swap(v, left, (left+right)/2);
+ last = left;
+ for(i=left+1; i<=right; i++)
+ if((*comp)(v[i], v[left])<0)
+ swap(v, ++last, i);
+ swap(v, left, last);
+ quicksort(v, left, last-1, comp);
+ quicksort(v, last+1, right, comp);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.h
new file mode 100644
index 000000000..3a8dcd6a2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.h
@@ -0,0 +1,42 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _QUICKSORT_H
+#define _QUICKSORT_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+void quicksort(void *v[], int left, int right,
+ int (*comp) (void *, void *));
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc
new file mode 100644
index 000000000..f457b1573
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc
@@ -0,0 +1,196 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "zlassert.h"
+#include <GL/gl.h>
+
+#include "rectBlock.h"
+
+rectBlock::rectBlock(gridBoundaryChain* left, gridBoundaryChain* right, Int beginVline, Int endVline)
+{
+ Int i;
+
+
+ upGridLineIndex = left->getVlineIndex(beginVline);
+
+ lowGridLineIndex = left->getVlineIndex(endVline);
+
+ Int n = upGridLineIndex-lowGridLineIndex+1; //number of grid lines
+ leftIndices = (Int*) malloc(sizeof(Int) * n);
+ assert(leftIndices);
+ rightIndices = (Int*) malloc(sizeof(Int) * n);
+ assert(rightIndices);
+ for(i=0; i<n; i++)
+ {
+
+ leftIndices[i] = left->getInnerIndex(i+beginVline);
+ rightIndices[i] = right->getInnerIndex(i+beginVline);
+ }
+}
+
+
+rectBlock::~rectBlock()
+{
+ free(leftIndices);
+ free(rightIndices);
+}
+
+void rectBlock::print()
+{
+ Int i;
+ printf("block:\n");
+ for(i=upGridLineIndex; i >= lowGridLineIndex; i--)
+ {
+ printf("gridline %i, (%i,%i)\n", i, leftIndices[upGridLineIndex-i], rightIndices[upGridLineIndex-i]);
+ }
+}
+
+
+
+void rectBlock::draw(Real* u_values, Real* v_values)
+{
+ Int i,j,k;
+ //upgrid line to bot grid line
+#ifdef DEBUG
+printf("upGridLineIndex=%i, lowGridLineIndex=%i\n", upGridLineIndex, lowGridLineIndex);
+#endif
+ for(k=0, i=upGridLineIndex; i > lowGridLineIndex; i--, k++)
+ {
+ glBegin(GL_QUAD_STRIP);
+
+ for(j=leftIndices[k+1]; j<= rightIndices[k+1]; j++)
+ {
+ glVertex2f(u_values[j], v_values[i]);
+ glVertex2f(u_values[j], v_values[i-1]);
+ }
+ glEnd();
+ }
+}
+
+
+Int rectBlock::num_quads()
+{
+ Int ret=0;
+ Int k,i;
+ for(k=0, i=upGridLineIndex; i>lowGridLineIndex; i--, k++)
+ {
+ ret += (rightIndices[k+1]-leftIndices[k+1]);
+ }
+ return ret;
+}
+
+Int rectBlockArray::num_quads()
+{
+ Int ret=0;
+ for(Int i=0; i<n_elements; i++)
+ ret += array[i]->num_quads();
+ return ret;
+}
+
+rectBlockArray::rectBlockArray(Int s)
+{
+ Int i;
+ n_elements = 0;
+ size = s;
+ array = (rectBlock**) malloc(sizeof(rectBlock*) * s);
+ assert(array);
+//initialization
+ for(i=0; i<s; i++)
+ array[i] = NULL;
+}
+
+rectBlockArray::~rectBlockArray()
+{
+ Int i;
+ for(i=0; i<size; i++)
+ {
+ if(array[i] != NULL)
+ delete array[i];
+ }
+ free(array);
+}
+
+//put to the end of the array, check the size
+void rectBlockArray::insert(rectBlock* newBlock)
+{
+ Int i;
+ if(n_elements == size) //full
+ {
+ rectBlock** temp = (rectBlock**) malloc(sizeof(rectBlock) * (2*size+1));
+ assert(temp);
+ //initialization
+ for(i=0; i<2*size+1; i++)
+ temp[i] = NULL;
+
+ for(i=0; i<n_elements; i++)
+ temp[i] = array[i];
+
+ free(array);
+ array = temp;
+ size = 2*size + 1;
+ }
+
+ array[n_elements++] = newBlock;
+}
+
+void rectBlockArray::print()
+{
+ Int i;
+ for(i=0; i<n_elements; i++)
+ array[i]->print();
+}
+
+void rectBlockArray::draw(Real* u_values, Real* v_values)
+{
+ Int i;
+ for(i=0; i<n_elements; i++)
+ array[i]->draw(u_values, v_values);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.h
new file mode 100644
index 000000000..8dbd7eb81
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.h
@@ -0,0 +1,82 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _RECTBLOCK_H
+#define _RECTBLOCK_H
+
+#include "definitions.h"
+#include "gridWrap.h"
+
+class rectBlock{
+ Int upGridLineIndex;
+ Int lowGridLineIndex;
+ Int* leftIndices; //up to bottome
+ Int* rightIndices; //up to bottom
+public:
+ //the arrays are copies.
+ rectBlock(gridBoundaryChain* left, gridBoundaryChain* right, Int beginVline, Int endVline);
+ ~rectBlock(); //free the two arrays
+
+ Int get_upGridLineIndex() {return upGridLineIndex;}
+ Int get_lowGridLineIndex() {return lowGridLineIndex;}
+ Int* get_leftIndices() {return leftIndices;}
+ Int* get_rightIndices() {return rightIndices;}
+
+ Int num_quads();
+
+ void print();
+ void draw(Real* u_values, Real* v_values);
+};
+
+
+class rectBlockArray{
+ rectBlock** array;
+ Int n_elements;
+ Int size;
+public:
+ rectBlockArray(Int s);
+ ~rectBlockArray();//delete avarything including the blocks
+
+ Int get_n_elements() {return n_elements;}
+ rectBlock* get_element(Int i) {return array[i];}
+ void insert(rectBlock* newBlock); //only take the pointer, not ther cotent
+
+ Int num_quads();
+
+ void print();
+ void draw(Real* u_values, Real* v_values);
+};
+
+
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc
new file mode 100644
index 000000000..861c71bb3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc
@@ -0,0 +1,371 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "sampleComp.h"
+#include "sampleCompTop.h"
+#include "sampleCompBot.h"
+#include "sampleCompRight.h"
+
+
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+void sampleConnectedComp(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ )
+{
+
+ sampleCompLeft(topVertex, botVertex,
+ leftChain,
+ leftStartIndex, leftEndIndex,
+ rightChain,
+ rightStartIndex, rightEndIndex,
+ leftGridChain,
+ gridIndex1,
+ gridIndex2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ pStream);
+
+
+ sampleCompRight(topVertex, botVertex,
+ leftChain,
+ leftStartIndex, leftEndIndex,
+ rightChain,
+ rightStartIndex,
+ rightEndIndex,
+ rightGridChain,
+ gridIndex1, gridIndex2,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+
+ sampleCompTop(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+
+ sampleCompBot(botVertex,
+ leftChain,
+ leftEndIndex,
+ rightChain,
+ rightEndIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex2,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+
+ //the center
+
+ rbArray->insert(new rectBlock(leftGridChain, rightGridChain, gridIndex1, gridIndex2));
+
+
+}
+
+/*notice that we need rightChain because the
+ *corners could be on the rightChain.
+ *here comp means component.
+ */
+void sampleCompLeft(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream)
+{
+ /*find out whether there is a trim vertex which is
+ *inbetween the top and bot grid lines or not.
+ */
+ Int midIndex1;
+ Int midIndex2;
+ Int gridMidIndex1 = 0, gridMidIndex2 = 0;
+ //midIndex1: array[i] <= v, array[i-1] > v
+ //midIndex2: array[i] >= v, array[i+1] < v
+ // v(gridMidIndex1) >= v(midindex1) > v(gridMidIndex1+1)
+ // v(gridMidIndex2-1) >= v(midIndex2) > v(gridMidIndex2) ??
+ midIndex1 = leftChain->findIndexBelowGen(
+ leftGridChain->get_v_value(gridIndex1),
+ leftStartIndex,
+ leftEndIndex);
+
+ midIndex2 = -1; /*initilization*/
+ if(midIndex1<= leftEndIndex && gridIndex1<gridIndex2)
+ if(leftChain->getVertex(midIndex1)[1] >= leftGridChain->get_v_value(gridIndex2))
+ {
+ midIndex2 = leftChain->findIndexAboveGen(
+ leftGridChain->get_v_value(gridIndex2),
+ midIndex1, //midIndex1 <= midIndex2.
+ leftEndIndex);
+ gridMidIndex1 = leftGridChain->lookfor(leftChain->getVertex(midIndex1)[1],
+ gridIndex1, gridIndex2);
+ gridMidIndex2 = 1+leftGridChain->lookfor(leftChain->getVertex(midIndex2)[1],
+ gridMidIndex1, gridIndex2);
+ }
+
+
+ /*to interprete the corner information*/
+ Real* cornerTop;
+ Real* cornerBot;
+ Int cornerLeftStart;
+ Int cornerLeftEnd;
+ Int cornerRightUpEnd;
+ Int cornerRightDownStart;
+ if(up_leftCornerWhere == 0) /*left corner is on left chain*/
+ {
+ cornerTop = leftChain->getVertex(up_leftCornerIndex);
+ cornerLeftStart = up_leftCornerIndex+1;
+ cornerRightUpEnd = -1; /*no right*/
+ }
+ else if(up_leftCornerWhere == 1) /*left corner is on top*/
+ {
+ cornerTop = topVertex;
+ cornerLeftStart = leftStartIndex;
+ cornerRightUpEnd = -1; /*no right*/
+ }
+ else /*left corner is on right chain*/
+ {
+ cornerTop = topVertex;
+ cornerLeftStart = leftStartIndex;
+ cornerRightUpEnd = up_leftCornerIndex;
+ }
+
+ if(down_leftCornerWhere == 0) /*left corner is on left chain*/
+ {
+ cornerBot = leftChain->getVertex(down_leftCornerIndex);
+ cornerLeftEnd = down_leftCornerIndex-1;
+ cornerRightDownStart = rightEndIndex+1; /*no right*/
+ }
+ else if(down_leftCornerWhere == 1) /*left corner is on bot*/
+ {
+ cornerBot = botVertex;
+ cornerLeftEnd = leftEndIndex;
+ cornerRightDownStart = rightEndIndex+1; /*no right*/
+ }
+ else /*left corner is on the right chian*/
+ {
+ cornerBot = botVertex;
+ cornerLeftEnd = leftEndIndex;
+ cornerRightDownStart = down_leftCornerIndex;
+ }
+
+
+
+
+ /*sample*/
+ if(midIndex2 >= 0) /*there is a trim point inbewteen grid lines*/
+ {
+
+ sampleLeftSingleTrimEdgeRegionGen(cornerTop, leftChain->getVertex(midIndex1),
+ leftChain,
+ cornerLeftStart,
+ midIndex1-1,
+ leftGridChain,
+ gridIndex1,
+ gridMidIndex1,
+ rightChain,
+ rightStartIndex,
+ cornerRightUpEnd,
+ 0, //no right down section
+ -1,
+ pStream);
+
+ sampleLeftSingleTrimEdgeRegionGen(leftChain->getVertex(midIndex2),
+ cornerBot,
+ leftChain,
+ midIndex2+1,
+ cornerLeftEnd,
+ leftGridChain,
+ gridMidIndex2,
+ gridIndex2,
+ rightChain,
+ 0, //no right up section
+ -1,
+ cornerRightDownStart,
+ rightEndIndex,
+ pStream);
+
+
+ sampleLeftStripRecF(leftChain,
+ midIndex1,
+ midIndex2,
+ leftGridChain,
+ gridMidIndex1,
+ gridMidIndex2,
+ pStream);
+ }
+ else
+ {
+ sampleLeftSingleTrimEdgeRegionGen(cornerTop, cornerBot,
+ leftChain,
+ cornerLeftStart,
+ cornerLeftEnd,
+ leftGridChain,
+ gridIndex1,
+ gridIndex2,
+ rightChain,
+ rightStartIndex,
+ cornerRightUpEnd,
+ cornerRightDownStart,
+ rightEndIndex,
+ pStream);
+ }
+}
+
+void sampleLeftSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBeginIndex,
+ Int gridEndIndex,
+ vertexArray* rightChain,
+ Int rightUpBegin,
+ Int rightUpEnd,
+ Int rightDownBegin,
+ Int rightDownEnd,
+ primStream* pStream)
+{
+ Int i,j,k;
+
+ /*creat an array to store all the up and down secments of the right chain,
+ *and the left end grid points
+ *
+ *although vertex array is a dynamic array, but to gain efficiency,
+ *it is better to initiliza the exact array size
+ */
+ vertexArray vArray(gridEndIndex-gridBeginIndex+1 +
+ max(0,rightUpEnd - rightUpBegin+1)+
+ max(0,rightDownEnd - rightDownBegin+1));
+
+ /*append the vertices on the up section of thr right chain*/
+ for(i=rightUpBegin; i<= rightUpEnd; i++)
+ vArray.appendVertex(rightChain->getVertex(i));
+
+ /*append the vertices of the left extremal grid points,
+ *and at the same time, perform triangulation for the stair cases
+ */
+ vArray.appendVertex(gridChain->get_vertex(gridBeginIndex));
+
+ for(k=1, i=gridBeginIndex+1; i<=gridEndIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ /*output the fan of the grid points of the (i)th and (i-1)th grid line.
+ */
+ if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i-1));
+ for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i));
+ for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+ }
+
+ /*then append all the vertices on the down section of the right chain*/
+ for(i=rightDownBegin; i<= rightDownEnd; i++)
+ vArray.appendVertex(rightChain->getVertex(i));
+
+ monoTriangulationRecGen(topVert, botVert,
+ leftChain, leftStart, leftEnd,
+ &vArray, 0, vArray.getNumElements()-1,
+ pStream);
+
+}
+
+
+
+
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.h
new file mode 100644
index 000000000..a3c179025
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.h
@@ -0,0 +1,86 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLECOMP_H
+#define _SAMPLECOMP_H
+
+#include "sampleMonoPoly.h"
+#include "rectBlock.h"
+
+void sampleConnectedComp(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int botLeftIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ );
+
+void sampleCompLeft(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream);
+
+void sampleLeftSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBegindex,
+ Int gridEndIndex,
+ vertexArray* rightChain,
+ Int rightUpBegin,
+ Int rightUpEnd,
+ Int rightDownBegin,
+ Int rightDownEnd,
+ primStream* pStream);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc
new file mode 100644
index 000000000..e12f88bab
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc
@@ -0,0 +1,844 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "zlassert.h"
+#include "sampleCompBot.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+//return: index_mono, index_pass
+//from [pass, mono] is strictly U-monotone
+//from [corner, pass] is <u
+// vertex[pass][0] >= u
+//if everybost is <u, then pass = end+1.
+//otherwise both mono and pass are meanng full and we have corner<=pass<=mono<=end
+void findBotLeftSegment(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass)
+{
+ Int i;
+
+ assert(leftCorner <= leftEnd);
+ for(i=leftCorner; i<= leftEnd; i++)
+ if(leftChain->getVertex(i)[0] >= u)
+ break;
+ ret_index_pass = i;
+ if(ret_index_pass <= leftEnd)
+ {
+ for(i=ret_index_pass; i< leftEnd; i++)
+ {
+ if(leftChain->getVertex(i+1)[0] <= leftChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_mono = i;
+ }
+
+}
+
+void findBotRightSegment(vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass)
+{
+ Int i;
+ assert(rightCorner <= rightEnd);
+ for(i=rightCorner; i<= rightEnd; i++)
+ if(rightChain->getVertex(i)[0] <= u)
+ break;
+
+
+
+ ret_index_pass = i;
+
+ if(ret_index_pass <= rightEnd)
+ {
+ for(i=ret_index_pass; i< rightEnd; i++)
+ {
+ if(rightChain->getVertex(i+1)[0] >= rightChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_mono = i;
+ }
+}
+
+
+void sampleBotRightWithGridLinePost(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the right of rightU
+ if(segIndexPass > rightCorner) //from corner to pass-1 is > u.
+ {
+ Real *tempBot;
+ if(segIndexPass <= rightEnd) //there is a point to the left of u
+ tempBot = rightChain->getVertex(segIndexPass);
+ else //nothing is to the left of u.
+ tempBot = botVertex;
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(rightU);
+ tempTop[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, tempBot,
+ rightChain,
+ rightCorner,
+ segIndexPass-1,
+ 0, // a decrease chain
+ pStream);
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexPass <= rightEnd) //segIndex pass and mono exist
+ {
+ //if there are grid points which are to the left of botVertex
+ //then we should use botVertex to form a fan with these points to
+ //optimize the triangulation
+ int do_optimize = 1;
+ if(botVertex[0] <= grid->get_u_value(leftU))
+ do_optimize = 0;
+ else
+ {
+ //we also have to make sure that botVertex is the left most vertex on the chain
+ int i;
+ for(i=segIndexMono; i<=rightEnd; i++)
+ if(rightChain->getVertex(i)[0] <= botVertex[0])
+ {
+ do_optimize = 0;
+ break;
+ }
+ }
+
+ if(do_optimize)
+ {
+ //find midU so that grid->get_u_value(midU) <= botVertex[0]
+ //and grid->get_u_value(midU) > botVertex[0]
+ int midU = leftU;
+ while(grid->get_u_value(midU) <= botVertex[0])
+ {
+ midU++;
+ if(midU > rightU)
+ break;
+ }
+ midU--;
+
+ grid->outputFanWithPoint(gridV, leftU, midU, botVertex, pStream);
+ stripOfFanRight(rightChain, segIndexMono, segIndexPass, grid, gridV, midU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(midU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, botVertex, rightChain, segIndexMono, rightEnd, 0, pStream);
+ }
+ else //not optimize
+ {
+ stripOfFanRight(rightChain, segIndexMono, segIndexPass, grid, gridV, leftU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(leftU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, botVertex, rightChain, segIndexMono, rightEnd, 0, pStream);
+ }
+ }
+ else //the botVertex forms a fan witht eh grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+}
+
+void sampleBotRightWithGridLine(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //if right chaain is empty, then there is only one bot vertex with
+ //one grid line
+ if(rightEnd<rightCorner){
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ return;
+ }
+
+ Int segIndexMono, segIndexPass;
+ findBotRightSegment(rightChain,
+ rightEnd,
+ rightCorner,
+ grid->get_u_value(rightU),
+ segIndexMono,
+ segIndexPass);
+
+ sampleBotRightWithGridLinePost(botVertex,
+ rightChain,
+ rightEnd,
+ segIndexMono,
+ segIndexPass,
+ rightCorner,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+void sampleBotLeftWithGridLinePost(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+
+ //the possible section which is to the left of leftU
+ if(segIndexPass > leftCorner) //at least leftCorner is to the left of leftU
+ {
+ Real *tempBot;
+ if(segIndexPass <= leftEnd) //from corner to pass-1 is <u
+ tempBot = leftChain->getVertex(segIndexPass);
+ else //nothing is to the rigth of u
+ tempBot = botVertex;
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(leftU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, tempBot, leftChain, leftCorner, segIndexPass-1,
+ 1, //a increase chain,
+ pStream);
+ }
+ //the possible section which is strictly Umonotone
+ if(segIndexPass <= leftEnd) //segIndexpass and mono exist
+ {
+ stripOfFanLeft(leftChain, segIndexMono, segIndexPass, grid, gridV, leftU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(rightU);
+ tempTop[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, botVertex, leftChain, segIndexMono, leftEnd,
+ 1, //increase chain
+ pStream);
+ }
+ else //the botVertex forms a fan with the grid points
+ {
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ }
+
+}
+
+void sampleBotLeftWithGridLine(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+
+ //if leftChain is empty, then there is only one botVertex with one grid line
+ if(leftEnd< leftCorner){
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ return;
+ }
+
+ Int segIndexPass, segIndexMono;
+ findBotLeftSegment(leftChain, leftEnd, leftCorner, grid->get_u_value(leftU), segIndexMono, segIndexPass);
+
+ sampleBotLeftWithGridLinePost(botVertex,
+ leftChain,
+ leftEnd,
+ segIndexMono,
+ segIndexPass,
+ leftCorner,
+ grid,
+ gridV,
+ leftU, rightU, pStream);
+}
+
+//return 1 if separator exists, 0 otherwise
+Int findBotSeparator(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Int& ret_sep_left,
+ Int& ret_sep_right)
+{
+ Int oldLeftI, oldRightI, newLeftI, newRightI;
+ Int i,j,k;
+ Real leftMax /*= leftChain->getVertex(leftCorner)[0]*/;
+ Real rightMin /*= rightChain->getVertex(rightCorner)[0]*/;
+ if(leftChain->getVertex(leftCorner)[1] < rightChain->getVertex(rightCorner)[1])//leftlower
+ {
+ oldLeftI = leftCorner-1;
+ oldRightI = rightCorner;
+ leftMax = leftChain->getVertex(leftCorner)[0] - Real(1.0) ; //initilize to be left of leftCorner
+ rightMin = rightChain->getVertex(rightCorner)[0];
+ }
+ else //rightlower
+ {
+ oldLeftI = leftCorner;
+ oldRightI = rightCorner-1;
+ leftMax = leftChain->getVertex(leftCorner)[0];
+ rightMin = rightChain->getVertex(rightCorner)[0] + Real(1.0);
+ }
+
+ //i: the current working leftChain Index
+ //j: the curent working right chian index
+ //if(left(i) is lower than right(j), then the two chains above right(j) are separated.
+ //else the two chains below left(i) are separated.
+ i = leftCorner;
+ j = rightCorner;
+ while(1)
+ {
+ newLeftI = oldLeftI;
+ newRightI = oldRightI;
+ if(i> leftEnd) //left chain is doen , go through remaining right chain
+ {
+ for(k=j+1; k<= rightEnd; k++)
+ {
+ if(rightChain->getVertex(k)[0] > leftMax) //no conflict
+ {
+ //update oldRightI if necessary
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ oldRightI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop, above right(k+1) is separated: oldLeftI, oldRightI
+ }
+ break; //the while loop
+ }
+ else if(j > rightEnd) //right Chain is doen
+ {
+ for(k=i+1; k<= leftEnd; k++)
+ {
+ if(leftChain->getVertex(k)[0] < rightMin) //no conflict
+ {
+ //update oldLeftI if necessary
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ oldLeftI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop, above left(k+1) is separated: oldLeftI, oldRightI
+ }
+ break; //the while loop
+ }
+ else if(leftChain->getVertex(i)[1] < rightChain->getVertex(j)[1]) //left lower
+ {
+
+ if(leftChain->getVertex(i)[0] > leftMax) //update leftMax amd newLeftI
+ {
+ leftMax = leftChain->getVertex(i)[0];
+ newLeftI = i;
+ }
+ for(k=j+1; k<= rightEnd; k++) //update rightMin and newRightI;
+ {
+ if(rightChain->getVertex(k)[1] < leftChain->getVertex(i)[1]) //right gets lower
+ break;
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ newRightI = k;
+ }
+ }
+ j = k; //next working j, since j will he lower than i in next loop
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+
+ }
+ }
+ else //right lower
+ {
+ if(rightChain->getVertex(j)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(j)[0];
+ newRightI = j;
+ }
+ for(k=i+1; k<= leftEnd; k++)
+ {
+ if(leftChain->getVertex(k)[1] < rightChain->getVertex(j)[1])
+ break;
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ newLeftI = k;
+ }
+ }
+ i=k; //nexct working i, since i will be lower than j next loop
+ if(leftMax >= rightMin) //there is conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ }//end of while loop
+ //now oldLeftI and oldRight I are the desired separator index notice that they are not
+ //necessarily valid
+ if(oldLeftI < leftCorner || oldRightI < rightCorner)
+ return 0; //no separator
+ else
+ {
+ ret_sep_left = oldLeftI;
+ ret_sep_right = oldRightI;
+ return 1;
+ }
+}
+
+void sampleCompBot(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+
+ if(down_leftCornerWhere == 1 && down_rightCornerWhere == 1) //the bot is botVertex with possible grid points
+ {
+
+ leftGridChain->getGrid()->outputFanWithPoint(leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ botVertex,
+ pStream);
+ return;
+ }
+ else if(down_leftCornerWhere != 0)
+ {
+
+ Real* tempBot;
+ Int tempRightEnd;
+ if(down_leftCornerWhere == 1){
+ tempRightEnd = rightEnd;
+ tempBot = botVertex;
+ }
+ else
+ {
+ tempRightEnd = down_leftCornerIndex-1;
+ tempBot = rightChain->getVertex(down_leftCornerIndex);
+ }
+
+ sampleBotRightWithGridLine(tempBot,
+ rightChain,
+ tempRightEnd,
+ down_rightCornerIndex,
+ rightGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+ }
+ else if(down_rightCornerWhere != 2)
+ {
+
+ Real* tempBot;
+ Int tempLeftEnd;
+ if(down_rightCornerWhere == 1){
+ tempLeftEnd = leftEnd;
+ tempBot = botVertex;
+ }
+ else //right corner is on left chain
+ {
+ tempLeftEnd = down_rightCornerIndex-1;
+ tempBot = leftChain->getVertex(down_rightCornerIndex);
+ }
+
+
+ sampleBotLeftWithGridLine(tempBot, leftChain, tempLeftEnd, down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+
+ }
+ else //down_leftCornereWhere == 0, down_rightCornerwhere == 2
+ {
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+ return;
+
+#ifdef NOT_REACHABLE
+ //the following code is trying to do some optimization, but not quite working. so it is not reachable, but leave it here for reference
+ Int sep_left, sep_right;
+ if(findBotSeparator(leftChain, leftEnd, down_leftCornerIndex,
+ rightChain, rightEnd, down_rightCornerIndex,
+ sep_left, sep_right)
+ )//separator exiosts
+ {
+
+ if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex) &&
+ rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex))
+ {
+ Int gridSep;
+ Int segLeftMono, segLeftPass, segRightMono, segRightPass;
+ findBotLeftSegment(leftChain,
+ sep_left,
+ down_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex),
+ segLeftMono,
+ segLeftPass);
+ findBotRightSegment(rightChain,
+ sep_right,
+ down_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex),
+ segRightMono,
+ segRightPass);
+ if(leftChain->getVertex(segLeftMono)[1] <= rightChain->getVertex(segRightMono)[1])
+ {
+ gridSep = rightGridChain->getUlineIndex(gridIndex);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) > leftChain->getVertex(segLeftMono)[0])
+ gridSep--;
+ }
+ else
+ {
+ gridSep = leftGridChain->getUlineIndex(gridIndex);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) < rightChain->getVertex(segRightMono)[0])
+ gridSep++;
+ }
+
+ sampleBotLeftWithGridLinePost(leftChain->getVertex(segLeftMono),
+ leftChain,
+ segLeftMono-1,
+ segLeftMono-1,
+ segLeftPass,
+ down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ gridSep,
+ pStream);
+ sampleBotRightWithGridLinePost(rightChain->getVertex(segRightMono),
+ rightChain,
+ segRightMono-1,
+ segRightMono-1,
+ segRightPass,
+ down_rightCornerIndex,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex),
+ gridSep,
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+ Real tempTop[2];
+ tempTop[0] = leftGridChain->getGrid()->get_u_value(gridSep);
+ tempTop[1] = leftGridChain->get_v_value(gridIndex);
+ monoTriangulationRecGen(tempTop, botVertex,
+ leftChain, segLeftMono, leftEnd,
+ rightChain, segRightMono, rightEnd,
+ pStream);
+ }//end if both sides have vertices inside the gridboundary points
+ else if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex)) //left n right out
+
+ {
+ Int segLeftMono, segLeftPass;
+ findBotLeftSegment(leftChain,
+ sep_left,
+ down_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex),
+ segLeftMono,
+ segLeftPass);
+ assert(segLeftPass <= sep_left); //make sure there is a point to the right of u.
+ monoTriangulation2(leftGridChain->get_vertex(gridIndex),
+ leftChain->getVertex(segLeftPass),
+ leftChain,
+ down_leftCornerIndex,
+ segLeftPass-1,
+ 1, //a increase chain
+ pStream);
+ stripOfFanLeft(leftChain, segLeftMono, segLeftPass,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream,1 );
+/*
+ sampleBotLeftWithGridLinePost(leftChain->getVertex(segLeftMono),
+ leftChain,
+ segLeftMono-1,
+ segLeftMono-1,
+ segLeftPass,
+ down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+*/
+
+ monoTriangulationRecGen(rightGridChain->get_vertex(gridIndex),
+ botVertex,
+ leftChain, segLeftMono, leftEnd,
+ rightChain, down_rightCornerIndex, rightEnd,
+ pStream);
+ }//end left in right out
+ else if(rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex))//left out right in
+ {
+ Int segRightMono, segRightPass;
+ findBotRightSegment(rightChain, sep_right, down_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex),
+ segRightMono,
+ segRightPass);
+
+ assert(segRightPass <= sep_right); //make sure there is a point to the left of u.
+ monoTriangulation2(rightGridChain->get_vertex(gridIndex),
+ rightChain->getVertex(segRightPass),
+ rightChain,
+ down_rightCornerIndex,
+ segRightPass-1,
+ 0, // a decrease chain
+ pStream);
+
+ stripOfFanRight(rightChain, segRightMono, segRightPass,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream, 1);
+
+
+ monoTriangulationRecGen(leftGridChain->get_vertex(gridIndex),
+ botVertex,
+ leftChain, down_leftCornerIndex, leftEnd,
+ rightChain, segRightMono, rightEnd,
+ pStream);
+
+ }//end left out right in
+ else //left out, right out
+ {
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+ }//end leftout right out
+ }//end if separator exists
+ else //no separator
+ {
+
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+ }
+#endif
+ }//end id 0 2
+}//end if the functin
+
+
+void sampleCompBotSimple(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+ //the plan is to use monotriangulation algorithm.
+ Int i,k;
+ Real* ActualTop;
+ Real* ActualBot;
+ Int ActualLeftStart, ActualLeftEnd;
+ Int ActualRightStart, ActualRightEnd;
+
+ //creat an array to store the points on the grid line
+ gridWrap* grid = leftGridChain->getGrid();
+ Int gridV = leftGridChain->getVlineIndex(gridIndex);
+ Int gridLeftU = leftGridChain->getUlineIndex(gridIndex);
+ Int gridRightU = rightGridChain->getUlineIndex(gridIndex);
+ Real2* gridPoints = (Real2*) malloc(sizeof(Real2) * (gridRightU - gridLeftU +1));
+ assert(gridPoints);
+
+ for(k=0, i=gridRightU; i>= gridLeftU; i--, k++)
+ {
+ gridPoints[k][0] = grid->get_u_value(i);
+ gridPoints[k][1] = grid->get_v_value(gridV);
+ }
+
+ if(down_rightCornerWhere != 0) //rightCorner is not on lef
+ ActualLeftEnd = leftEnd;
+ else
+ ActualLeftEnd = down_rightCornerIndex-1; //down_rightCornerIndex will be th actualBot
+
+ if(down_leftCornerWhere != 0) //left corner is not on let chian
+ ActualLeftStart = leftEnd+1; //meaning that there is no actual left section
+ else
+ ActualLeftStart = down_leftCornerIndex;
+
+ vertexArray ActualLeftChain(max(0, ActualLeftEnd - ActualLeftStart +1) + gridRightU - gridLeftU +1);
+
+ for(i=0; i<gridRightU - gridLeftU +1 ; i++)
+ ActualLeftChain.appendVertex(gridPoints[i]);
+ for(i=ActualLeftStart; i<= ActualLeftEnd; i++)
+ ActualLeftChain.appendVertex(leftChain->getVertex(i));
+
+ //determine ActualRightStart
+ if(down_rightCornerWhere != 2) //right is not on right
+ ActualRightStart = rightEnd +1; //meaning no section on right
+ else
+ ActualRightStart = down_rightCornerIndex;
+
+ //determine actualrightEnd
+ if(down_leftCornerWhere != 2) //left is not on right
+ {
+
+ ActualRightEnd = rightEnd;
+ }
+ else //left corner is on right
+ {
+ ActualRightEnd = down_leftCornerIndex-1; //down_leftCornerIndex will be the bot
+
+ }
+
+ //actual bot
+ if(down_rightCornerWhere == 2)
+ {
+ if(down_leftCornerWhere == 2)
+ ActualBot = rightChain->getVertex(down_leftCornerIndex);
+ else
+ ActualBot = botVertex;
+ }
+ else if(down_rightCornerWhere == 1) //right corner bot
+ ActualBot = botVertex;
+ else //down_rightCornerWhere == 0
+ ActualBot = leftChain->getVertex(down_rightCornerIndex);
+
+ ActualTop = gridPoints[0];
+/*
+printf("in bot simple, actual leftChain is \n");
+ActualLeftChain.print();
+printf("Actual Top = %f,%f\n", ActualTop[0],ActualTop[1]);
+printf("Actual Bot = %f,%f\n", ActualBot[0],ActualBot[1]);
+printf("Actual right start = %i, end=%i\n",ActualRightStart, ActualRightEnd);
+*/
+ if(rightChain->getVertex(ActualRightStart)[1] == ActualTop[1])
+ monoTriangulationRecGenOpt(rightChain->getVertex(ActualRightStart),
+ ActualBot,
+ &ActualLeftChain,
+ 0,
+ ActualLeftChain.getNumElements()-1,
+ rightChain,
+ ActualRightStart+1,
+ ActualRightEnd,
+ pStream);
+ else
+ monoTriangulationRecGenOpt(ActualTop, ActualBot,
+ &ActualLeftChain,
+ 1, //the first one is the top vertex
+ ActualLeftChain.getNumElements()-1,
+ rightChain,
+ ActualRightStart,
+ ActualRightEnd,
+ pStream);
+ free(gridPoints);
+}
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h
new file mode 100644
index 000000000..7b982794c
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h
@@ -0,0 +1,138 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLECOMPBOT_H
+#define _SAMPLECOMPBOT_H
+
+#include "sampleMonoPoly.h"
+
+void findBotLeftSegment(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass);
+
+void findBotRightSegment(vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass);
+
+
+void sampleBotRightWithGridLinePost(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotRightWithGridLine(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotLeftWithGridLinePost(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotLeftWithGridLine(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+Int findBotSeparator(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Int& ret_sep_left,
+ Int& ret_sep_right);
+
+void sampleCompBot(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream);
+
+void sampleCompBotSimple(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc
new file mode 100644
index 000000000..d01e50018
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc
@@ -0,0 +1,644 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gluos.h"
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+
+
+#ifdef NOT_TAKEOUT
+
+/*notice that we need leftChain because the
+ *corners could be on the leftChain.
+ */
+void sampleCompRight(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+ /*find out whether there is a trim vertex which is
+ *inbetween the top and bot grid lines or not.
+ */
+ Int midIndex1;
+ Int midIndex2;
+ Int gridMidIndex1 = 0, gridMidIndex2 = 0;
+ //midIndex1: array[i] <= v, array[i+1] > v
+ //midIndex2: array[i] >= v, array[i+1] < v
+ midIndex1 = rightChain->findIndexBelowGen(rightGridChain->get_v_value(gridIndex1),
+ rightStartIndex,
+ rightEndIndex);
+ midIndex2 = -1; //initilization
+ if(midIndex1 <= rightEndIndex && gridIndex1 < gridIndex2)
+ if(rightChain->getVertex(midIndex1)[1] >= rightGridChain->get_v_value(gridIndex2))
+ {
+ //midIndex2 must exist:
+ midIndex2 = rightChain->findIndexAboveGen(rightGridChain->get_v_value(gridIndex2),
+ midIndex1, //midIndex1<=midIndex2
+ rightEndIndex);
+ //find gridMidIndex1 so that either it=gridIndex1 when the gridline is
+ // at the same height as trim vertex midIndex1, or it is the last one
+ //which is strictly above midIndex1.
+ {
+ Real temp = rightChain->getVertex(midIndex1)[1];
+ if(rightGridChain->get_v_value(gridIndex1) == temp)
+ gridMidIndex1 = gridIndex1;
+ else
+ {
+ gridMidIndex1 = gridIndex1;
+ while(rightGridChain->get_v_value(gridMidIndex1) > temp)
+ gridMidIndex1++;
+ gridMidIndex1--;
+ }
+ }//end of find gridMindIndex1
+ //find gridMidIndex2 so that it is the (first one below or equal
+ //midIndex) last one above or equal midIndex2
+ {
+ Real temp = rightChain->getVertex(midIndex2)[1];
+ for(gridMidIndex2 = gridMidIndex1+1; gridMidIndex2 <= gridIndex2; gridMidIndex2++)
+ if(rightGridChain->get_v_value(gridMidIndex2) <= temp)
+ break;
+
+ assert(gridMidIndex2 <= gridIndex2);
+ }//end of find gridMidIndex2
+ }
+
+
+
+ //to interprete the corner information
+ Real* cornerTop;
+ Real* cornerBot;
+ Int cornerRightStart;
+ Int cornerRightEnd;
+ Int cornerLeftUpEnd;
+ Int cornerLeftDownStart;
+ if(up_rightCornerWhere == 2) //right corner is on right chain
+ {
+ cornerTop = rightChain->getVertex(up_rightCornerIndex);
+ cornerRightStart = up_rightCornerIndex+1;
+ cornerLeftUpEnd = -1; //no left
+ }
+ else if(up_rightCornerWhere == 1) //right corner is on top
+ {
+ cornerTop = topVertex;
+ cornerRightStart = rightStartIndex;
+ cornerLeftUpEnd = -1; //no left
+ }
+ else //right corner is on left chain
+ {
+ cornerTop = topVertex;
+ cornerRightStart = rightStartIndex;
+ cornerLeftUpEnd = up_rightCornerIndex;
+ }
+
+ if(down_rightCornerWhere == 2) //right corner is on right chan
+ {
+ cornerBot = rightChain->getVertex(down_rightCornerIndex);
+ cornerRightEnd = down_rightCornerIndex-1;
+ cornerLeftDownStart = leftEndIndex+1; //no left
+ }
+ else if (down_rightCornerWhere == 1) //right corner is at bot
+ {
+ cornerBot = botVertex;
+ cornerRightEnd = rightEndIndex;
+ cornerLeftDownStart = leftEndIndex+1; //no left
+ }
+ else //right corner is on the left chain
+ {
+ cornerBot = botVertex;
+ cornerRightEnd = rightEndIndex;
+ cornerLeftDownStart = down_rightCornerIndex;
+ }
+
+ //sample
+ if(midIndex2 >= 0) //there is a trm point between grid lines
+ {
+
+ sampleRightSingleTrimEdgeRegionGen(cornerTop, rightChain->getVertex(midIndex1),
+ rightChain,
+ cornerRightStart,
+ midIndex1-1,
+ rightGridChain,
+ gridIndex1,
+ gridMidIndex1,
+ leftChain,
+ leftStartIndex,
+ cornerLeftUpEnd,
+ 0, //no left down section,
+ -1,
+ pStream);
+
+ sampleRightSingleTrimEdgeRegionGen(rightChain->getVertex(midIndex2),
+ cornerBot,
+ rightChain,
+ midIndex2+1,
+ cornerRightEnd,
+ rightGridChain,
+ gridMidIndex2,
+ gridIndex2,
+ leftChain,
+ 0, //no left up section
+ -1,
+ cornerLeftDownStart,
+ leftEndIndex,
+ pStream);
+
+ sampleRightStripRecF(rightChain,
+ midIndex1,
+ midIndex2,
+ rightGridChain,
+ gridMidIndex1,
+ gridMidIndex2,
+ pStream);
+
+ }
+ else
+ {
+ sampleRightSingleTrimEdgeRegionGen(cornerTop, cornerBot,
+ rightChain,
+ cornerRightStart,
+ cornerRightEnd,
+ rightGridChain,
+ gridIndex1,
+ gridIndex2,
+ leftChain,
+ leftStartIndex,
+ cornerLeftUpEnd,
+ cornerLeftDownStart,
+ leftEndIndex,
+ pStream);
+ }
+}
+
+void sampleRightSingleTrimEdgeRegionGen(Real topVertex[2], Real botVertex[2],
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBeginIndex,
+ Int gridEndIndex,
+ vertexArray* leftChain,
+ Int leftUpBegin,
+ Int leftUpEnd,
+ Int leftDownBegin,
+ Int leftDownEnd,
+ primStream* pStream)
+{
+ Int i,k;
+ /*creat an array to store all the up and down secments of the left chain,
+ *and the right end grid points
+ *
+ *although vertex array is a dynamic array, but to gain efficiency,
+ *it is better to initiliza the exact array size
+ */
+ vertexArray vArray(gridEndIndex-gridBeginIndex+1 +
+ max(0,leftUpEnd - leftUpBegin+1)+
+ max(0,leftDownEnd - leftDownBegin+1));
+ //append the vertices on the up section of the left chain
+ for(i=leftUpBegin; i<= leftUpEnd; i++)
+ vArray.appendVertex(leftChain->getVertex(i));
+
+ //append the vertices of the right extremal grid points,
+ //and at the same time, perform triangulation for the stair cases
+ vArray.appendVertex(gridChain->get_vertex(gridBeginIndex));
+
+ for(k=1, i=gridBeginIndex+1; i<= gridEndIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ //output the fan of the grid points of the (i)th and (i-1)th grid line.
+ gridChain->rightEndFan(i, pStream);
+ }
+
+ //append all the vertices on the down section of the left chain
+ for(i=leftDownBegin; i<= leftDownEnd; i++)
+ vArray.appendVertex(leftChain->getVertex(i));
+ monoTriangulationRecGen(topVertex, botVertex,
+ &vArray, 0, vArray.getNumElements()-1,
+ rightChain, rightStart, rightEnd,
+ pStream);
+}
+
+void sampleRightSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream)
+{
+ Int i,k;
+ vertexArray vArray(endIndex-beginIndex+1);
+ vArray.appendVertex(gridChain->get_vertex(beginIndex));
+ for(k=1, i=beginIndex+1; i<= endIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+ //output the fan of the grid points of the (i)_th and i-1th gridLine
+ gridChain->rightEndFan(i, pStream);
+ }
+ monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex,
+ 1, //increase chain (to the left)
+ pStream);
+}
+
+
+/*the gridlines from rightGridChainStartIndex to
+ *rightGridChainEndIndex are assumed to form a
+ *connected componenet
+ *the trm vertex of topRightIndex is assumed to be below
+ *or equal the first gridLine, and the trm vertex of
+ *botRightIndex is assumed to be above or equal the last gridline
+ **there could be multipe trm vertices equal to the last gridline, but
+ **only one could be equal to top gridline. shape: ____| (recall that
+ **for left chain recF, we allow shape: |----
+ *if botRightIndex<topRightIndex, then no connected componenet exists, and
+ *no triangles are generated.
+ *Othewise, botRightIndex>= topRightIndex, there is at least one triangles to
+ *output
+ */
+void sampleRightStripRecF(vertexArray* rightChain,
+ Int topRightIndex,
+ Int botRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ Int rightGridChainEndIndex,
+ primStream* pStream
+ )
+{
+
+ //sstop conditionL: if topRightIndex > botRightIndex, then stop
+ if(topRightIndex > botRightIndex)
+ return;
+
+ //if there is only one grid line, return
+ if(rightGridChainStartIndex >= rightGridChainEndIndex)
+ return;
+
+
+ assert(rightChain->getVertex(topRightIndex)[1] <= rightGridChain->get_v_value(rightGridChainStartIndex) &&
+ rightChain->getVertex(botRightIndex)[1] >= rightGridChain->get_v_value(rightGridChainEndIndex));
+
+ //firstfind the first trim vertex which is strictly below the second top
+ //grid line: index1.
+ Real secondGridChainV = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+ Int index1 = topRightIndex;
+ while(rightChain->getVertex(index1)[1] >= secondGridChainV){
+ index1++;
+ if(index1 > botRightIndex)
+ break;
+ }
+ //now rightChain->getVertex(index1-1)[1] >= secondGridChainV and
+ //rightChain->getVertex(index1)[1] < secondGridChainV and
+ //we should include index1-1 to perform a gridStep
+ index1--;
+
+ //now we have rightChain->getVertex(index1)[1] >= secondGridChainV, and
+ //rightChain->getVertex(index1+1)[1] < secondGridChainV
+ sampleRightOneGridStep(rightChain, topRightIndex, index1, rightGridChain, rightGridChainStartIndex, pStream);
+
+ //if rightChain->getVertex(index1)[1] ==secondGridChainV then we can
+ //recurvesively to the rest
+ if(rightChain->getVertex(index1)[1] == secondGridChainV)
+ {
+
+
+ sampleRightStripRecF(rightChain, index1, botRightIndex, rightGridChain, rightGridChainStartIndex+1, rightGridChainEndIndex, pStream);
+ }
+ else if(index1 < botRightIndex)
+ {
+ //otherwise, we have rightChain->getVertex(index1)[1] > secondV
+ //let the next trim vertex be nextTrimVertex, (which should be strictly
+ //below the second grid line). Find the last grid line index2 which is STRICTLY ABOVE
+ //nextTrimVertex.
+ //sample one trm edge region.
+ Real *uppervert, *lowervert;
+ uppervert = rightChain->getVertex(index1);
+ lowervert = rightChain->getVertex(index1+1); //okay since index1<botRightindex
+ Int index2 = rightGridChainStartIndex+1;
+ while(rightGridChain->get_v_value(index2) > lowervert[1])
+ {
+ index2++;
+ if(index2 > rightGridChainEndIndex)
+ break;
+ }
+ index2--;
+
+ sampleRightSingleTrimEdgeRegion(uppervert, lowervert, rightGridChain, rightGridChainStartIndex+1, index2, pStream);
+
+ //recursion
+ sampleRightStripRecF(rightChain, index1+1, botRightIndex, rightGridChain, index2, rightGridChainEndIndex, pStream);
+ }
+}
+
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream)
+{
+ /*since there is no middle, there is at most one point which is on the
+ *second grid line, there could be multiple points on the first (top)
+ *grid line.
+ */
+ rightGridChain->rightEndFan(rightGridChainStartIndex+1, pStream);
+ monoTriangulation2(rightGridChain->get_vertex(rightGridChainStartIndex),
+ rightGridChain->get_vertex(rightGridChainStartIndex+1),
+ rightChain,
+ beginRightIndex,
+ endRightIndex,
+ 0, //decrease chain
+ pStream);
+}
+
+//sampling the right area in between two grid lines
+//shape: _________|
+void sampleRightOneGridStep(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream)
+{
+ if(checkMiddle(rightChain, beginRightIndex, endRightIndex,
+ rightGridChain->get_v_value(rightGridChainStartIndex),
+ rightGridChain->get_v_value(rightGridChainStartIndex+1))<0)
+ {
+ sampleRightOneGridStepNoMiddle(rightChain, beginRightIndex, endRightIndex, rightGridChain, rightGridChainStartIndex, pStream);
+ return;
+ }
+
+ //copy into a polygn
+ {
+ directedLine* poly = NULL;
+ sampledLine* sline;
+ directedLine* dline;
+ gridWrap* grid = rightGridChain->getGrid();
+ float vert1[2];
+ float vert2[2];
+ Int i;
+
+ Int innerInd = rightGridChain->getInnerIndex(rightGridChainStartIndex+1);
+ Int upperInd = rightGridChain->getUlineIndex(rightGridChainStartIndex);
+ Int lowerInd = rightGridChain->getUlineIndex(rightGridChainStartIndex+1);
+ Real upperV = rightGridChain->get_v_value(rightGridChainStartIndex);
+ Real lowerV = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+
+ //the upper gridline
+ vert1[1]=vert2[1]=upperV;
+ for(i=upperInd;
+ i>innerInd;
+ i--)
+ {
+ vert1[0]=grid->get_u_value(i);
+ vert2[0]=grid->get_u_value(i-1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+ }
+
+ //the vertical grid line segment
+ vert1[0]=vert2[0] = grid->get_u_value(innerInd);
+ vert1[1]=upperV;
+ vert2[1]=lowerV;
+ sline=new sampledLine(vert1, vert2);
+ dline=new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+
+ //the lower grid line
+ vert1[1]=vert2[1]=lowerV;
+ for(i=innerInd; i<lowerInd; i++)
+ {
+ vert1[0] = grid->get_u_value(i);
+ vert2[0] = grid->get_u_value(i+1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting lower grid to right chain
+ vert1[0]=grid->get_u_value(lowerInd);
+ sline = new sampledLine(vert1, rightChain->getVertex(endRightIndex));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+
+
+ //the right Chain
+ for(i=endRightIndex; i>beginRightIndex; i--)
+ {
+ sline = new sampledLine(rightChain->getVertex(i), rightChain->getVertex(i-1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting right chain with upper grid
+ vert2[1]=upperV;
+ vert2[0]=grid->get_u_value(upperInd);
+ sline = new sampledLine(rightChain->getVertex(beginRightIndex), vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ monoTriangulationOpt(poly, pStream);
+ //clean up
+ poly->deleteSinglePolygonWithSline();
+
+ return;
+ }
+
+ //this following code cannot be reached, but leave it for debuggig purpose.
+ Int i;
+ //find the maximal U-monotone chain of beginRightIndex, beginRightIndex+1,...
+ i=beginRightIndex;
+ Real prevU = rightChain->getVertex(i)[0];
+ for(i=beginRightIndex+1; i<= endRightIndex; i++){
+ Real thisU = rightChain->getVertex(i)[0];
+ if(thisU < prevU)
+ prevU = thisU;
+ else
+ break;
+ }
+ //from beginRightIndex to i-1 is strictly U-monotne
+ //if(i-1==beginRightIndex and the vertex of rightchain is on the first
+ //gridline, then we should use 2 vertices on the right chain. Of we only
+ //use one (begin), we would output degenrate triangles.
+ if(i-1 == beginRightIndex && rightChain->getVertex(beginRightIndex)[1] == rightGridChain->get_v_value(rightGridChainStartIndex))
+ i++;
+
+ Int j = endRightIndex -1;
+ if(rightGridChain->getInnerIndex(rightGridChainStartIndex+1) < rightGridChain->getUlineIndex(rightGridChainStartIndex+1))
+ {
+ j = rightChain->findDecreaseChainFromEnd(i-1/*beginRightIndex*/, endRightIndex);
+ Int temp = endRightIndex;
+ //now from j+1 to end is strictly U-monotone.
+ //if j+1 is on the last grid line, then we wat to skip to the vertex
+ //whcih is strictly above the second grid line. This vertex must exist
+ //since there is a middle vertex
+ if(j+1 == endRightIndex)
+ {
+ while(rightChain->getVertex(j+1)[1] == rightGridChain->get_v_value(rightGridChainStartIndex+1))
+ j--;
+
+ monoTriangulation2(rightChain->getVertex(j+1),
+ rightGridChain->get_vertex(rightGridChainStartIndex+1),
+ rightChain,
+ j+2,
+ endRightIndex,
+ 0, //a decrease chain
+ pStream);
+
+ temp = j+1;
+ }
+
+ stripOfFanRight(rightChain, temp, j+1, rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(rightGridChainStartIndex+1),
+ rightGridChain->getInnerIndex(rightGridChainStartIndex+1),
+ rightGridChain->getUlineIndex(rightGridChainStartIndex+1),
+ pStream,
+ 0 //the grid line is below the trim line
+ );
+
+ }
+
+
+ stripOfFanRight(rightChain, i-1, beginRightIndex, rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(rightGridChainStartIndex),
+ rightGridChain->getInnerIndex(rightGridChainStartIndex+1),
+ rightGridChain->getUlineIndex(rightGridChainStartIndex),
+ pStream,
+ 1 //the grid line is above the trm lines
+ );
+
+ //monotone triangulate the remaining rightchain together with the
+ //two vertices on the two grid v-lines
+ Real vert[2][2];
+ vert[0][0] = vert[1][0] = rightGridChain->getInner_u_value(rightGridChainStartIndex+1);
+ vert[0][1] = rightGridChain->get_v_value(rightGridChainStartIndex);
+ vert[1][1] = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+
+ monoTriangulation2(&vert[0][0],
+ &vert[1][0],
+ rightChain,
+ i-1,
+ j+1,
+ 0, ///a decreae chain
+ pStream);
+}
+
+#endif
+
+void stripOfFanRight(vertexArray* rightChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if the grid line is above the trim lines*/
+ )
+{
+ assert(largeIndex >= smallIndex);
+
+ Real grid_v_value;
+ grid_v_value = grid->get_v_value(vlineIndex);
+
+ Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1));
+ assert(trimVerts);
+
+
+ Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1));
+ assert(gridVerts);
+
+ Int k,i;
+ if(! gridLineUp) /*trim line is above grid line, so trim vertices are going right when index increases*/
+ for(k=0, i=smallIndex; i<=largeIndex; i++, k++)
+ {
+ trimVerts[k][0] = rightChain->getVertex(i)[0];
+ trimVerts[k][1] = rightChain->getVertex(i)[1];
+ }
+ else
+ for(k=0, i=largeIndex; i>=smallIndex; i--, k++)
+ {
+ trimVerts[k][0] = rightChain->getVertex(i)[0];
+ trimVerts[k][1] = rightChain->getVertex(i)[1];
+ }
+
+ for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++)
+ {
+ gridVerts[k][0] = grid->get_u_value(i);
+ gridVerts[k][1] = grid_v_value;
+ }
+
+ if(gridLineUp)
+ triangulateXYMono(
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ largeIndex-smallIndex+1, trimVerts,
+ pStream);
+ else
+ triangulateXYMono(largeIndex-smallIndex+1, trimVerts,
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ pStream);
+ free(trimVerts);
+ free(gridVerts);
+}
+
+
+
+
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h
new file mode 100644
index 000000000..4670b87ca
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h
@@ -0,0 +1,117 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLECOMPRIGHT_H
+#define _SAMPLECOMPRIGHT_H
+
+#define NOT_TAKEOUT
+
+#include "sampleMonoPoly.h"
+void stripOfFanRight(vertexArray* rightChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if grid line is above the trim lines */
+ );
+
+#ifdef NOT_TAKEOUT
+void sampleRightStripRecF(vertexArray* rightChain,
+ Int topRightIndex,
+ Int botRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ Int rightGridChainEndIndex,
+ primStream* pStream
+ );
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+//sampling the right area in between two grid lines
+//shape: _________|
+void sampleRightOneGridStep(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+void sampleRightSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream);
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+
+void sampleCompRight(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream);
+
+void sampleRightSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBegindex,
+ Int gridEndIndex,
+ vertexArray* leftChain,
+ Int leftUpBegin,
+ Int leftUpEnd,
+ Int leftDownBegin,
+ Int leftDownEnd,
+ primStream* pStream);
+#endif
+
+#endif
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc
new file mode 100644
index 000000000..b7b929623
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc
@@ -0,0 +1,1030 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "zlassert.h"
+#include "sampleCompTop.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+//return : index_small, and index_large,
+//from [small, large] is strictly U-monotne,
+//from [large+1, end] is <u
+//and vertex[large][0] is >= u
+//if eveybody is <u, the large = start-1.
+//otherwise both large and small are meaningful and we have start<=small<=large<=end
+void findTopLeftSegment(vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ Real u,
+ Int& ret_index_small,
+ Int& ret_index_large
+ )
+{
+ Int i;
+ assert(leftStart <= leftEnd);
+ for(i=leftEnd; i>= leftStart; i--)
+ {
+ if(leftChain->getVertex(i)[0] >= u)
+ break;
+ }
+ ret_index_large = i;
+ if(ret_index_large >= leftStart)
+ {
+ for(i=ret_index_large; i>leftStart; i--)
+ {
+ if(leftChain->getVertex(i-1)[0] <= leftChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_small = i;
+ }
+}
+
+void findTopRightSegment(vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ Real u,
+ Int& ret_index_small,
+ Int& ret_index_large)
+{
+ Int i;
+ assert(rightStart<=rightEnd);
+ for(i=rightEnd; i>=rightStart; i--)
+ {
+ if(rightChain->getVertex(i)[0] <= u)
+ break;
+ }
+ ret_index_large = i;
+ if(ret_index_large >= rightStart)
+ {
+ for(i=ret_index_large; i>rightStart;i--)
+ {
+ if(rightChain->getVertex(i-1)[0] >= rightChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_small = i;
+ }
+}
+
+
+void sampleTopRightWithGridLinePost(Real* topVertex,
+ vertexArray* rightChain,
+ Int rightStart,
+ Int segIndexSmall,
+ Int segIndexLarge,
+ Int rightEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the right of rightU
+ if(segIndexLarge < rightEnd)
+ {
+ Real *tempTop;
+ if(segIndexLarge >= rightStart)
+ tempTop = rightChain->getVertex(segIndexLarge);
+ else
+ tempTop = topVertex;
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(rightU);
+ tempBot[1] = grid->get_v_value(gridV);
+monoTriangulationRecGenOpt(tempTop, tempBot,
+ NULL, 1,0,
+ rightChain, segIndexLarge+1, rightEnd,
+ pStream);
+/*
+ monoTriangulation2(tempTop, tempBot,
+ rightChain,
+ segIndexLarge+1,
+ rightEnd,
+ 0, //a decrease chian
+ pStream);
+*/
+
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexLarge >= rightStart)
+ {
+ stripOfFanRight(rightChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(leftU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, rightChain, rightStart, segIndexSmall, 0, pStream);
+ }
+ else //the topVertex forms a fan with the grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+}
+
+void sampleTopRightWithGridLine(Real* topVertex,
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream
+ )
+{
+ //if right chian is empty, then there is only one topVertex with one grid line
+ if(rightEnd < rightStart){
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+ return;
+ }
+
+ Int segIndexSmall, segIndexLarge;
+ findTopRightSegment(rightChain,
+ rightStart,
+ rightEnd,
+ grid->get_u_value(rightU),
+ segIndexSmall,
+ segIndexLarge
+ );
+ sampleTopRightWithGridLinePost(topVertex, rightChain,
+ rightStart,
+ segIndexSmall,
+ segIndexLarge,
+ rightEnd,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+void sampleTopLeftWithGridLinePost(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStart,
+ Int segIndexSmall,
+ Int segIndexLarge,
+ Int leftEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the left of leftU
+
+ if(segIndexLarge < leftEnd)
+ {
+ Real *tempTop;
+ if(segIndexLarge >= leftStart)
+ tempTop = leftChain->getVertex(segIndexLarge);
+ else
+ tempTop = topVertex;
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(leftU);
+ tempBot[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, tempBot,
+ leftChain,
+ segIndexLarge+1,
+ leftEnd,
+ 1, //a increase chian
+ pStream);
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexLarge >= leftStart)
+ {
+ //if there are grid points which are to the right of topV,
+ //then we should use topVertex to form a fan with these points to
+ //optimize the triangualtion
+ int do_optimize=1;
+ if(topVertex[0] >= grid->get_u_value(rightU))
+ do_optimize = 0;
+ else
+ {
+ //we also have to make sure that topVertex are the right most vertex
+ //on the chain.
+ int i;
+ for(i=leftStart; i<=segIndexSmall; i++)
+ if(leftChain->getVertex(i)[0] >= topVertex[0])
+ {
+ do_optimize = 0;
+ break;
+ }
+ }
+
+ if(do_optimize)
+ {
+ //find midU so that grid->get_u_value(midU) >= topVertex[0]
+ //and grid->get_u_value(midU-1) < topVertex[0]
+ int midU=rightU;
+ while(grid->get_u_value(midU) >= topVertex[0])
+ {
+ midU--;
+ if(midU < leftU)
+ break;
+ }
+ midU++;
+
+ grid->outputFanWithPoint(gridV, midU, rightU, topVertex, pStream);
+ stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, midU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(midU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
+ }
+ else //not optimize
+ {
+
+ stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(rightU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
+ }
+ }
+ else //the topVertex forms a fan with the grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+}
+
+
+void sampleTopLeftWithGridLine(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream
+ )
+{
+ Int segIndexSmall, segIndexLarge;
+ //if left chain is empty, then there is only one top vertex with one grid
+ // line
+ if(leftEnd < leftStart) {
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+ return;
+ }
+ findTopLeftSegment(leftChain,
+ leftStart,
+ leftEnd,
+ grid->get_u_value(leftU),
+ segIndexSmall,
+ segIndexLarge
+ );
+ sampleTopLeftWithGridLinePost(topVertex,
+ leftChain,
+ leftStart,
+ segIndexSmall,
+ segIndexLarge,
+ leftEnd,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+//return 1 if saprator exits, 0 otherwise
+Int findTopSeparator(vertexArray* leftChain,
+ Int leftStartIndex,
+ Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ Int rightEndIndex,
+ Int& ret_sep_left,
+ Int& ret_sep_right)
+{
+
+ Int oldLeftI, oldRightI, newLeftI, newRightI;
+ Int i,j,k;
+ Real leftMax /*= leftChain->getVertex(leftEndIndex)[0]*/;
+ Real rightMin /*= rightChain->getVertex(rightEndIndex)[0]*/;
+ if(leftChain->getVertex(leftEndIndex)[1] > rightChain->getVertex(rightEndIndex)[1]) //left higher
+ {
+ oldLeftI = leftEndIndex+1;
+ oldRightI = rightEndIndex;
+ leftMax = leftChain->getVertex(leftEndIndex)[0] - Real(1.0); //initilza to left of leftU
+ rightMin = rightChain->getVertex(rightEndIndex)[0];
+ }
+ else
+ {
+ oldLeftI = leftEndIndex;
+ oldRightI = rightEndIndex+1;
+ leftMax = leftChain->getVertex(leftEndIndex)[0];
+ rightMin = rightChain->getVertex(rightEndIndex)[0] + Real(1.0);
+ }
+
+ //i: the current working leftChain index,
+ //j: the current working rightChain index,
+ //if left(i) is higher than right(j), then the two chains beloew right(j) are separated.
+ //else the two chains below left(i) are separeated.
+ i=leftEndIndex;
+ j=rightEndIndex;
+ while(1)
+ {
+ newLeftI = oldLeftI;
+ newRightI = oldRightI;
+
+ if(i<leftStartIndex) //left chain is done, go through remining right chain.
+ {
+ for(k=j-1; k>= rightStartIndex; k--)
+ {
+ if(rightChain->getVertex(k)[0] > leftMax) //no conflict
+ {
+ //update oldRightI if necessary
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ oldRightI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop. below right(k-1) is seperated: oldLeftI, oldRightI.
+ }
+ break; //the while loop
+ }
+ else if(j<rightStartIndex) //rightChain is done
+ {
+ for(k=i-1; k>= leftStartIndex; k--)
+ {
+ if(leftChain->getVertex(k)[0] < rightMin) //no conflict
+ {
+ //update oldLeftI if necessary
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ oldLeftI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for loop
+ }
+ break; //the while loop
+ }
+ else if(leftChain->getVertex(i)[1] > rightChain->getVertex(j)[1]) //left hgiher
+ {
+ if(leftChain->getVertex(i)[0] > leftMax) //update leftMax and newLeftI.
+ {
+ leftMax = leftChain->getVertex(i)[0];
+ newLeftI = i;
+ }
+ for(k=j-1; k>= rightStartIndex; k--) //update rightMin and newRightI.
+ {
+ if(rightChain->getVertex(k)[1] > leftChain->getVertex(i)[1])
+ break;
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ newRightI = k;
+ }
+ }
+ j = k; //next working j, since j will be higher than i in next loop
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ else //right higher
+ {
+ if(rightChain->getVertex(j)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(j)[0];
+ newRightI = j;
+ }
+ for(k=i-1; k>= leftStartIndex; k--)
+ {
+ if(leftChain->getVertex(k)[1] > rightChain->getVertex(j)[1])
+ break;
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ newLeftI = k;
+ }
+ }
+ i = k; //next working i, since i will be higher than j next loop
+
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ }//end of while loop
+ //now oldLeftI and oldRightI are the desired separeator index, notice that there are not necessarily valid
+ if(oldLeftI > leftEndIndex || oldRightI > rightEndIndex)
+ return 0;
+ else
+ {
+ ret_sep_left = oldLeftI;
+ ret_sep_right = oldRightI;
+ return 1;
+ }
+}
+
+
+void sampleCompTop(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream)
+{
+ if(up_leftCornerWhere == 1 && up_rightCornerWhere == 1) //the top is topVertex with possible grid points
+ {
+ leftGridChain->getGrid()->outputFanWithPoint(leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ topVertex,
+ pStream);
+ return;
+ }
+
+ else if(up_leftCornerWhere != 0)
+ {
+ Real* tempTop;
+ Int tempRightStart;
+ if(up_leftCornerWhere == 1){
+ tempRightStart = rightStartIndex;
+ tempTop = topVertex;
+ }
+ else
+ {
+ tempRightStart = up_leftCornerIndex+1;
+ tempTop = rightChain->getVertex(up_leftCornerIndex);
+ }
+ sampleTopRightWithGridLine(tempTop, rightChain, tempRightStart, up_rightCornerIndex,
+ rightGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+ }
+ else if(up_rightCornerWhere != 2)
+ {
+ Real* tempTop;
+ Int tempLeftStart;
+ if(up_rightCornerWhere == 1)
+ {
+ tempLeftStart = leftStartIndex;
+ tempTop = topVertex;
+ }
+ else //0
+ {
+ tempLeftStart = up_rightCornerIndex+1;
+ tempTop = leftChain->getVertex(up_rightCornerIndex);
+ }
+/*
+ sampleTopLeftWithGridLine(tempTop, leftChain, tempLeftStart, up_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+*/
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+ else //up_leftCornerWhere == 0, up_rightCornerWhere == 2.
+ {
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ return;
+#ifdef NOT_REACHABLE //code is not reachable, for test purpose only
+ //the following code is trying to do some optimization, but not quite working, also see sampleCompBot.C:
+ Int sep_left, sep_right;
+ if(findTopSeparator(leftChain,
+ leftStartIndex,
+ up_leftCornerIndex,
+ rightChain,
+ rightStartIndex,
+ up_rightCornerIndex,
+ sep_left,
+ sep_right)
+ ) //separator exists
+ {
+
+ if( leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1) &&
+ rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
+ {
+ Int gridSep;
+ Int segLeftSmall, segLeftLarge, segRightSmall, segRightLarge;
+ Int valid=1; //whether the gridStep is valid or not.
+ findTopLeftSegment(leftChain,
+ sep_left,
+ up_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex1),
+ segLeftSmall,
+ segLeftLarge);
+ findTopRightSegment(rightChain,
+ sep_right,
+ up_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex1),
+ segRightSmall,
+ segRightLarge);
+ if(leftChain->getVertex(segLeftSmall)[1] >= rightChain->getVertex(segRightSmall)[1])
+ {
+ gridSep = rightGridChain->getUlineIndex(gridIndex1);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) > leftChain->getVertex(segLeftSmall)[0])
+ gridSep--;
+ if(segLeftSmall<segLeftLarge)
+ if(leftGridChain->getGrid()->get_u_value(gridSep) < leftChain->getVertex(segLeftSmall+1)[0])
+ {
+ valid = 0;
+ }
+ }
+ else
+ {
+ gridSep = leftGridChain->getUlineIndex(gridIndex1);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) < rightChain->getVertex(segRightSmall)[0])
+ gridSep++;
+ if(segRightSmall<segRightLarge)
+ if(leftGridChain->getGrid()->get_u_value(gridSep) > rightChain->getVertex(segRightSmall+1)[0])
+ {
+ valid = 0;
+ }
+ }
+
+ if(! valid)
+ {
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+ else
+ {
+ sampleTopLeftWithGridLinePost(leftChain->getVertex(segLeftSmall),
+ leftChain,
+ segLeftSmall+1,
+ segLeftSmall+1,
+ segLeftLarge,
+ up_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ gridSep,
+ pStream);
+ sampleTopRightWithGridLinePost(rightChain->getVertex(segRightSmall),
+ rightChain,
+ segRightSmall+1,
+ segRightSmall+1,
+ segRightLarge,
+ up_rightCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ gridSep,
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+ Real tempBot[2];
+ tempBot[0] = leftGridChain->getGrid()->get_u_value(gridSep);
+ tempBot[1] = leftGridChain->get_v_value(gridIndex1);
+ monoTriangulationRecGen(topVertex, tempBot,
+ leftChain, leftStartIndex, segLeftSmall,
+ rightChain, rightStartIndex, segRightSmall,
+ pStream);
+ }
+ }//end if both sides have vetices inside the gridboundary points
+ else if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1)) //left is in, right is nout
+ {
+
+ Int segLeftSmall, segLeftLarge;
+ findTopLeftSegment(leftChain,
+ sep_left,
+ up_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex1),
+ segLeftSmall,
+ segLeftLarge);
+ assert(segLeftLarge >= sep_left);
+ monoTriangulation2(leftChain->getVertex(segLeftLarge),
+ leftGridChain->get_vertex(gridIndex1),
+ leftChain,
+ segLeftLarge+1,
+ up_leftCornerIndex,
+ 1, //a increase chain,
+ pStream);
+
+ stripOfFanLeft(leftChain, segLeftLarge, segLeftSmall,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream, 0);
+
+
+ monoTriangulationRecGen(topVertex, rightGridChain->get_vertex(gridIndex1),
+ leftChain, leftStartIndex, segLeftSmall,
+ rightChain, rightStartIndex, up_rightCornerIndex,
+ pStream);
+ }//end left in right out
+ else if(rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
+ {
+ Int segRightSmall, segRightLarge;
+ findTopRightSegment(rightChain,
+ sep_right,
+ up_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex1),
+ segRightSmall,
+ segRightLarge);
+ assert(segRightLarge>=sep_right);
+ monoTriangulation2(rightChain->getVertex(segRightLarge),
+ rightGridChain->get_vertex(gridIndex1),
+ rightChain,
+ segRightLarge+1,
+ up_rightCornerIndex,
+ 0, //a decrease chain
+ pStream);
+ stripOfFanRight(rightChain, segRightLarge, segRightSmall,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream, 0);
+
+
+ monoTriangulationRecGen(topVertex, leftGridChain->get_vertex(gridIndex1),
+ leftChain, leftStartIndex, up_leftCornerIndex,
+ rightChain, rightStartIndex,segRightSmall,
+ pStream);
+
+ }//end left out rigth in
+ else //left out , right out
+ {
+
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }//end leftout, right out
+ }//end if separator exixts.
+ else //no separator
+ {
+
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+#endif
+ }//end if 0,2
+}//end if the function
+
+
+static void sampleCompTopSimpleOpt(gridWrap* grid,
+ Int gridV,
+ Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ if(gridV <= 0 || dec_end<dec_current || inc_end <inc_current)
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+ if(grid->get_v_value(gridV+1) >= topVertex[1])
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+ Int i,j,k;
+ Real currentV = grid->get_v_value(gridV+1);
+ if(inc_chain->getVertex(inc_end)[1] <= currentV &&
+ dec_chain->getVertex(dec_end)[1] < currentV)
+ {
+ //find i bottom up so that inc_chain[i]<= curentV and inc_chain[i-1] > currentV,
+ //find j botom up so that dec_chain[j] < currentV and dec_chain[j-1] >= currentV
+ for(i=inc_end; i >= inc_current; i--)
+ {
+ if(inc_chain->getVertex(i)[1] > currentV)
+ break;
+ }
+ i++;
+ for(j=dec_end; j >= dec_current; j--)
+ {
+ if(dec_chain->getVertex(j)[1] >= currentV)
+ break;
+ }
+ j++;
+ if(inc_chain->getVertex(i)[1] <= dec_chain->getVertex(j)[1])
+ {
+ //find the k so that dec_chain[k][1] < inc_chain[i][1]
+ for(k=j; k<=dec_end; k++)
+ {
+ if(dec_chain->getVertex(k)[1] < inc_chain->getVertex(i)[1])
+ break;
+ }
+ //we know that dec_chain[j][1] >= inc_chian[i][1]
+ //we know that dec_chain[k-1][1]>=inc_chain[i][1]
+ //we know that dec_chian[k][1] < inc_chain[i][1]
+ //find l in [j, k-1] so that dec_chain[l][0] 0 is closest to
+ // inc_chain[i]
+ int l;
+ Real tempI = Real(j);
+ Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
+ for(l=j+1; l<= k-1; l++)
+ {
+ if(fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0])
+ <= tempMin)
+ {
+ tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0]);
+ tempI = (Real)l;
+ }
+ }
+ //inc_chain[i] and dec_chain[tempI] are connected.
+ monoTriangulationRecGenOpt(dec_chain->getVertex((int)tempI),
+ botVertex,
+ inc_chain, i, inc_end,
+ dec_chain, (int)(tempI+1), dec_end,
+ pStream);
+ //recursively do the rest
+ sampleCompTopSimpleOpt(grid,
+ gridV+1,
+ topVertex, inc_chain->getVertex(i),
+ inc_chain, inc_current, i-1,
+ dec_chain, dec_current, (int)tempI,
+ pStream);
+ }
+ else
+ {
+ //find the k so that inc_chain[k][1] <= dec_chain[j][1]
+ for(k=i; k<=inc_end; k++)
+ {
+ if(inc_chain->getVertex(k)[1] <= dec_chain->getVertex(j)[1])
+ break;
+ }
+ //we know that inc_chain[i] > dec_chain[j]
+ //we know that inc_chain[k-1][1] > dec_chain[j][1]
+ //we know that inc_chain[k][1] <= dec_chain[j][1]
+ //so we find l between [i,k-1] so that
+ //inc_chain[l][0] is the closet to dec_chain[j][0]
+ int tempI = i;
+ int l;
+ Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
+ for(l=i+1; l<=k-1; l++)
+ {
+ if(fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]) <= tempMin)
+ {
+ tempMin = (Real)fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]);
+ tempI = l;
+ }
+ }
+
+ //inc_chain[tempI] and dec_chain[j] are connected
+
+ monoTriangulationRecGenOpt(inc_chain->getVertex(tempI),
+ botVertex,
+ inc_chain, tempI+1, inc_end,
+ dec_chain, j, dec_end,
+ pStream);
+
+ //recurvesily do the rest
+ sampleCompTopSimpleOpt(grid, gridV+1,
+ topVertex, dec_chain->getVertex(j),
+ inc_chain, inc_current, tempI,
+ dec_chain, dec_current, j-1,
+ pStream);
+ }
+ }
+ else //go to the next higher gridV
+ {
+ sampleCompTopSimpleOpt(grid,
+ gridV+1,
+ topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ }
+}
+
+void sampleCompTopSimple(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream)
+{
+ //the plan is to use monotriangulation algortihm.
+ Int i,k;
+ Real* ActualTop;
+ Real* ActualBot;
+ Int ActualLeftStart, ActualLeftEnd;
+ Int ActualRightStart, ActualRightEnd;
+
+ //creat an array to store the points on the grid line
+ gridWrap* grid = leftGridChain->getGrid();
+ Int gridV = leftGridChain->getVlineIndex(gridIndex1);
+ Int gridLeftU = leftGridChain->getUlineIndex(gridIndex1);
+ Int gridRightU = rightGridChain->getUlineIndex(gridIndex1);
+
+ Real2* gridPoints = (Real2*) malloc(sizeof(Real2) * (gridRightU - gridLeftU +1));
+ assert(gridPoints);
+
+ for(k=0, i=gridRightU; i>= gridLeftU; i--, k++)
+ {
+ gridPoints[k][0] = grid->get_u_value(i);
+ gridPoints[k][1] = grid->get_v_value(gridV);
+ }
+
+ if(up_leftCornerWhere != 2)
+ ActualRightStart = rightStartIndex;
+ else
+ ActualRightStart = up_leftCornerIndex+1; //up_leftCornerIndex will be the ActualTop
+
+ if(up_rightCornerWhere != 2) //right corner is not on right chain
+ ActualRightEnd = rightStartIndex-1; //meaning that there is no actual rigth section
+ else
+ ActualRightEnd = up_rightCornerIndex;
+
+ vertexArray ActualRightChain(max(0, ActualRightEnd-ActualRightStart+1) + gridRightU-gridLeftU+1);
+
+ for(i=ActualRightStart; i<= ActualRightEnd; i++)
+ ActualRightChain.appendVertex(rightChain->getVertex(i));
+ for(i=0; i<gridRightU-gridLeftU+1; i++)
+ ActualRightChain.appendVertex(gridPoints[i]);
+
+ //determine ActualLeftEnd
+ if(up_leftCornerWhere != 0)
+ ActualLeftEnd = leftStartIndex-1;
+ else
+ ActualLeftEnd = up_leftCornerIndex;
+
+ if(up_rightCornerWhere != 0)
+ ActualLeftStart = leftStartIndex;
+ else
+ ActualLeftStart = up_rightCornerIndex+1; //up_rightCornerIndex will be the actual top
+
+ if(up_leftCornerWhere == 0)
+ {
+ if(up_rightCornerWhere == 0)
+ ActualTop = leftChain->getVertex(up_rightCornerIndex);
+ else
+ ActualTop = topVertex;
+ }
+ else if(up_leftCornerWhere == 1)
+ ActualTop = topVertex;
+ else //up_leftCornerWhere == 2
+ ActualTop = rightChain->getVertex(up_leftCornerIndex);
+
+ ActualBot = gridPoints[gridRightU - gridLeftU];
+
+
+
+
+ if(leftChain->getVertex(ActualLeftEnd)[1] == ActualBot[1])
+ {
+/*
+ monoTriangulationRecGenOpt(ActualTop, leftChain->getVertex(ActualLeftEnd),
+ leftChain,
+ ActualLeftStart, ActualLeftEnd-1,
+ &ActualRightChain,
+ 0,
+ ActualRightChain.getNumElements()-1,
+ pStream);
+*/
+
+ sampleCompTopSimpleOpt(grid, gridV,
+ ActualTop, leftChain->getVertex(ActualLeftEnd),
+ leftChain,
+ ActualLeftStart, ActualLeftEnd-1,
+ &ActualRightChain,
+ 0,
+ ActualRightChain.getNumElements()-1,
+ pStream);
+
+ }
+ else
+ {
+/*
+ monoTriangulationRecGenOpt(ActualTop, ActualBot, leftChain,
+ ActualLeftStart, ActualLeftEnd,
+ &ActualRightChain,
+ 0, ActualRightChain.getNumElements()-2, //the last is the bot.
+ pStream);
+*/
+
+ sampleCompTopSimpleOpt(grid, gridV,
+ ActualTop, ActualBot, leftChain,
+ ActualLeftStart, ActualLeftEnd,
+ &ActualRightChain,
+ 0, ActualRightChain.getNumElements()-2, //the last is the bot.
+ pStream);
+
+
+ }
+
+ free(gridPoints);
+
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h
new file mode 100644
index 000000000..95598d63a
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h
@@ -0,0 +1,67 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLECOMPTOP_H
+#define _SAMPLECOMPTOP_H
+
+#include "sampleMonoPoly.h"
+
+void sampleCompTop(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream);
+
+void sampleCompTopSimple(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream);
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc
new file mode 100644
index 000000000..051f24108
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc
@@ -0,0 +1,2427 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifndef max
+#define max(a,b) ((a>b)? a:b)
+#endif
+#ifndef min
+#define min(a,b) ((a>b)? b:a)
+#endif
+
+#include <GL/gl.h>
+
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampleMonoPoly.h"
+#include "sampleComp.h"
+#include "polyDBG.h"
+#include "partitionX.h"
+
+
+#define ZERO 0.00001
+
+//#define MYDEBUG
+
+//#define SHORTEN_GRID_LINE
+//see work/newtess/internal/test/problems
+
+
+/*split a polygon so that each vertex correcpond to one edge
+ *the head of the first edge of the returned plygon must be the head of the first
+ *edge of the origianl polygon. This is crucial for the code in sampleMonoPoly function
+ */
+ directedLine* polygonConvert(directedLine* polygon)
+{
+ int i;
+ directedLine* ret;
+ sampledLine* sline;
+ sline = new sampledLine(2);
+ sline->setPoint(0, polygon->getVertex(0));
+ sline->setPoint(1, polygon->getVertex(1));
+ ret=new directedLine(INCREASING, sline);
+ for(i=1; i<= polygon->get_npoints()-2; i++)
+ {
+ sline = new sampledLine(2);
+ sline->setPoint(0, polygon->getVertex(i));
+ sline->setPoint(1, polygon->getVertex(i+1));
+ ret->insert(new directedLine(INCREASING, sline));
+ }
+
+ for(directedLine *temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ {
+ for(i=0; i<= temp->get_npoints()-2; i++)
+ {
+ sline = new sampledLine(2);
+ sline->setPoint(0, temp->getVertex(i));
+ sline->setPoint(1, temp->getVertex(i+1));
+ ret->insert(new directedLine(INCREASING, sline));
+ }
+ }
+ return ret;
+}
+
+void triangulateConvexPolyVertical(directedLine* topV, directedLine* botV, primStream *pStream)
+{
+ Int i,j;
+ Int n_leftVerts;
+ Int n_rightVerts;
+ Real** leftVerts;
+ Real** rightVerts;
+ directedLine* tempV;
+ n_leftVerts = 0;
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ n_leftVerts += tempV->get_npoints();
+ }
+ n_rightVerts=0;
+ for(tempV = botV; tempV != topV; tempV = tempV->getNext())
+ {
+ n_rightVerts += tempV->get_npoints();
+ }
+
+ Real2* temp_leftVerts = (Real2 *) malloc(sizeof(Real2) * n_leftVerts);
+ assert(temp_leftVerts);
+ Real2* temp_rightVerts = (Real2 *) malloc(sizeof(Real2) * n_rightVerts);
+ assert(temp_rightVerts);
+
+ leftVerts = (Real**) malloc(sizeof(Real2*) * n_leftVerts);
+ assert(leftVerts);
+ rightVerts = (Real**) malloc(sizeof(Real2*) * n_rightVerts);
+ assert(rightVerts);
+ for(i=0; i<n_leftVerts; i++)
+ leftVerts[i] = temp_leftVerts[i];
+ for(i=0; i<n_rightVerts; i++)
+ rightVerts[i] = temp_rightVerts[i];
+
+ i=0;
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ for(j=1; j<tempV->get_npoints(); j++)
+ {
+ leftVerts[i][0] = tempV->getVertex(j)[0];
+ leftVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ n_leftVerts = i;
+ i=0;
+ for(tempV = topV->getPrev(); tempV != botV->getPrev(); tempV = tempV->getPrev())
+ {
+ for(j=tempV->get_npoints()-1; j>=1; j--)
+ {
+ rightVerts[i][0] = tempV->getVertex(j)[0];
+ rightVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ n_rightVerts = i;
+ triangulateXYMonoTB(n_leftVerts, leftVerts, n_rightVerts, rightVerts, pStream);
+ free(leftVerts);
+ free(rightVerts);
+ free(temp_leftVerts);
+ free(temp_rightVerts);
+}
+
+void triangulateConvexPolyHoriz(directedLine* leftV, directedLine* rightV, primStream *pStream)
+{
+ Int i,j;
+ Int n_lowerVerts;
+ Int n_upperVerts;
+ Real2 *lowerVerts;
+ Real2 *upperVerts;
+ directedLine* tempV;
+ n_lowerVerts=0;
+ for(tempV = leftV; tempV != rightV; tempV = tempV->getNext())
+ {
+ n_lowerVerts += tempV->get_npoints();
+ }
+ n_upperVerts=0;
+ for(tempV = rightV; tempV != leftV; tempV = tempV->getNext())
+ {
+ n_upperVerts += tempV->get_npoints();
+ }
+ lowerVerts = (Real2 *) malloc(sizeof(Real2) * n_lowerVerts);
+ assert(n_lowerVerts);
+ upperVerts = (Real2 *) malloc(sizeof(Real2) * n_upperVerts);
+ assert(n_upperVerts);
+ i=0;
+ for(tempV = leftV; tempV != rightV; tempV = tempV->getNext())
+ {
+ for(j=0; j<tempV->get_npoints(); j++)
+ {
+ lowerVerts[i][0] = tempV->getVertex(j)[0];
+ lowerVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ i=0;
+ for(tempV = leftV->getPrev(); tempV != rightV->getPrev(); tempV = tempV->getPrev())
+ {
+ for(j=tempV->get_npoints()-1; j>=0; j--)
+ {
+ upperVerts[i][0] = tempV->getVertex(j)[0];
+ upperVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ triangulateXYMono(n_upperVerts, upperVerts, n_lowerVerts, lowerVerts, pStream);
+ free(lowerVerts);
+ free(upperVerts);
+}
+void triangulateConvexPoly(directedLine* polygon, Int ulinear, Int vlinear, primStream* pStream)
+{
+ /*find left, right, top , bot
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ directedLine* leftV;
+ directedLine* rightV;
+ topV = botV = polygon;
+
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+
+ botV = tempV;
+ }
+ }
+ //find leftV
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ if(tempV->tail()[0] >= tempV->head()[0])
+ break;
+ }
+ leftV = tempV;
+ //find rightV
+ for(tempV = botV; tempV != topV; tempV = tempV->getNext())
+ {
+ if(tempV->tail()[0] <= tempV->head()[0])
+ break;
+ }
+ rightV = tempV;
+ if(vlinear)
+ {
+ triangulateConvexPolyHoriz( leftV, rightV, pStream);
+ }
+ else if(ulinear)
+ {
+ triangulateConvexPolyVertical(topV, botV, pStream);
+ }
+ else
+ {
+ if(DBG_is_U_direction(polygon))
+ {
+ triangulateConvexPolyHoriz( leftV, rightV, pStream);
+ }
+ else
+ triangulateConvexPolyVertical(topV, botV, pStream);
+ }
+}
+
+/*for debug purpose*/
+void drawCorners(
+ Real* topV, Real* botV,
+ vertexArray* leftChain,
+ vertexArray* rightChain,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int gridIndex2,
+ Int leftCornerWhere,
+ Int leftCornerIndex,
+ Int rightCornerWhere,
+ Int rightCornerIndex,
+ Int bot_leftCornerWhere,
+ Int bot_leftCornerIndex,
+ Int bot_rightCornerWhere,
+ Int bot_rightCornerIndex)
+{
+ Real* leftCornerV;
+ Real* rightCornerV;
+ Real* bot_leftCornerV;
+ Real* bot_rightCornerV;
+
+ if(leftCornerWhere == 1)
+ leftCornerV = topV;
+ else if(leftCornerWhere == 0)
+ leftCornerV = leftChain->getVertex(leftCornerIndex);
+ else
+ leftCornerV = rightChain->getVertex(leftCornerIndex);
+
+ if(rightCornerWhere == 1)
+ rightCornerV = topV;
+ else if(rightCornerWhere == 0)
+ rightCornerV = leftChain->getVertex(rightCornerIndex);
+ else
+ rightCornerV = rightChain->getVertex(rightCornerIndex);
+
+ if(bot_leftCornerWhere == 1)
+ bot_leftCornerV = botV;
+ else if(bot_leftCornerWhere == 0)
+ bot_leftCornerV = leftChain->getVertex(bot_leftCornerIndex);
+ else
+ bot_leftCornerV = rightChain->getVertex(bot_leftCornerIndex);
+
+ if(bot_rightCornerWhere == 1)
+ bot_rightCornerV = botV;
+ else if(bot_rightCornerWhere == 0)
+ bot_rightCornerV = leftChain->getVertex(bot_rightCornerIndex);
+ else
+ bot_rightCornerV = rightChain->getVertex(bot_rightCornerIndex);
+
+ Real topGridV = leftGridChain->get_v_value(gridIndex1);
+ Real topGridU1 = leftGridChain->get_u_value(gridIndex1);
+ Real topGridU2 = rightGridChain->get_u_value(gridIndex1);
+ Real botGridV = leftGridChain->get_v_value(gridIndex2);
+ Real botGridU1 = leftGridChain->get_u_value(gridIndex2);
+ Real botGridU2 = rightGridChain->get_u_value(gridIndex2);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(leftCornerV);
+ glVertex2f(topGridU1, topGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(rightCornerV);
+ glVertex2f(topGridU2, topGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(bot_leftCornerV);
+ glVertex2f(botGridU1, botGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(bot_rightCornerV);
+ glVertex2f(botGridU2, botGridV);
+ glEnd();
+
+
+}
+
+void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain)
+{
+ Int i;
+ directedLine* tempV;
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ leftChain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ leftChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+}
+
+
+void findTopAndBot(directedLine* polygon, directedLine*& topV, directedLine*& botV)
+{
+ assert(polygon);
+ directedLine* tempV;
+ topV = botV = polygon;
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+}
+
+void findGridChains(directedLine* topV, directedLine* botV,
+ gridWrap* grid,
+ gridBoundaryChain*& leftGridChain,
+ gridBoundaryChain*& rightGridChain)
+{
+ /*find the first(top) and the last (bottom) grid line which intersect the
+ *this polygon
+ */
+ Int firstGridIndex; /*the index in the grid*/
+ Int lastGridIndex;
+
+ firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1));
+
+ if(botV->head()[1] < grid->get_v_min())
+ lastGridIndex = 0;
+ else
+ lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1;
+
+ /*find the interval inside the polygon for each gridline*/
+ Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridIndices);
+ Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridIndices);
+ Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridInnerIndices);
+ Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridInnerIndices);
+
+ findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices);
+
+ findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices);
+
+ leftGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices);
+
+ rightGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices);
+
+ free(leftGridIndices);
+ free(rightGridIndices);
+ free(leftGridInnerIndices);
+ free(rightGridInnerIndices);
+}
+
+void findDownCorners(Real *botVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/
+ Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/
+ )
+{
+#ifdef MYDEBUG
+printf("*************enter find donw corner\n");
+printf("finddownCorner: v=%f, uleft=%f, uright=%f\n", v, uleft, uright);
+printf("(%i,%i,%i,%i)\n", leftChainStartIndex, leftChainEndIndex,rightChainStartIndex, rightChainEndIndex);
+printf("left chain is\n");
+leftChain->print();
+printf("right chain is\n");
+rightChain->print();
+#endif
+
+ assert(v > botVertex[1]);
+ Real leftGridPoint[2];
+ leftGridPoint[0] = uleft;
+ leftGridPoint[1] = v;
+ Real rightGridPoint[2];
+ rightGridPoint[0] = uright;
+ rightGridPoint[1] = v;
+
+ Int i;
+ Int index1, index2;
+
+ index1 = leftChain->findIndexBelowGen(v, leftChainStartIndex, leftChainEndIndex);
+ index2 = rightChain->findIndexBelowGen(v, rightChainStartIndex, rightChainEndIndex);
+
+ if(index2 <= rightChainEndIndex) //index2 was found above
+ index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex);
+
+ if(index1>leftChainEndIndex && index2 > rightChainEndIndex) /*no point below v on left chain or right chain*/
+ {
+
+ /*the botVertex is the only vertex below v*/
+ ret_leftCornerWhere = 1;
+ ret_rightCornerWhere = 1;
+ }
+ else if(index1>leftChainEndIndex ) /*index2 <= rightChainEndIndex*/
+ {
+
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+
+
+ Real tempMin = rightChain->getVertex(index2)[0];
+ Int tempI = index2;
+ for(i=index2+1; i<= rightChainEndIndex; i++)
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+
+
+ //we consider whether we can use botVertex as left corner. First check
+ //if (leftGirdPoint, botVertex) interesects right chian or not.
+ if(DBG_intersectChain(rightChain, rightChainStartIndex,rightChainEndIndex,
+ leftGridPoint, botVertex))
+ {
+ ret_leftCornerWhere = 2;//right
+ ret_leftCornerIndex = index2; //should use tempI???
+ }
+ else if(botVertex[0] < tempMin)
+ ret_leftCornerWhere = 1; //bot
+ else
+ {
+ ret_leftCornerWhere = 2; //right
+ ret_leftCornerIndex = tempI;
+ }
+ }
+ else if(index2> rightChainEndIndex) /*index1<=leftChainEndIndex*/
+ {
+ ret_leftCornerWhere = 0; /*left chain*/
+ ret_leftCornerIndex = index1;
+
+ /*find the vertex on the left chain with the maximum u,
+ *either this vertex or the botvertex can be used as the right corner
+ */
+
+ Int tempI;
+ //skip those points which are equal to v. (avoid degeneratcy)
+ for(tempI = index1; tempI <= leftChainEndIndex; tempI++)
+ if(leftChain->getVertex(tempI)[1] < v)
+ break;
+ if(tempI > leftChainEndIndex)
+ ret_rightCornerWhere = 1;
+ else
+ {
+ Real tempMax = leftChain->getVertex(tempI)[0];
+ for(i=tempI; i<= leftChainEndIndex; i++)
+ if(leftChain->getVertex(i)[0] > tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+
+
+
+ //we consider whether we can use botVertex as a corner. So first we check
+ //whether (rightGridPoint, botVertex) interescts the left chain or not.
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex,
+ rightGridPoint, botVertex))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1; //should use tempI???
+ }
+ else if(botVertex[0] > tempMax)
+ {
+
+ ret_rightCornerWhere = 1;
+ }
+ else
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = tempI;
+ }
+ }
+
+ }
+ else /*index1<=leftChainEndIndex and index2 <=rightChainEndIndex*/
+ {
+ if(leftChain->getVertex(index1)[1] >= rightChain->getVertex(index2)[1]) /*left point above right point*/
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+
+ Real tempMax;
+ Int tempI;
+
+ tempI = index1;
+ tempMax = leftChain->getVertex(index1)[0];
+
+ /*find the maximum u for all the points on the left above the right point index2*/
+ for(i=index1+1; i<= leftChainEndIndex; i++)
+ {
+ if(leftChain->getVertex(i)[1] < rightChain->getVertex(index2)[1])
+ break;
+
+ if(leftChain->getVertex(i)[0]>tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+ }
+ //we consider if we can use rightChain(index2) as right corner
+ //we check if (rightChain(index2), rightGidPoint) intersecs left chain or not.
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2)))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1; //should use tempI???
+ }
+ else if(tempMax >= rightChain->getVertex(index2)[0] ||
+ tempMax >= uright
+ )
+ {
+
+ ret_rightCornerWhere = 0; /*on left Chain*/
+ ret_rightCornerIndex = tempI;
+ }
+ else
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+ }
+ }
+ else /*left below right*/
+ {
+ ret_rightCornerWhere = 2; /*on the right*/
+ ret_rightCornerIndex = index2;
+
+ Real tempMin;
+ Int tempI;
+
+ tempI = index2;
+ tempMin = rightChain->getVertex(index2)[0];
+
+ /*find the minimum u for all the points on the right above the left poitn index1*/
+ for(i=index2+1; i<= rightChainEndIndex; i++)
+ {
+ if( rightChain->getVertex(i)[1] < leftChain->getVertex(index1)[1])
+ break;
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+ }
+
+ //we consider if we can use leftchain(index1) as left corner.
+ //we check if (leftChain(index1) intersects right chian or not
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, leftGridPoint, leftChain->getVertex(index1)))
+ {
+ ret_leftCornerWhere = 2;
+ ret_leftCornerIndex = index2; //should use tempI???
+ }
+ else if(tempMin <= leftChain->getVertex(index1)[0] ||
+ tempMin <= uleft)
+ {
+ ret_leftCornerWhere = 2; /* on right chain*/
+ ret_leftCornerIndex = tempI;
+ }
+ else
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+ }
+ }
+ }
+
+}
+
+
+void findUpCorners(Real *topVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/
+ Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/
+ )
+{
+#ifdef MYDEBUG
+printf("***********enter findUpCorners\n");
+#endif
+
+ assert(v < topVertex[1]);
+ Real leftGridPoint[2];
+ leftGridPoint[0] = uleft;
+ leftGridPoint[1] = v;
+ Real rightGridPoint[2];
+ rightGridPoint[0] = uright;
+ rightGridPoint[1] = v;
+
+ Int i;
+ Int index1, index2;
+
+ index1 = leftChain->findIndexFirstAboveEqualGen(v, leftChainStartIndex, leftChainEndIndex);
+
+
+ index2 = rightChain->findIndexFirstAboveEqualGen(v, rightChainStartIndex, rightChainEndIndex);
+
+ if(index2>= leftChainStartIndex) //index2 was found above
+ index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex);
+
+ if(index1<leftChainStartIndex && index2 <rightChainStartIndex) /*no point above v on left chain or right chain*/
+ {
+ /*the topVertex is the only vertex above v*/
+ ret_leftCornerWhere = 1;
+ ret_rightCornerWhere = 1;
+ }
+ else if(index1<leftChainStartIndex ) /*index2 >= rightChainStartIndex*/
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+
+ //find the minimum u on right top, either that, or top, or right[index2] is the left corner
+ Real tempMin = rightChain->getVertex(index2)[0];
+ Int tempI = index2;
+ for(i=index2-1; i>=rightChainStartIndex; i--)
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempMin = rightChain->getVertex(i)[0];
+ tempI = i;
+ }
+ //chech whether (leftGridPoint, top) intersects rightchai,
+ //if yes, use right corner as left corner
+ //if not, use top or right[tempI] as left corner
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex,
+ leftGridPoint, topVertex))
+ {
+ ret_leftCornerWhere = 2; //rightChain
+ ret_leftCornerIndex = index2;
+ }
+ else if(topVertex[0] < tempMin)
+ ret_leftCornerWhere = 1; /*topvertex*/
+ else
+ {
+ ret_leftCornerWhere = 2; //right chain
+ ret_leftCornerIndex = tempI;
+ }
+
+ }
+ else if(index2< rightChainStartIndex) /*index1>=leftChainStartIndex*/
+ {
+ ret_leftCornerWhere = 0; /*left chain*/
+ ret_leftCornerIndex = index1;
+
+ //find the maximum u on the left top section. either that or topvertex, or left[index1] is the right corner
+ Real tempMax = leftChain->getVertex(index1)[0];
+ Int tempI = index1;
+
+ for(i=index1-1; i>=leftChainStartIndex; i--){
+
+ if(leftChain->getVertex(i)[0] > tempMax)
+ {
+
+ tempMax = leftChain->getVertex(i)[0];
+ tempI = i;
+ }
+ }
+ //check whether (rightGridPoint, top) intersects leftChain or not
+ //if yes, we use leftCorner as the right corner
+ //if not, we use either top or left[tempI] as the right corner
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex,
+ rightGridPoint, topVertex))
+ {
+ ret_rightCornerWhere = 0; //left chan
+ ret_rightCornerIndex = index1;
+ }
+ else if(topVertex[0] > tempMax)
+ ret_rightCornerWhere = 1;//topVertex
+ else
+ {
+ ret_rightCornerWhere = 0;//left chain
+ ret_rightCornerIndex = tempI;
+ }
+ }
+ else /*index1>=leftChainStartIndex and index2 >=rightChainStartIndex*/
+ {
+ if(leftChain->getVertex(index1)[1] <= rightChain->getVertex(index2)[1]) /*left point below right point*/
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+
+ Real tempMax;
+ Int tempI;
+
+ tempI = index1;
+ tempMax = leftChain->getVertex(index1)[0];
+
+ /*find the maximum u for all the points on the left below the right point index2*/
+ for(i=index1-1; i>= leftChainStartIndex; i--)
+ {
+ if(leftChain->getVertex(i)[1] > rightChain->getVertex(index2)[1])
+ break;
+
+ if(leftChain->getVertex(i)[0]>tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+ }
+ //chek whether (rightChain(index2), rightGridPoint) intersects leftchian or not
+ if(DBG_intersectChain(leftChain, leftChainStartIndex, leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2)))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1;
+ }
+ else if(tempMax >= rightChain->getVertex(index2)[0] ||
+ tempMax >= uright)
+ {
+ ret_rightCornerWhere = 0; /*on left Chain*/
+ ret_rightCornerIndex = tempI;
+ }
+ else
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+ }
+ }
+ else /*left above right*/
+ {
+ ret_rightCornerWhere = 2; /*on the right*/
+ ret_rightCornerIndex = index2;
+
+ Real tempMin;
+ Int tempI;
+
+ tempI = index2;
+ tempMin = rightChain->getVertex(index2)[0];
+
+ /*find the minimum u for all the points on the right below the left poitn index1*/
+ for(i=index2-1; i>= rightChainStartIndex; i--)
+ {
+ if( rightChain->getVertex(i)[1] > leftChain->getVertex(index1)[1])
+ break;
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+ }
+ //check whether (leftGRidPoint,left(index1)) interesect right chain
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex,
+ leftGridPoint, leftChain->getVertex(index1)))
+ {
+ ret_leftCornerWhere = 2; //right
+ ret_leftCornerIndex = index2;
+ }
+ else if(tempMin <= leftChain->getVertex(index1)[0] ||
+ tempMin <= uleft)
+ {
+ ret_leftCornerWhere = 2; /* on right chain*/
+ ret_leftCornerIndex = tempI;
+ }
+ else
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+ }
+ }
+ }
+#ifdef MYDEBUG
+printf("***********leave findUpCorners\n");
+#endif
+}
+
+//return 1 if neck exists, 0 othewise
+Int findNeckF(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ Int& neckLeft,
+ Int& neckRight)
+{
+/*
+printf("enter findNeckF, botleft, botright=%i,%i,gstartindex=%i\n",botLeftIndex,botRightIndex,gridStartIndex);
+printf("leftChain is\n");
+leftChain->print();
+printf("rightChain is\n");
+rightChain->print();
+*/
+
+ Int lowerGridIndex; //the grid below leftChain and rightChian vertices
+ Int i;
+ Int n_vlines = leftGridChain->get_nVlines();
+ Real v;
+ if(botLeftIndex >= leftChain->getNumElements() ||
+ botRightIndex >= rightChain->getNumElements())
+ return 0; //no neck exists
+
+ v=min(leftChain->getVertex(botLeftIndex)[1], rightChain->getVertex(botRightIndex)[1]);
+
+
+
+
+ for(i=gridStartIndex; i<n_vlines; i++)
+ if(leftGridChain->get_v_value(i) <= v &&
+ leftGridChain->getUlineIndex(i)<= rightGridChain->getUlineIndex(i))
+ break;
+
+ lowerGridIndex = i;
+
+ if(lowerGridIndex == n_vlines) //the two trm vertex are higher than all gridlines
+ return 0;
+ else
+ {
+ Int botLeft2, botRight2;
+/*
+printf("leftGridChain->get_v_)value=%f\n",leftGridChain->get_v_value(lowerGridIndex), botLeftIndex);
+printf("leftChain->get_vertex(0)=(%f,%f)\n", leftChain->getVertex(0)[0],leftChain->getVertex(0)[1]);
+printf("leftChain->get_vertex(1)=(%f,%f)\n", leftChain->getVertex(1)[0],leftChain->getVertex(1)[1]);
+printf("leftChain->get_vertex(2)=(%f,%f)\n", leftChain->getVertex(2)[0],leftChain->getVertex(2)[1]);
+*/
+ botLeft2 = leftChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botLeftIndex, leftChain->getNumElements()-1) -1 ;
+
+/*
+printf("botLeft2=%i\n", botLeft2);
+printf("leftChain->getNumElements=%i\n", leftChain->getNumElements());
+*/
+
+ botRight2 = rightChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botRightIndex, rightChain->getNumElements()-1) -1;
+ if(botRight2 < botRightIndex) botRight2=botRightIndex;
+
+ if(botLeft2 < botLeftIndex) botLeft2 = botLeftIndex;
+
+ assert(botLeft2 >= botLeftIndex);
+ assert(botRight2 >= botRightIndex);
+ //find nectLeft so that it is th erightmost vertex on letChain
+
+ Int tempI = botLeftIndex;
+ Real temp = leftChain->getVertex(tempI)[0];
+ for(i=botLeftIndex+1; i<= botLeft2; i++)
+ if(leftChain->getVertex(i)[0] > temp)
+ {
+ temp = leftChain->getVertex(i)[0];
+ tempI = i;
+ }
+ neckLeft = tempI;
+
+ tempI = botRightIndex;
+ temp = rightChain->getVertex(tempI)[0];
+ for(i=botRightIndex+1; i<= botRight2; i++)
+ if(rightChain->getVertex(i)[0] < temp)
+ {
+ temp = rightChain->getVertex(i)[0];
+ tempI = i;
+ }
+ neckRight = tempI;
+ return 1;
+ }
+}
+
+
+
+/*find i>=botLeftIndex,j>=botRightIndex so that
+ *(leftChain[i], rightChain[j]) is a neck.
+ */
+void findNeck(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ Int& leftLastIndex, /*left point of the neck*/
+ Int& rightLastIndex /*right point of the neck*/
+ )
+{
+ assert(botLeftIndex < leftChain->getNumElements() &&
+ botRightIndex < rightChain->getNumElements());
+
+ /*now the neck exists for sure*/
+
+ if(leftChain->getVertex(botLeftIndex)[1] <= rightChain->getVertex(botRightIndex)[1]) //left below right
+ {
+
+ leftLastIndex = botLeftIndex;
+
+ /*find i so that rightChain[i][1] >= leftchainbotverte[1], and i+1<
+ */
+ rightLastIndex=rightChain->findIndexAboveGen(leftChain->getVertex(botLeftIndex)[1], botRightIndex+1, rightChain->getNumElements()-1);
+ }
+ else //left above right
+ {
+
+ rightLastIndex = botRightIndex;
+
+ leftLastIndex = leftChain->findIndexAboveGen(rightChain->getVertex(botRightIndex)[1],
+ botLeftIndex+1,
+ leftChain->getNumElements()-1);
+ }
+}
+
+
+
+void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices)
+{
+
+ Int i,k,isHoriz = 0;
+ Int n_ulines = grid->get_n_ulines();
+ Real uMin = grid->get_u_min();
+ Real uMax = grid->get_u_max();
+ /*
+ Real vMin = grid->get_v_min();
+ Real vMax = grid->get_v_max();
+ */
+ Real slop = 0.0, uinterc;
+
+#ifdef SHORTEN_GRID_LINE
+ //uintercBuf stores all the interction u value for each grid line
+ //notice that lastGridIndex<= firstGridIndex
+ Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1));
+ assert(uintercBuf);
+#endif
+
+ /*initialization to make vtail bigger than grid->...*/
+ directedLine* dLine = topEdge;
+ Real vtail = grid->get_v_value(firstGridIndex) + 1.0;
+ Real tempMaxU = grid->get_u_min();
+
+
+ /*for each grid line*/
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+
+ Real grid_v_value = grid->get_v_value(i);
+
+ /*check whether this grid line is below the current trim edge.*/
+ if(vtail > grid_v_value)
+ {
+ /*since the grid line is below the trim edge, we
+ *find the trim edge which will contain the trim line
+ */
+ while( (vtail=dLine->tail()[1]) > grid_v_value){
+
+ tempMaxU = max(tempMaxU, dLine->tail()[0]);
+ dLine = dLine -> getNext();
+ }
+
+ if( fabs(dLine->head()[1] - vtail) < ZERO)
+ isHoriz = 1;
+ else
+ {
+ isHoriz = 0;
+ slop = (dLine->head()[0] - dLine->tail()[0]) / (dLine->head()[1]-vtail);
+ }
+ }
+
+ if(isHoriz)
+ {
+ uinterc = max(dLine->head()[0], dLine->tail()[0]);
+ }
+ else
+ {
+ uinterc = slop * (grid_v_value - vtail) + dLine->tail()[0];
+ }
+
+ tempMaxU = max(tempMaxU, uinterc);
+
+ if(uinterc < uMin && uinterc >= uMin - ZERO)
+ uinterc = uMin;
+ if(uinterc > uMax && uinterc <= uMax + ZERO)
+ uinterc = uMax;
+
+#ifdef SHORTEN_GRID_LINE
+ uintercBuf[k] = uinterc;
+#endif
+
+ assert(uinterc >= uMin && uinterc <= uMax);
+ if(uinterc == uMax)
+ ret_indices[k] = n_ulines-1;
+ else
+ ret_indices[k] = (Int)(((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1;
+ if(ret_indices[k] >= n_ulines)
+ ret_indices[k] = n_ulines-1;
+
+
+ ret_innerIndices[k] = (Int)(((tempMaxU-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1;
+
+ /*reinitialize tempMaxU for next grdiLine*/
+ tempMaxU = uinterc;
+ }
+#ifdef SHORTEN_GRID_LINE
+ //for each grid line, compare the left grid point with the
+ //intersection point. If the two points are too close, then
+ //we should move the grid point one grid to the right
+ //and accordingly we should update the inner index.
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+ //check gridLine i
+ //check ret_indices[k]
+ Real a = grid->get_u_value(ret_indices[k]-1);
+ Real b = grid->get_u_value(ret_indices[k]);
+ assert(uintercBuf[k] >= a && uintercBuf < b);
+ if( (b-uintercBuf[k]) <= 0.2 * (b-a)) //interc is very close to b
+ {
+ ret_indices[k]++;
+ }
+
+ //check ret_innerIndices[k]
+ if(k>0)
+ {
+ if(ret_innerIndices[k] < ret_indices[k-1])
+ ret_innerIndices[k] = ret_indices[k-1];
+ if(ret_innerIndices[k] < ret_indices[k])
+ ret_innerIndices[k] = ret_indices[k];
+ }
+ }
+ //clean up
+ free(uintercBuf);
+#endif
+}
+
+void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices)
+{
+
+ Int i,k;
+ Int n_ulines = grid->get_n_ulines();
+ Real uMin = grid->get_u_min();
+ Real uMax = grid->get_u_max();
+ /*
+ Real vMin = grid->get_v_min();
+ Real vMax = grid->get_v_max();
+ */
+ Real slop = 0.0, uinterc;
+
+#ifdef SHORTEN_GRID_LINE
+ //uintercBuf stores all the interction u value for each grid line
+ //notice that firstGridIndex >= lastGridIndex
+ Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1));
+ assert(uintercBuf);
+#endif
+
+ /*initialization to make vhead bigger than grid->v_value...*/
+ directedLine* dLine = topEdge->getPrev();
+ Real vhead = dLine->tail()[1];
+ Real tempMinU = grid->get_u_max();
+
+ /*for each grid line*/
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+
+ Real grid_v_value = grid->get_v_value(i);
+
+
+ /*check whether this grid line is below the current trim edge.*/
+ if(vhead >= grid_v_value)
+ {
+ /*since the grid line is below the tail of the trim edge, we
+ *find the trim edge which will contain the trim line
+ */
+ while( (vhead=dLine->head()[1]) > grid_v_value){
+ tempMinU = min(tempMinU, dLine->head()[0]);
+ dLine = dLine -> getPrev();
+ }
+
+ /*skip the equality in the case of degenerat case: horizontal */
+ while(dLine->head()[1] == grid_v_value)
+ dLine = dLine->getPrev();
+
+ assert( dLine->tail()[1] != dLine->head()[1]);
+ slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-dLine->head()[1]);
+ /*
+ if(dLine->tail()[1] == vhead)
+ isHoriz = 1;
+ else
+ {
+ isHoriz = 0;
+ slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-vhead);
+ }
+ */
+ }
+ uinterc = slop * (grid_v_value - dLine->head()[1]) + dLine->head()[0];
+
+ //in case unterc is outside of the grid due to floating point
+ if(uinterc < uMin)
+ uinterc = uMin;
+ else if(uinterc > uMax)
+ uinterc = uMax;
+
+#ifdef SHORTEN_GRID_LINE
+ uintercBuf[k] = uinterc;
+#endif
+
+ tempMinU = min(tempMinU, uinterc);
+
+ assert(uinterc >= uMin && uinterc <= uMax);
+
+ if(uinterc == uMin)
+ ret_indices[k] = 0;
+ else
+ ret_indices[k] = (int)ceil((((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1))) -1;
+/*
+if(ret_indices[k] >= grid->get_n_ulines())
+ {
+ printf("ERROR3\n");
+ exit(0);
+}
+if(ret_indices[k] < 0)
+ {
+ printf("ERROR4\n");
+ exit(0);
+}
+*/
+ ret_innerIndices[k] = (int)ceil ((((tempMinU-uMin)/(uMax - uMin)) * (n_ulines-1))) -1;
+
+ tempMinU = uinterc;
+ }
+#ifdef SHORTEN_GRID_LINE
+ //for each grid line, compare the left grid point with the
+ //intersection point. If the two points are too close, then
+ //we should move the grid point one grid to the right
+ //and accordingly we should update the inner index.
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+ //check gridLine i
+ //check ret_indices[k]
+ Real a = grid->get_u_value(ret_indices[k]);
+ Real b = grid->get_u_value(ret_indices[k]+1);
+ assert(uintercBuf[k] > a && uintercBuf <= b);
+ if( (uintercBuf[k]-a) <= 0.2 * (b-a)) //interc is very close to a
+ {
+ ret_indices[k]--;
+ }
+
+ //check ret_innerIndices[k]
+ if(k>0)
+ {
+ if(ret_innerIndices[k] > ret_indices[k-1])
+ ret_innerIndices[k] = ret_indices[k-1];
+ if(ret_innerIndices[k] > ret_indices[k])
+ ret_innerIndices[k] = ret_indices[k];
+ }
+ }
+ //clean up
+ free(uintercBuf);
+#endif
+}
+
+
+void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream* pStream, rectBlockArray* rbArray)
+{
+/*
+{
+grid->print();
+polygon->writeAllPolygons("zloutputFile");
+exit(0);
+}
+*/
+
+if(grid->get_n_ulines() == 2 ||
+ grid->get_n_vlines() == 2)
+{
+ if(ulinear && grid->get_n_ulines() == 2)
+ {
+ monoTriangulationFun(polygon, compV2InY, pStream);
+ return;
+ }
+ else if(DBG_isConvex(polygon) && polygon->numEdges() >=4)
+ {
+ triangulateConvexPoly(polygon, ulinear, vlinear, pStream);
+ return;
+ }
+ else if(vlinear || DBG_is_U_direction(polygon))
+ {
+ Int n_cusps;//num interior cusps
+ Int n_edges = polygon->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*) * n_edges);
+ assert(cusps);
+ findInteriorCuspsX(polygon, n_cusps, cusps);
+
+ if(n_cusps == 0) //u_monotone
+ {
+
+ monoTriangulationFun(polygon, compV2InX, pStream);
+
+ free(cusps);
+ return;
+ }
+ else if(n_cusps == 1) //one interior cusp
+ {
+
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+
+ directedLine* other = findDiagonal_singleCuspX( new_polygon);
+
+
+
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(polygon, compV2InX, pStream);
+ free(cusps);
+ return;
+ }
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+
+ free(cusps);
+ return;
+ }
+ free(cusps);
+ }
+}
+
+ /*find the top and bottom of the polygon. It is supposed to be
+ *a V-monotone polygon
+ */
+
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = polygon;
+
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+
+ botV = tempV;
+ }
+ }
+
+ /*find the first(top) and the last (bottom) grid line which intersect the
+ *this polygon
+ */
+ Int firstGridIndex; /*the index in the grid*/
+ Int lastGridIndex;
+ firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1));
+ lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1;
+
+
+ /*find the interval inside the polygon for each gridline*/
+ Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridIndices);
+ Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridIndices);
+ Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridInnerIndices);
+ Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridInnerIndices);
+
+ findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices);
+
+ findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices);
+
+ gridBoundaryChain leftGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices);
+
+ gridBoundaryChain rightGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices);
+
+
+
+// leftGridChain.draw();
+// leftGridChain.drawInner();
+// rightGridChain.draw();
+// rightGridChain.drawInner();
+ /*(1) determine the grid boundaries (left and right).
+ *(2) process polygon into two monotone chaines: use vertexArray
+ *(3) call sampleMonoPolyRec
+ */
+
+ /*copy the two chains into vertexArray datastructure*/
+ Int i;
+ vertexArray leftChain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ leftChain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ leftChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray rightChain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+
+ sampleMonoPolyRec(topV->head(),
+ botV->head(),
+ &leftChain,
+ 0,
+ &rightChain,
+ 0,
+ &leftGridChain,
+ &rightGridChain,
+ 0,
+ pStream,
+ rbArray);
+
+
+ /*cleanup space*/
+ free(leftGridIndices);
+ free(rightGridIndices);
+ free(leftGridInnerIndices);
+ free(rightGridInnerIndices);
+}
+
+void sampleMonoPolyRec(
+ Real* topVertex,
+ Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray)
+{
+
+ /*find the first connected component, and the four corners.
+ */
+ Int index1, index2; /*the first and last grid line of the first connected component*/
+
+ if(topVertex[1] <= botVertex[1])
+ return;
+
+ /*find i so that the grid line is below the top vertex*/
+ Int i=gridStartIndex;
+ while (i < leftGridChain->get_nVlines())
+ {
+ if(leftGridChain->get_v_value(i) < topVertex[1])
+ break;
+ i++;
+ }
+
+ /*find the first connected component starting with i*/
+ /*find index1 so that left_uline_index <= right_uline_index, that is, this
+ *grid line contains at least one inner grid point
+ */
+ index1=i;
+ int num_skipped_grid_lines=0;
+ while(index1 < leftGridChain->get_nVlines())
+ {
+ if(leftGridChain->getUlineIndex(index1) <= rightGridChain->getUlineIndex(index1))
+ break;
+ num_skipped_grid_lines++;
+ index1++;
+ }
+
+
+
+ if(index1 >= leftGridChain->get_nVlines()) /*no grid line exists which has inner point*/
+ {
+ /*stop recursion, ...*/
+ /*monotone triangulate it...*/
+// printf("no grid line exists\n");
+/*
+ monoTriangulationRecOpt(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+*/
+
+if(num_skipped_grid_lines <2)
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex, leftChain, leftStartIndex,
+ leftChain->getNumElements()-1,
+ rightChain, rightStartIndex,
+ rightChain->getNumElements()-1,
+ pStream);
+ }
+else
+ {
+ //the optimum way to triangulate is top-down since this polygon
+ //is narrow-long.
+ monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+ }
+
+/*
+ monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+*/
+
+/* monoTriangulationRecGenTBOpt(topVertex, botVertex,
+ leftChain, leftStartIndex, leftChain->getNumElements()-1,
+ rightChain, rightStartIndex, rightChain->getNumElements()-1,
+ pStream);*/
+
+
+
+ }
+ else
+ {
+
+ /*find index2 so that left_inner_index <= right_inner_index holds until index2*/
+ index2=index1+1;
+ if(index2 < leftGridChain->get_nVlines())
+ while(leftGridChain->getInnerIndex(index2) <= rightGridChain->getInnerIndex(index2))
+ {
+ index2++;
+ if(index2 >= leftGridChain->get_nVlines())
+ break;
+ }
+
+ index2--;
+
+
+
+ /*the neck*/
+ Int neckLeftIndex;
+ Int neckRightIndex;
+
+ /*the four corners*/
+ Int up_leftCornerWhere;
+ Int up_leftCornerIndex;
+ Int up_rightCornerWhere;
+ Int up_rightCornerIndex;
+ Int down_leftCornerWhere;
+ Int down_leftCornerIndex;
+ Int down_rightCornerWhere;
+ Int down_rightCornerIndex;
+
+ Real* tempBotVertex; /*the bottom vertex for this component*/
+ Real* nextTopVertex=NULL; /*for the recursion*/
+ Int nextLeftStartIndex=0;
+ Int nextRightStartIndex=0;
+
+ /*find the points below the grid line index2 on both chains*/
+ Int botLeftIndex = leftChain->findIndexStrictBelowGen(
+ leftGridChain->get_v_value(index2),
+ leftStartIndex,
+ leftChain->getNumElements()-1);
+ Int botRightIndex = rightChain->findIndexStrictBelowGen(
+ rightGridChain->get_v_value(index2),
+ rightStartIndex,
+ rightChain->getNumElements()-1);
+ /*if either botLeftIndex>= numelements,
+ * or botRightIndex >= numelemnet,
+ *then there is no neck exists. the bottom vertex is botVertex,
+ */
+ if(! findNeckF(leftChain, botLeftIndex, rightChain, botRightIndex,
+ leftGridChain, rightGridChain, index2, neckLeftIndex, neckRightIndex))
+ /*
+ if(botLeftIndex == leftChain->getNumElements() ||
+ botRightIndex == rightChain->getNumElements())
+ */
+ {
+#ifdef MYDEBUG
+ printf("neck NOT exists, botRightIndex=%i\n", botRightIndex);
+#endif
+
+ tempBotVertex = botVertex;
+ nextTopVertex = botVertex;
+ botLeftIndex = leftChain->getNumElements()-1;
+ botRightIndex = rightChain->getNumElements()-1;
+ }
+ else /*neck exists*/
+ {
+#ifdef MYDEBUG
+ printf("neck exists\n");
+#endif
+
+ /*
+ findNeck(leftChain, botLeftIndex,
+ rightChain, botRightIndex,
+ neckLeftIndex,
+ neckRightIndex);
+ */
+#ifdef MYDEBUG
+printf("neck is found, neckLeftIndex=%i, neckRightIndex=%i\n", neckLeftIndex, neckRightIndex);
+glBegin(GL_LINES);
+glVertex2fv(leftChain->getVertex(neckLeftIndex));
+glVertex2fv(rightChain->getVertex(neckRightIndex));
+glEnd();
+#endif
+
+ if(leftChain->getVertex(neckLeftIndex)[1] <= rightChain->getVertex(neckRightIndex)[1])
+ {
+ tempBotVertex = leftChain->getVertex(neckLeftIndex);
+ botLeftIndex = neckLeftIndex-1;
+ botRightIndex = neckRightIndex;
+ nextTopVertex = rightChain->getVertex(neckRightIndex);
+ nextLeftStartIndex = neckLeftIndex;
+ nextRightStartIndex = neckRightIndex+1;
+ }
+ else
+ {
+ tempBotVertex = rightChain->getVertex(neckRightIndex);
+ botLeftIndex = neckLeftIndex;
+ botRightIndex = neckRightIndex-1;
+ nextTopVertex = leftChain->getVertex(neckLeftIndex);
+ nextLeftStartIndex = neckLeftIndex+1;
+ nextRightStartIndex = neckRightIndex;
+ }
+ }
+
+ findUpCorners(topVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain->get_v_value(index1),
+ leftGridChain->get_u_value(index1),
+ rightGridChain->get_u_value(index1),
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex);
+
+ findDownCorners(tempBotVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain->get_v_value(index2),
+ leftGridChain->get_u_value(index2),
+ rightGridChain->get_u_value(index2),
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex);
+#ifdef MYDEBUG
+ printf("find corners done, down_leftwhere=%i, down_righwhere=%i,\n",down_leftCornerWhere, down_rightCornerWhere );
+ printf("find corners done, up_leftwhere=%i, up_righwhere=%i,\n",up_leftCornerWhere, up_rightCornerWhere );
+ printf("find corners done, up_leftindex=%i, up_righindex=%i,\n",up_leftCornerIndex, up_rightCornerIndex );
+ printf("find corners done, down_leftindex=%i, down_righindex=%i,\n",down_leftCornerIndex, down_rightCornerIndex );
+#endif
+
+/*
+ drawCorners(topVertex,
+ tempBotVertex,
+ leftChain,
+ rightChain,
+ leftGridChain,
+ rightGridChain,
+ index1,
+ index2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex);
+*/
+
+
+ sampleConnectedComp(topVertex, tempBotVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain,
+ rightGridChain,
+ index1, index2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream,
+ rbArray
+ );
+
+ /*recursion*/
+
+ sampleMonoPolyRec(
+ nextTopVertex,
+ botVertex,
+ leftChain,
+ nextLeftStartIndex,
+ rightChain,
+ nextRightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ index2+1,
+ pStream, rbArray);
+
+
+ }
+
+}
+
+void sampleLeftStrip(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ assert(leftChain->getVertex(topLeftIndex)[1] > leftGridChain->get_v_value(leftGridChainStartIndex));
+ assert(leftChain->getVertex(topLeftIndex+1)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex));
+ assert(leftChain->getVertex(botLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainEndIndex));
+ assert(leftChain->getVertex(botLeftIndex-1)[1] > leftGridChain->get_v_value(leftGridChainEndIndex));
+
+ /*
+ *(1)find the last grid line which doesn'; pass below
+ * this first edge, sample this region: one trim edge and
+ * possily multiple grid lines.
+ */
+ Real *upperVert, *lowerVert; /*the end points of the first trim edge*/
+ upperVert = leftChain->getVertex(topLeftIndex);
+ lowerVert = leftChain->getVertex(topLeftIndex+1);
+
+ Int index = leftGridChainStartIndex;
+ while(leftGridChain->get_v_value(index) >= lowerVert[1]){
+ index++;
+ if(index > leftGridChainEndIndex)
+ break;
+ }
+ index--;
+
+ sampleLeftSingleTrimEdgeRegion(upperVert, lowerVert,
+ leftGridChain,
+ leftGridChainStartIndex,
+ index,
+ pStream);
+ sampleLeftStripRec(leftChain, topLeftIndex+1, botLeftIndex,
+ leftGridChain, index, leftGridChainEndIndex,
+ pStream);
+
+}
+
+void sampleLeftStripRec(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ /*now top left trim vertex is below the top grid line.
+ */
+ /*stop condition: if topLeftIndex >= botLeftIndex, then stop.
+ */
+ if(topLeftIndex >= botLeftIndex)
+ return;
+
+ /*find the last trim vertex which is above the second top grid line:
+ * index1.
+ *and sampleLeftOneGridStep(leftchain, topLeftIndex, index1, leftGridChain,
+ * leftGridChainStartIndex).
+ * index1 could be equal to topLeftIndex.
+ */
+ Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+ assert(leftGridChainStartIndex < leftGridChainEndIndex);
+ Int index1 = topLeftIndex;
+ while(leftChain->getVertex(index1)[1] > secondGridChainV)
+ index1++;
+ index1--;
+
+ sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream);
+
+
+ /*
+ * Let the next trim vertex be nextTrimVertIndex (which should be
+ * below the second grid line).
+ * Find the last grid line index2 which is above nextTrimVert.
+ * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2],
+ * leftGridChain, leftGridChainStartIndex+1, index2).
+ */
+ Real *uppervert, *lowervert;
+ uppervert = leftChain->getVertex(index1);
+ lowervert = leftChain->getVertex(index1+1);
+ Int index2 = leftGridChainStartIndex+1;
+
+ while(leftGridChain->get_v_value(index2) >= lowervert[1])
+ {
+ index2++;
+ if(index2 > leftGridChainEndIndex)
+ break;
+ }
+ index2--;
+ sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream);
+
+ /* sampleLeftStripRec(leftChain,
+ nextTrimVertIndex,
+ botLeftIndex,
+ leftGridChain,
+ index2,
+ leftGridChainEndIndex
+ )
+ *
+ */
+ sampleLeftStripRec(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream);
+
+}
+
+
+/***************begin RecF***********************/
+/* the gridlines from leftGridChainStartIndex to
+ * leftGridChainEndIndex are assumed to form a
+ * connected component.
+ * the trim vertex of topLeftIndex is assumed to
+ * be below the first gridline, and the tim vertex
+ * of botLeftIndex is assumed to be above the last
+ * grid line.
+ * If botLeftIndex < topLeftIndex, then no connected componeent exists, and this funcion returns without
+ * outputing any triangles.
+ * Otherwise botLeftIndex >= topLeftIndex, there is at least one triangle to output.
+ */
+void sampleLeftStripRecF(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ /*now top left trim vertex is below the top grid line.
+ */
+ /*stop condition: if topLeftIndex > botLeftIndex, then stop.
+ */
+ if(topLeftIndex > botLeftIndex)
+ return;
+
+ /*if there is only one grid Line, return.*/
+
+ if(leftGridChainStartIndex>=leftGridChainEndIndex)
+ return;
+
+
+ assert(leftChain->getVertex(topLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex) &&
+ leftChain->getVertex(botLeftIndex)[1] >= leftGridChain->get_v_value(leftGridChainEndIndex));
+
+ /*firs find the first trim vertex which is below or equal to the second top grid line:
+ * index1.
+ */
+ Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+
+ Int index1 = topLeftIndex;
+
+ while(leftChain->getVertex(index1)[1] > secondGridChainV){
+ index1++;
+ if(index1>botLeftIndex)
+ break;
+ }
+
+ /*now leftChain->getVertex(index-1)[1] > secondGridChainV and
+ * leftChain->getVertex(index)[1] <= secondGridChainV
+ *If equality holds, then we should include the vertex index1, otherwise we include only index1-1, to
+ *perform sampleOneGridStep.
+ */
+ if(index1>botLeftIndex)
+ index1--;
+ else if(leftChain->getVertex(index1)[1] < secondGridChainV)
+ index1--;
+
+ /*now we have leftChain->getVertex(index1)[1] >= secondGridChainV, and
+ * leftChain->getVertex(index1+1)[1] <= secondGridChainV
+ */
+
+
+ sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream);
+
+
+ /*if leftChain->getVertex(index1)[1] == secondGridChainV, then we can recursively do the rest.
+ */
+ if(leftChain->getVertex(index1)[1] == secondGridChainV)
+ {
+
+ sampleLeftStripRecF(leftChain, index1, botLeftIndex,leftGridChain, leftGridChainStartIndex+1, leftGridChainEndIndex, pStream);
+ }
+ else if(index1 < botLeftIndex)
+ {
+
+ /* Otherwise, we have leftChain->getVertex(index1)[1] > secondGridChainV,
+ * let the next trim vertex be nextTrimVertIndex (which should be strictly
+ * below the second grid line).
+ * Find the last grid line index2 which is above nextTrimVert.
+ * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2],
+ * leftGridChain, leftGridChainStartIndex+1, index2).
+ */
+ Real *uppervert, *lowervert;
+ uppervert = leftChain->getVertex(index1);
+ lowervert = leftChain->getVertex(index1+1); //okay since index1<botLeftIndex
+ Int index2 = leftGridChainStartIndex+1;
+
+
+ while(leftGridChain->get_v_value(index2) >= lowervert[1])
+ {
+ index2++;
+ if(index2 > leftGridChainEndIndex)
+ break;
+ }
+ index2--;
+
+
+ sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream);
+
+ /*recursion*/
+
+ sampleLeftStripRecF(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream);
+ }
+
+}
+
+/***************End RecF***********************/
+
+/*sample the left area in between one trim edge and multiple grid lines.
+ * all the grid lines should be in between the two end poins of the
+ *trim edge.
+ */
+void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream)
+{
+ Int i,j,k;
+
+ vertexArray vArray(endIndex-beginIndex+1);
+ vArray.appendVertex(gridChain->get_vertex(beginIndex));
+
+ for(k=1, i=beginIndex+1; i<=endIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ /*output the fan of the grid points of the (i)th and (i-1)th grid line.
+ */
+ if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i-1));
+ for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i));
+ for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+ }
+
+ monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex,
+ 0, /*decreasing chain*/
+ pStream);
+}
+
+/*return i, such that from begin to i-1 the chain is strictly u-monotone.
+ */
+Int findIncreaseChainFromBegin(vertexArray* chain, Int begin ,Int end)
+{
+ Int i=begin;
+ Real prevU = chain->getVertex(i)[0];
+ Real thisU;
+ for(i=begin+1; i<=end; i++){
+ thisU = chain->getVertex(i)[0];
+
+ if(prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ return i;
+}
+
+/*check whether there is a vertex whose v value is strictly
+ *inbetween vup vbelow
+ *if no middle exists return -1, else return the idnex.
+ */
+Int checkMiddle(vertexArray* chain, Int begin, Int end,
+ Real vup, Real vbelow)
+{
+ Int i;
+ for(i=begin; i<=end; i++)
+ {
+ if(chain->getVertex(i)[1] < vup && chain->getVertex(i)[1]>vbelow)
+ return i;
+ }
+ return -1;
+}
+
+/*the degenerat case of sampleLeftOneGridStep*/
+void sampleLeftOneGridStepNoMiddle(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream)
+{
+ /*since there is no middle, there is at most one point which is on the
+ *second grid line, there could be multiple points on the first (top)
+ *grid line.
+ */
+
+ leftGridChain->leftEndFan(leftGridChainStartIndex+1, pStream);
+
+ monoTriangulation2(leftGridChain->get_vertex(leftGridChainStartIndex),
+ leftGridChain->get_vertex(leftGridChainStartIndex+1),
+ leftChain,
+ beginLeftIndex,
+ endLeftIndex,
+ 1, //is increase chain.
+ pStream);
+}
+
+
+
+/*sampling the left area in between two grid lines.
+ */
+void sampleLeftOneGridStep(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream
+ )
+{
+ if(checkMiddle(leftChain, beginLeftIndex, endLeftIndex,
+ leftGridChain->get_v_value(leftGridChainStartIndex),
+ leftGridChain->get_v_value(leftGridChainStartIndex+1))<0)
+
+ {
+
+ sampleLeftOneGridStepNoMiddle(leftChain, beginLeftIndex, endLeftIndex, leftGridChain, leftGridChainStartIndex, pStream);
+ return;
+ }
+
+ //copy into a polygon
+ {
+ directedLine* poly = NULL;
+ sampledLine* sline;
+ directedLine* dline;
+ gridWrap* grid = leftGridChain->getGrid();
+ Real vert1[2];
+ Real vert2[2];
+ Int i;
+
+ Int innerInd = leftGridChain->getInnerIndex(leftGridChainStartIndex+1);
+ Int upperInd = leftGridChain->getUlineIndex(leftGridChainStartIndex);
+ Int lowerInd = leftGridChain->getUlineIndex(leftGridChainStartIndex+1);
+ Real upperV = leftGridChain->get_v_value(leftGridChainStartIndex);
+ Real lowerV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+ //the upper gridline
+ vert1[1] = vert2[1] = upperV;
+ for(i=innerInd; i>upperInd; i--)
+ {
+ vert1[0]=grid->get_u_value(i);
+ vert2[0]=grid->get_u_value(i-1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+ }
+
+ //the edge connecting upper grid with left chain
+ vert1[0] = grid->get_u_value(upperInd);
+ vert1[1] = upperV;
+ sline = new sampledLine(vert1, leftChain->getVertex(beginLeftIndex));
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+
+ //the left chain
+ for(i=beginLeftIndex; i<endLeftIndex; i++)
+ {
+ sline = new sampledLine(leftChain->getVertex(i), leftChain->getVertex(i+1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting left chain with lower gridline
+ vert2[0] = grid->get_u_value(lowerInd);
+ vert2[1] = lowerV;
+ sline = new sampledLine(leftChain->getVertex(endLeftIndex), vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+
+ //the lower grid line
+ vert1[1] = vert2[1] = lowerV;
+ for(i=lowerInd; i<innerInd; i++)
+ {
+ vert1[0] = grid->get_u_value(i);
+ vert2[0] = grid->get_u_value(i+1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the vertical grid line segement
+ vert1[0]=vert2[0] = grid->get_u_value(innerInd);
+ vert2[1]=upperV;
+ vert1[1]=lowerV;
+ sline=new sampledLine(vert1, vert2);
+ dline=new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ monoTriangulationOpt(poly, pStream);
+ //cleanup
+ poly->deleteSinglePolygonWithSline();
+ return;
+ }
+
+
+
+
+
+ Int i;
+ if(1/*leftGridChain->getUlineIndex(leftGridChainStartIndex) >=
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1)*/
+ ) /*the second grid line is beyond the first one to the left*/
+ {
+ /*find the maximal U-monotone chain
+ * of endLeftIndex, endLeftIndex-1, ...,
+ */
+ i=endLeftIndex;
+ Real prevU = leftChain->getVertex(i)[0];
+ for(i=endLeftIndex-1; i>=beginLeftIndex; i--){
+ Real thisU = leftChain->getVertex(i)[0];
+ if( prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ /*from endLeftIndex to i+1 is strictly U- monotone */
+ /*if i+1==endLeftIndex and the vertex and leftchain is on the second gridline, then
+ *we should use 2 vertices on the leftchain. If we only use one (endLeftIndex), then we
+ *we would output degenerate triangles
+ */
+ if(i+1 == endLeftIndex && leftChain->getVertex(endLeftIndex)[1] == leftGridChain->get_v_value(1+leftGridChainStartIndex))
+ i--;
+
+ Int j = beginLeftIndex/*endLeftIndex*/+1;
+
+
+ if(leftGridChain->getInnerIndex(leftGridChainStartIndex+1) > leftGridChain->getUlineIndex(leftGridChainStartIndex))
+ {
+ j = findIncreaseChainFromBegin(leftChain, beginLeftIndex, i+1/*endLeftIndex*/);
+
+ Int temp = beginLeftIndex;
+ /*now from begin to j-1 is strictly u-monotone*/
+ /*if j-1 is on the first grid line, then we want to skip to the vertex which is strictly
+ *below the grid line. This vertexmust exist since there is a 'corner turn' inbetween the two grid lines
+ */
+ if(j-1 == beginLeftIndex)
+ {
+ while(leftChain->getVertex(j-1)[1] == leftGridChain->get_v_value(leftGridChainStartIndex))
+ j++;
+
+ Real vert[2];
+ vert[0] = leftGridChain->get_u_value(leftGridChainStartIndex);
+ vert[1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+
+ monoTriangulation2(
+ vert/*leftChain->getVertex(beginLeftIndex)*/,
+ leftChain->getVertex(j-1),
+ leftChain,
+ beginLeftIndex,
+ j-2,
+ 1,
+ pStream //increase chain
+ );
+
+ temp = j-1;
+ }
+
+ stripOfFanLeft(leftChain, j-1, temp/*beginLeftIndex*/, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex),
+ leftGridChain->getInnerIndex(leftGridChainStartIndex+1),
+ pStream,
+ 1 /*the grid line is above the trim line*/
+ );
+ }
+
+ stripOfFanLeft(leftChain, endLeftIndex, i+1, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex+1),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1),
+ leftGridChain->getInnerIndex(leftGridChainStartIndex+1),
+ pStream,
+ 0 /*the grid line is below the trim lines*/
+ );
+
+ /*monotone triangulate the remaining left chain togther with the
+ *two vertices on the two grid v-lines.
+ */
+ Real vert[2][2];
+ vert[0][0]=vert[1][0] = leftGridChain->getInner_u_value(leftGridChainStartIndex+1);
+ vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+ vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+// vertexArray right(vert, 2);
+
+ monoTriangulation2(
+ &vert[0][0], /*top vertex */
+ &vert[1][0], /*bottom vertex*/
+ leftChain,
+ /*beginLeftIndex*/j-1,
+ i+1,
+ 1, /*an increasing chain*/
+ pStream);
+ }
+ else /*the second one is shorter than the first one to the left*/
+ {
+ /*find the maximal U-monotone chain of beginLeftIndex, beginLeftIndex+1,...,
+ */
+ i=beginLeftIndex;
+ Real prevU = leftChain->getVertex(i)[0];
+ for(i=beginLeftIndex+1; i<=endLeftIndex; i++){
+ Real thisU = leftChain->getVertex(i)[0];
+
+ if(prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ /*from beginLeftIndex to i-1 is strictly U-monotone*/
+
+
+ stripOfFanLeft(leftChain, i-1, beginLeftIndex, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1),
+ pStream,
+ 1 /*the grid line is above the trim lines*/
+ );
+ /*monotone triangulate the remaining left chain together with the
+ *two vertices on the two grid v-lines.
+ */
+ Real vert[2][2];
+ vert[0][0]=vert[1][0] = leftGridChain->get_u_value(leftGridChainStartIndex+1);
+ vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+ vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+ vertexArray right(vert, 2);
+
+ monoTriangulation2(
+ &vert[0][0], //top vertex
+ &vert[1][0], //bottom vertex
+ leftChain,
+ i-1,
+ endLeftIndex,
+ 1, /*an increase chain*/
+ pStream);
+
+ }
+}
+
+/*n_upper>=1
+ *n_lower>=1
+ */
+void triangulateXYMono(Int n_upper, Real upperVerts[][2],
+ Int n_lower, Real lowerVerts[][2],
+ primStream* pStream)
+{
+ Int i,j,k,l;
+ Real* leftMostV;
+
+ assert(n_upper>=1 && n_lower>=1);
+ if(upperVerts[0][0] <= lowerVerts[0][0])
+ {
+ i=1;
+ j=0;
+ leftMostV = upperVerts[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+ leftMostV = lowerVerts[0];
+ }
+
+ while(1)
+ {
+ if(i >= n_upper) /*case1: no more in upper*/
+ {
+
+ if(j<n_lower-1) /*at least two vertices in lower*/
+ {
+ pStream->begin();
+ pStream->insert(leftMostV);
+ while(j<n_lower){
+ pStream->insert(lowerVerts[j]);
+ j++;
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else if(j>= n_lower) /*case2: no more in lower*/
+ {
+
+ if(i<n_upper-1) /*at least two vertices in upper*/
+ {
+ pStream->begin();
+ pStream->insert(leftMostV);
+
+ for(k=n_upper-1; k>=i; k--)
+ pStream->insert(upperVerts[k]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
+ {
+
+ if(upperVerts[i][0] <= lowerVerts[j][0])
+ {
+ pStream->begin();
+ pStream->insert(lowerVerts[j]); /*the origin of this fan*/
+
+ /*find the last k>=i such that
+ *upperverts[k][0] <= lowerverts[j][0]
+ */
+ k=i;
+ while(k<n_upper)
+ {
+ if(upperVerts[k][0] > lowerVerts[j][0])
+ break;
+ k++;
+ }
+ k--;
+ for(l=k; l>=i; l--)/*the reverse is for two-face lighting*/
+ {
+ pStream->insert(upperVerts[l]);
+ }
+ pStream->insert(leftMostV);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ //update i for next loop
+ i = k+1;
+ leftMostV = upperVerts[k];
+
+ }
+ else /*upperVerts[i][0] > lowerVerts[j][0]*/
+ {
+ pStream->begin();
+ pStream->insert(upperVerts[i]);/*the origion of this fan*/
+ pStream->insert(leftMostV);
+ /*find the last k>=j such that
+ *lowerverts[k][0] < upperverts[i][0]*/
+ k=j;
+ while(k< n_lower)
+ {
+ if(lowerVerts[k][0] >= upperVerts[i][0])
+ break;
+ pStream->insert(lowerVerts[k]);
+ k++;
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ j=k;
+ leftMostV = lowerVerts[j-1];
+ }
+ }
+ }
+}
+
+
+void stripOfFanLeft(vertexArray* leftChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if the grid line is above the trim lines*/
+ )
+{
+ assert(largeIndex >= smallIndex);
+
+ Real grid_v_value;
+ grid_v_value = grid->get_v_value(vlineIndex);
+
+ Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1));
+ assert(trimVerts);
+
+
+ Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1));
+ assert(gridVerts);
+
+ Int k,i;
+ if(gridLineUp) /*trim line is below grid line, so trim vertices are going right when index increases*/
+ for(k=0, i=smallIndex; i<=largeIndex; i++, k++)
+ {
+ trimVerts[k][0] = leftChain->getVertex(i)[0];
+ trimVerts[k][1] = leftChain->getVertex(i)[1];
+ }
+ else
+ for(k=0, i=largeIndex; i>=smallIndex; i--, k++)
+ {
+ trimVerts[k][0] = leftChain->getVertex(i)[0];
+ trimVerts[k][1] = leftChain->getVertex(i)[1];
+ }
+
+ for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++)
+ {
+ gridVerts[k][0] = grid->get_u_value(i);
+ gridVerts[k][1] = grid_v_value;
+ }
+
+ if(gridLineUp)
+ triangulateXYMono(
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ largeIndex-smallIndex+1, trimVerts,
+ pStream);
+ else
+ triangulateXYMono(largeIndex-smallIndex+1, trimVerts,
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ pStream);
+ free(trimVerts);
+ free(gridVerts);
+}
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h
new file mode 100644
index 000000000..3a5fa6c91
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h
@@ -0,0 +1,184 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLEMONOPOLY_H
+#define _SAMPLEMONOPOLY_H
+
+#include "monoTriangulation.h"
+#include "gridWrap.h"
+#include "rectBlock.h"
+
+
+void triangulateXYMono(Int n_upper, Real upperVerts[][2],
+ Int n_lower, Real lowerVerts[][2],
+ primStream* pStream);
+
+void stripOfFanLeft(vertexArray* leftChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp
+ );
+void sampleLeftOneGridStep(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream
+ );
+
+void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream);
+
+void sampleLeftStripRec(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void sampleLeftStrip(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_inner);
+
+void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_inner);
+
+void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream *pStream, rectBlockArray* rbArray);
+
+void sampleMonoPolyRec(
+ Real* topVertex,
+ Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ );
+
+void sampleLeftStripRecF(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void findUpCorners(Real *topVertex,
+ vertexArray *leftChain,
+ Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain,
+ Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere,
+ Int& ret_leftCornerIndex,
+ Int& ret_rightCornerWhere,
+ Int& ret_rightCornerIndex
+ );
+void findDownCorners(Real *botVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere,
+ Int& ret_leftCornerIndex,
+ Int& ret_rightCornerWhere,
+ Int& ret_rightCornerIndex
+ );
+void findNeck(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ Int& leftLastIndex, /*left point of the neck*/
+ Int& rightLastIndex /*right point of the neck*/
+ );
+
+Int findNeckF(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ Int& neckLeft,
+ Int& neckRight);
+
+void findTopAndBot(directedLine* polygon,
+ directedLine*& topV,
+ directedLine*& botV);
+void findGridChains(directedLine* top, directedLine* bot,
+ gridWrap* grid,
+ gridBoundaryChain*& leftGridChain,
+ gridBoundaryChain*& rightGridChain);
+void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain);
+
+void drawCorners(
+ Real* topV, Real* botV,
+ vertexArray* leftChain,
+ vertexArray* rightChain,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int gridIndex2,
+ Int leftCornerWhere,
+ Int leftCornerIndex,
+ Int rightCornerWhere,
+ Int rightCornerIndex,
+ Int bot_leftCornerWhere,
+ Int bot_leftCornerIndex,
+ Int bot_rightCornerWhere,
+ Int bot_rightCornerIndex);
+
+Int checkMiddle(vertexArray* chain, Int begin, Int end,
+ Real vup, Real vbelow);
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc
new file mode 100644
index 000000000..6253a7c09
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc
@@ -0,0 +1,179 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h> //for fabs()
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampledLine.h"
+
+void sampledLine::setPoint(Int i, Real p[2])
+{
+ points[i][0]=p[0];
+ points[i][1]=p[1];
+}
+
+
+/*insert this single line in front of the oldList*/
+sampledLine* sampledLine::insert(sampledLine *oldList)
+{
+ next = oldList;
+ return this;
+}
+
+void sampledLine::deleteList()
+{
+ sampledLine *temp, *tempNext;
+ for(temp = this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+
+/*space of points[][2] is allocated*/
+sampledLine::sampledLine(Int n_points)
+{
+ npoints = n_points;
+ points = (Real2*) malloc(sizeof(Real2) * n_points);
+ assert(points);
+ next = NULL;
+}
+
+/*space of points[][2] is allocated and
+ *points are copied
+ */
+sampledLine::sampledLine(Int n_points, Real2 pts[])
+{
+ int i;
+ npoints = n_points;
+ points = (Real2*) malloc(sizeof(Real2) * n_points);
+ assert(points);
+ for(i=0; i<npoints; i++) {
+ points[i][0] = pts[i][0];
+ points[i][1] = pts[i][1];
+ }
+ next = NULL;
+}
+
+sampledLine::sampledLine(Real pt1[2], Real pt2[2])
+{
+ npoints = 2;
+ points = (Real2*) malloc(sizeof(Real2) * 2);
+ assert(points);
+ points[0][0] = pt1[0];
+ points[0][1] = pt1[1];
+ points[1][0] = pt2[0];
+ points[1][1] = pt2[1];
+ next = NULL;
+}
+
+//needs tp call init to setup
+sampledLine::sampledLine()
+{
+}
+
+//warning: ONLY pointer is copies!!!
+void sampledLine::init(Int n_points, Real2 *pts)
+{
+ npoints = n_points;
+ points = pts;
+}
+
+/*points[] is dealocated
+ */
+sampledLine::~sampledLine()
+{
+ free(points);
+}
+
+void sampledLine::print()
+{
+ int i;
+ printf("npoints=%i\n", npoints);
+
+ for(i=0; i<npoints; i++){
+ printf("(%f,%f)\n", points[i][0], points[i][1]);
+ }
+
+}
+
+void sampledLine::tessellate(Real u_reso, Real v_reso)
+{
+ int i;
+
+ Int nu, nv, n;
+ nu = 1+(Int) (fabs((points[npoints-1][0] - points[0][0])) * u_reso);
+ nv = 1+(Int) (fabs((points[npoints-1][1] - points[0][1])) * v_reso);
+
+ if(nu > nv) n = nu;
+ else
+ n = nv;
+ if(n<1)
+ n = 1;
+ //du dv could be negative
+ Real du = (points[npoints-1][0] - points[0][0])/n;
+ Real dv = (points[npoints-1][1] - points[0][1])/n;
+ Real2 *temp = (Real2*) malloc(sizeof(Real2) * (n+1));
+ assert(temp);
+
+ Real u,v;
+ for(i=0, u=points[0][0], v=points[0][1]; i<n; i++, u+=du, v+=dv)
+ {
+ temp[i][0] = u;
+ temp[i][1] = v;
+ }
+ temp[n][0] = points[npoints-1][0];
+ temp[n][1] = points[npoints-1][1];
+
+ free(points);
+
+ npoints = n+1;
+ points = temp;
+
+}
+
+void sampledLine::tessellateAll(Real u_reso, Real v_reso)
+{
+ sampledLine* temp;
+ for(temp = this; temp != NULL; temp = temp->next)
+ {
+ temp->tessellate(u_reso, v_reso);
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.h
new file mode 100644
index 000000000..2cc726948
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.h
@@ -0,0 +1,71 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLEDLINE_H
+#define _SAMPLEDLINE_H
+
+#include "definitions.h"
+
+class sampledLine{
+ Int npoints;
+ Real2 *points;
+
+public:
+ sampledLine(Int n_points);
+ sampledLine(Int n_points, Real pts[][2]);
+ sampledLine(Real pt1[2], Real pt2[2]);
+ sampledLine(); //special, careful about memory
+ ~sampledLine();
+
+ void init(Int n_points, Real2 *pts);//special, careful about memory
+
+ void setPoint(Int i, Real p[2]) ;
+
+ sampledLine* insert(sampledLine *nline);
+ void deleteList();
+
+ Int get_npoints() {return npoints;}
+ Real2* get_points() {return points;}
+
+ //u_reso is number of segments (may not be integer) per unit u
+ void tessellate(Real u_reso, Real v_reso);//n segments
+ void tessellateAll(Real u_reso, Real v_reso);
+
+ void print();
+
+ sampledLine* next;
+};
+
+
+
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.cc
new file mode 100644
index 000000000..1865755a4
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.cc
@@ -0,0 +1,282 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "zlassert.h"
+
+#include "searchTree.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+treeNode* TreeNodeMake(void *key)
+{
+ treeNode *ret = (treeNode*) malloc(sizeof(treeNode));
+ assert(ret);
+ ret->key = key;
+ ret->parent = NULL;
+ ret->left = NULL;
+ ret->right = NULL;
+ return ret;
+}
+
+void TreeNodeDeleteSingleNode(treeNode* node)
+{
+ free(node);
+}
+
+void TreeNodeDeleteWholeTree(treeNode* node)
+{
+ if(node == NULL) return;
+ TreeNodeDeleteWholeTree(node->left);
+ TreeNodeDeleteWholeTree(node->right);
+ TreeNodeDeleteSingleNode(node);
+}
+
+void TreeNodePrint(treeNode* node,
+ void (*keyPrint) (void*))
+{
+ if(node ==NULL) return;
+ TreeNodePrint(node->left, keyPrint);
+ keyPrint(node->key);
+ TreeNodePrint(node->right, keyPrint);
+}
+
+int TreeNodeDepth(treeNode* root)
+{
+ if(root == NULL) return 0;
+ else{
+ int leftdepth = TreeNodeDepth(root->left);
+ int rightdepth = TreeNodeDepth(root->right);
+ return 1 + max(leftdepth, rightdepth);
+ }
+}
+
+/*return the node with the key.
+ *NULL is returned if not found
+ */
+treeNode* TreeNodeFind(treeNode* tree, void* key,
+ int (*compkey) (void*, void*))
+{
+ if(tree == NULL)
+ return NULL;
+ if(key == tree->key)
+ return tree;
+ else if(compkey(key, tree->key) < 0)
+ return TreeNodeFind(tree->left, key, compkey);
+ else
+ return TreeNodeFind(tree->right, key, compkey);
+}
+
+
+treeNode* TreeNodeInsert(treeNode* root, treeNode* newnode,
+ int (*compkey) (void *, void *))
+{
+ treeNode *y = NULL;
+ treeNode *x = root;
+ /*going down the tree from the root.
+ *x traces the path, y is the parent of x.
+ */
+ while (x != NULL){
+ y = x;
+ if(compkey(newnode->key,x->key) < 0) /*if newnode < x*/
+ x = x->left;
+ else
+ x = x->right;
+ }
+
+ /*now y has the property that
+ * if newnode < y, then y->left is NULL
+ * if newnode > y, then y->right is NULL.
+ *So we want to isnert newnode to be the child of y
+ */
+ newnode->parent = y;
+ if(y == NULL)
+ return newnode;
+ else if( compkey(newnode->key, y->key) <0)
+ {
+ y->left = newnode;
+ }
+ else
+ {
+ y->right = newnode;
+ }
+
+ return root;
+}
+
+treeNode* TreeNodeDeleteSingleNode(treeNode* tree, treeNode* node)
+{
+ treeNode* y;
+ treeNode* x;
+ treeNode* ret;
+ if(node==NULL) return tree;
+
+ if(node->left == NULL || node->right == NULL) {
+
+ y = node;
+ if(y->left != NULL)
+ x = y->left;
+ else
+ x = y->right;
+
+ if( x != NULL)
+ x->parent = y->parent;
+
+ if(y->parent == NULL) /*y is the root which has at most one child x*/
+ ret = x;
+ else /*y is not the root*/
+ {
+ if(y == y->parent->left)
+ y->parent->left = x;
+ else
+ y->parent->right = x;
+ ret = tree;
+ }
+ }
+ else { /*node has two children*/
+
+ y = TreeNodeSuccessor(node);
+ assert(y->left == NULL);
+
+ if(y == node->right) /*y is the right child if node*/
+ {
+ y->parent = node->parent;
+ y->left = node->left;
+ node->left->parent = y;
+
+ }
+ else /*y != node->right*/
+ {
+ x = y->right;
+ if(x!= NULL)
+ x->parent = y->parent;
+
+ assert(y->parent != NULL);
+ if(y == y->parent->left)
+ y->parent->left = x;
+ else
+ y->parent->right = x;
+ /*move y to the position of node*/
+ y->parent = node->parent;
+ y->left = node->left;
+ y->right = node->right;
+ node->left->parent = y;
+ node->right->parent = y;
+ }
+ if(node->parent != NULL) {
+ if(node->parent->left == node)
+ node->parent->left = y;
+ else
+ node->parent->right = y;
+ ret = tree; /*the root if the tree doesn't change*/
+ }
+ else /*node->parent is NULL: node is the root*/
+ ret = y;
+ }
+
+ /*finally free the node, and return the new root*/
+ TreeNodeDeleteSingleNode(node);
+ return ret;
+}
+
+
+/*the minimum node in the tree rooted by node
+ */
+treeNode* TreeNodeMinimum(treeNode* node)
+{
+ treeNode* temp = node;
+ if(temp == NULL) return NULL;
+ while(temp->left != NULL) {
+ temp = temp->left;
+ }
+ return temp;
+}
+
+/*the maximum node in the tree rooted by node
+ */
+treeNode* TreeNodeMaximum(treeNode* node)
+{
+ treeNode* temp = node;
+ if(temp == NULL) return NULL;
+ while(temp->right != NULL) {
+ temp = temp->right;
+ }
+ return temp;
+}
+
+/*return the first node (in sorted order) which is to the right of this node
+ */
+treeNode* TreeNodeSuccessor(treeNode* node)
+{
+ if(node == NULL) return NULL;
+ if(node->right != NULL)
+ return TreeNodeMinimum(node->right);
+ else{ /*node->right is NULL*/
+
+ /*find the first right-ancestor*/
+ treeNode *y = node->parent;
+ treeNode* x = node;
+ while(y != NULL && x == y->right) /*if y is a left parent of x*/
+ {
+
+ x = y;
+ y = y->parent;
+ }
+ return y;
+ }
+}
+
+/*return the first node (in sorted order) which is to the left of this node
+ */
+treeNode* TreeNodePredecessor(treeNode* node)
+{
+ if(node == NULL) return NULL;
+ if(node->left != NULL)
+ return TreeNodeMaximum(node->left);
+ else{ /*node->left is NULL*/
+ /*find the first left-ancestor*/
+ treeNode *y = node->parent;
+ treeNode *x = node;
+ while(y != NULL && x == y->left) /*if y is a right parent of x*/
+ {
+ x = y;
+ y = y->parent;
+ }
+ return y;
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.h
new file mode 100644
index 000000000..d5e33314b
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.h
@@ -0,0 +1,61 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SEARCHTREE_H
+#define _SEARCHTREE_H
+
+typedef struct treeNode{
+ void *key;
+ struct treeNode* parent;
+ struct treeNode* left; /*children*/
+ struct treeNode* right;
+} treeNode;
+
+treeNode* TreeNodeMake(void *key);
+void TreeNodeDeleteSingleNode(treeNode* node);
+void TreeNodeDeleteWholeTree(treeNode* node);
+void TreeNodePrint(treeNode* node,
+ void (*keyPrint) (void*));
+int TreeNodeDepth(treeNode* root);
+treeNode* TreeNodeMinimum(treeNode* node);
+treeNode* TreeNodeMaximum(treeNode* node);
+treeNode* TreeNodePredecessor(treeNode* node);
+treeNode* TreeNodeSuccessor(treeNode* node);
+treeNode* TreeNodeFind(treeNode* tree, void* key,
+ int (*compkey) (void*, void*));
+
+treeNode* TreeNodeInsert(treeNode* root, treeNode* newnode,
+ int (*comp) (void *, void *));
+treeNode* TreeNodeDeleteSingleNode(treeNode* tree, treeNode* node);
+
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/zlassert.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/zlassert.h
new file mode 100644
index 000000000..b9c073257
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/zlassert.h
@@ -0,0 +1,34 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+/*XXXblythe this file should be deleted*/
+#include <assert.h>