Example #1
0
//triangulation by ear removal
int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles) {
	long numvertices;
	PartitionVertex *vertices;
	PartitionVertex *ear = 0;
	TPPLPoly triangle;
	long i,j;
	bool earfound;

	if(poly->GetNumPoints() < 3) return 0;
	if(poly->GetNumPoints() == 3) {
		triangles->push_back(*poly);
		return 1;
	}

	numvertices = poly->GetNumPoints();

	vertices = new PartitionVertex[numvertices];
	for(i=0;i<numvertices;i++) {
		vertices[i].isActive = true;
		vertices[i].p = poly->GetPoint(i);
		if(i==(numvertices-1)) vertices[i].next=&(vertices[0]);
		else vertices[i].next=&(vertices[i+1]);
		if(i==0) vertices[i].previous = &(vertices[numvertices-1]);
		else vertices[i].previous = &(vertices[i-1]);
	}
	for(i=0;i<numvertices;i++) {
		UpdateVertex(&vertices[i],vertices,numvertices);
	}

	for(i=0;i<numvertices-3;i++) {
		earfound = false;
		//find the most extruded ear
		for(j=0;j<numvertices;j++) {
			if(!vertices[j].isActive) continue;
			if(!vertices[j].isEar) continue;
			if(!earfound) {
				earfound = true;
				ear = &(vertices[j]);
			} else {
				if(vertices[j].angle > ear->angle) {
					ear = &(vertices[j]);				
				}
			}
		}
		if(!earfound) {
			delete [] vertices;
			return 0;
		}

		triangle.Triangle(ear->previous->p,ear->p,ear->next->p);
		triangles->push_back(triangle);

		ear->isActive = false;
		ear->previous->next = ear->next;
		ear->next->previous = ear->previous;

		if(i==numvertices-4) break;

		UpdateVertex(ear->previous,vertices,numvertices);
		UpdateVertex(ear->next,vertices,numvertices);
	}
	for(i=0;i<numvertices;i++) {
		if(vertices[i].isActive) {
			triangle.Triangle(vertices[i].previous->p,vertices[i].p,vertices[i].next->p);
			triangles->push_back(triangle);
			break;
		}
	}

	delete [] vertices;

	return 1;
}
Example #2
0
//minimum-weight polygon triangulation by dynamic programming
//O(n^3) time complexity
//O(n^2) space complexity
int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles) {
	long i,j,k,gap,n;
	DPState **dpstates;
	TPPLPoint p1,p2,p3,p4;
	long bestvertex;
	tppl_float weight,minweight,d1,d2;
	Diagonal diagonal,newdiagonal;
	list<Diagonal> diagonals;
	TPPLPoly triangle;
	int ret = 1;

	n = poly->GetNumPoints();
	dpstates = new DPState *[n];
	for(i=1;i<n;i++) {
		dpstates[i] = new DPState[i];
	}

	//init states and visibility
	for(i=0;i<(n-1);i++) {
		p1 = poly->GetPoint(i);
		for(j=i+1;j<n;j++) {
			dpstates[j][i].visible = true;
			dpstates[j][i].weight = 0;
			dpstates[j][i].bestvertex = -1;
			if(j!=(i+1)) {
				p2 = poly->GetPoint(j);
				
				//visibility check
				if(i==0) p3 = poly->GetPoint(n-1);
				else p3 = poly->GetPoint(i-1);
				if(i==(n-1)) p4 = poly->GetPoint(0);
				else p4 = poly->GetPoint(i+1);
				if(!InCone(p3,p1,p4,p2)) {
					dpstates[j][i].visible = false;
					continue;
				}

				if(j==0) p3 = poly->GetPoint(n-1);
				else p3 = poly->GetPoint(j-1);
				if(j==(n-1)) p4 = poly->GetPoint(0);
				else p4 = poly->GetPoint(j+1);
				if(!InCone(p3,p2,p4,p1)) {
					dpstates[j][i].visible = false;
					continue;
				}

				for(k=0;k<n;k++) {
					p3 = poly->GetPoint(k);
					if(k==(n-1)) p4 = poly->GetPoint(0);
					else p4 = poly->GetPoint(k+1);
					if(Intersects(p1,p2,p3,p4)) {
						dpstates[j][i].visible = false;
						break;
					}
				}
			}
		}
	}
	dpstates[n-1][0].visible = true;
	dpstates[n-1][0].weight = 0;
	dpstates[n-1][0].bestvertex = -1;

	for(gap = 2; gap<n; gap++) {
		for(i=0; i<(n-gap); i++) {
			j = i+gap;
			if(!dpstates[j][i].visible) continue; 
			bestvertex = -1;
			for(k=(i+1);k<j;k++) {
				if(!dpstates[k][i].visible) continue; 
				if(!dpstates[j][k].visible) continue;

				if(k<=(i+1)) d1=0;
				else d1 = Distance(poly->GetPoint(i),poly->GetPoint(k));
				if(j<=(k+1)) d2=0;
				else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j));

				weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2;

				if((bestvertex == -1)||(weight<minweight)) {
					bestvertex = k;
					minweight = weight;
				}
			}
			if(bestvertex == -1) {
				for(i=1;i<n;i++) {
					delete [] dpstates[i];
				}
				delete [] dpstates;

				return 0;
			}
			
			dpstates[j][i].bestvertex = bestvertex;
			dpstates[j][i].weight = minweight;
		}
	}

	newdiagonal.index1 = 0;
	newdiagonal.index2 = n-1;
	diagonals.push_back(newdiagonal);
	while(!diagonals.empty()) {
		diagonal = *(diagonals.begin());
		diagonals.pop_front();
		bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex;
		if(bestvertex == -1) {
			ret = 0;		
			break;
		}
		triangle.Triangle(poly->GetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2));
		triangles->push_back(triangle);
		if(bestvertex > (diagonal.index1+1)) {
			newdiagonal.index1 = diagonal.index1;
			newdiagonal.index2 = bestvertex;
			diagonals.push_back(newdiagonal);
		}
		if(diagonal.index2 > (bestvertex+1)) {
			newdiagonal.index1 = bestvertex;
			newdiagonal.index2 = diagonal.index2;
			diagonals.push_back(newdiagonal);
		}
	}

	for(i=1;i<n;i++) {
		delete [] dpstates[i];
	}
	delete [] dpstates;

	return ret;
}
Example #3
0
//triangulates monotone polygon
//O(n) time, O(n) space complexity
int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles) {
	long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
	TPPLPoint *points;
	long numpoints;
	TPPLPoly triangle;

	numpoints = inPoly->GetNumPoints();
	points = inPoly->GetPoints();

	//trivial calses
	if(numpoints < 3) return 0;
	if(numpoints == 3) {
		triangles->push_back(*inPoly);
	}

	topindex = 0; bottomindex=0;
	for(i=1;i<numpoints;i++) {
		if(Below(points[i],points[bottomindex])) bottomindex = i;
		if(Below(points[topindex],points[i])) topindex = i;
	}

	//check if the poly is really monotone
	i = topindex;
	while(i!=bottomindex) {
		i2 = i+1; if(i2>=numpoints) i2 = 0;
		if(!Below(points[i2],points[i])) return 0;
		i = i2;
	}
	i = bottomindex;
	while(i!=topindex) {
		i2 = i+1; if(i2>=numpoints) i2 = 0;
		if(!Below(points[i],points[i2])) return 0;
		i = i2;
	}

	char *vertextypes = new char[numpoints];
	long *priority = new long[numpoints];

	//merge left and right vertex chains
	priority[0] = topindex;
	vertextypes[topindex] = 0;
	leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0;
	rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1;
	for(i=1;i<(numpoints-1);i++) {
		if(leftindex==bottomindex) {
			priority[i] = rightindex;
			rightindex--; if(rightindex<0) rightindex = numpoints-1;
			vertextypes[priority[i]] = -1;
		} else if(rightindex==bottomindex) {
			priority[i] = leftindex;
			leftindex++;  if(leftindex>=numpoints) leftindex = 0;
			vertextypes[priority[i]] = 1;
		} else {
			if(Below(points[leftindex],points[rightindex])) {
				priority[i] = rightindex;
				rightindex--; if(rightindex<0) rightindex = numpoints-1;
				vertextypes[priority[i]] = -1;
			} else {
				priority[i] = leftindex;
				leftindex++;  if(leftindex>=numpoints) leftindex = 0;
				vertextypes[priority[i]] = 1;			
			}
		}
	}
	priority[i] = bottomindex;
	vertextypes[bottomindex] = 0;

	long *stack = new long[numpoints];
	long stackptr = 0;

	stack[0] = priority[0];
	stack[1] = priority[1];
	stackptr = 2;

	//for each vertex from top to bottom trim as many triangles as possible
	for(i=2;i<(numpoints-1);i++) {
		vindex = priority[i];
		if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) {
			for(j=0;j<(stackptr-1);j++) {
				if(vertextypes[vindex]==1) {
					triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
				} else {
					triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
				}
				triangles->push_back(triangle);
			}
			stack[0] = priority[i-1];
			stack[1] = priority[i];
			stackptr = 2;
		} else {
			stackptr--;
			while(stackptr>0) {
				if(vertextypes[vindex]==1) {
					if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) {
						triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]);
						triangles->push_back(triangle);
						stackptr--;
					} else {
						break;
					}
				} else {
					if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) {
						triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]);
						triangles->push_back(triangle);
						stackptr--;
					} else {
						break;
					}
				}
			}
			stackptr++;
			stack[stackptr] = vindex;
			stackptr++;
		}
	}
	vindex = priority[i];
	for(j=0;j<(stackptr-1);j++) {
		if(vertextypes[stack[j+1]]==1) {
			triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
		} else {
			triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
		}
		triangles->push_back(triangle);
	}

	delete [] priority;
	delete [] vertextypes;
	delete [] stack;

	return 1;
}