diff options
Diffstat (limited to 'mesalib/src/glu/sgi/libnurbs/nurbtess')
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> |