short int legalizeEdge(Point * p, Triangle * T){
	short int ut, ua;
	Triangle * A;
	Point * center;

	for(ut=0; ut<3 && T->points[ut] != p; ++ut);
	if(ut==3) return -1;

	ADJACENT(T, T->points[NEXT(ut)], T->points[PREV(ut)], A);

	if(!A) return 1;

	for(ua=0; ua<3 && IN_TRIA(T, A->points[ua]); ua++);

	center = calcCenter(T);
	if(!center) return -2;

	if(DISQR(A->points[ua], center) >= DISQR(center, P0)){
		free(center);
		return 1;
	}
	free(center);

	if((ua=swap(T, A))<0) return -3;

	if((ua=legalizeEdge(p, T))<0) return -ua;
	if((ua=legalizeEdge(p, A))<0) return -ua;

	return 1;
}
short int delaunay(){
	Point * point, * p;
	Triangle * T, * A, * B, * C;
	int i, e, m;
	float a, b;
	short int len;

	for(e=0, p=pHead; p; ++e, p=p->next){
		if(ABS(p->x) > ABS(p->y)){
			i = ABS(p->x) > i ? ABS(p->x) : i;
		}
		else{
			i = ABS(p->y) > i ? ABS(p->y) : i;
		}
	}
	len = e;
	if(e==2) return -100;

	T = tHead = NEWT;
	T->next = NULL;

	P0 = NEWP;
	P0->id = -1;
	P0->x = i * 3 + 1;
	P0->y = 0;
	P0->next = pHead;
	pHead = P0;

	P1 = NEWP;
	P1->id = -2;
	P1->x = 0;
	P1->y = i * 3 + 1;
	P1->next = pHead;
	pHead = P1;

	P2 = NEWP;
	P2->id = -3;
	P2->x = P2->y = -(3 * i) - 1;
	P2->next = pHead;
	pHead = P2;

	for(point = pHead->next->next->next; point; point = point->next){
		for(T=tHead; T; T = T->next){
			e = pointInTriangle(point, T);
			switch(e){
				case -2: continue;
				case -1: goto pit;
				default: goto poe;
			}
		}
		return -200;
		poe:
		ADJACENT(T, T->points[e], T->points[NEXT(e)], A)
		if(!A) return -300;

		for(m=0; m<3 && A->points[m] != T->points[e]; ++m);
		if(m==3) return -400;

		B = NEWT;
		B->next = tHead;
		tHead = B;
		C = NEWT;
		C->next = tHead;
		tHead = C;

		B->points[0] = C->points[0] = T->points[e];
		B->points[1] = T->points[PREV(e)];
		C->points[1] = A->points[NEXT(m)] == T->points[NEXT(e)] ? A->points[PREV(m)] : A->points[NEXT(m)];
		T->points[e] = A->points[m] = B->points[2] = C->points[2] = point;

		if((i=legalizeEdge(point, T))<0) return i-510;
		if((i=legalizeEdge(point, A))<0) return i-520;
		if((i=legalizeEdge(point, B))<0) return i-530;
		if((i=legalizeEdge(point, C))<0) return i-540;

		continue;

		pit:

		A = NEWT;
		B = NEWT;
		A->next=tHead;
		tHead = A;
		B->next = tHead;
		tHead=B;

		A0 = P1;
		A1 = B->points[0] = P2;
		B->points[1] = P0;
		P2 = A2 = B->points[2] = point;

		if((i=legalizeEdge(point, T))<0) return i-610;
		if((i=legalizeEdge(point, A))<0) return i-620;
		if((i=legalizeEdge(point, B))<0) return i-630;


	}

	/*Calculate peak memory allocation*/
	mem=0;
	for(T=tHead, i=0; T; T=T->next, ++i);
	for(point=pHead, e=0; point; point=point->next, ++e);
	mem = i*sizeof(Triangle) + e*sizeof(Point);

	/*Patch*/
	for(T=tHead; T; T = T->next){
		/*Find # of external points*/
		for(i=0, e=0; i<3; e+=(T->points[i]->id < 0 ? 1 : 0), ++i);

		/*If # of external points is not equal to 1 continue*/
		if(e != 1) continue;

		check:

		/*Find external point*/
		for(e=0; e<3 && T->points[e]->id > -1; e++);

		/*Next mutual case*/
		/*Find the adjacent triangle*/
		ADJACENT(T, T->points[e], T->points[NEXT(e)], A)
		if(!A) return -710;

		/*Find the # of external points in the adjacent triangle*/
		for(i=0, m=0; i<3; m+=(A->points[i]->id < 0 ? 1 : 0), ++i);

		if(m==1){
			/*Find adjacent triangles external point*/
			for(m=0; m<3 && A->points[m]->id > -1; m++);
			/*Check whether the convex hull criteria apply*/
			a = CCW(T->points[PREV(e)], T->points[e],	A->points[T->points[NEXT(e)] == A->points[NEXT(m)] ? PREV(m) : NEXT(m)]);
			b = CCW(T->points[PREV(e)], T->points[NEXT(e)], A->points[T->points[NEXT(e)] == A->points[NEXT(m)] ? PREV(m) : NEXT(m)]);
			a*=b;
			if(a<0){
				if((i=swap(T, A))<0) return -711;
				T = P0->id<0 || P1->id<0 || P2->id<0 ? T : A;
				goto check;
			}
		}

		/*Find external point*/
		for(e=0; e<3 && T->points[e]->id > -1; e++);

		/*Prev mutual case*/
		/*Find the adjacent triangle*/
		ADJACENT(T, T->points[e], T->points[PREV(e)], A)
		if(!A) return -720;

		/*Find the external point in the adjacent triangle*/
		for(i=0, m=0; i<3; m+=(A->points[i]->id < 0 ? 1 : 0), ++i);

		if(m==1){
			/*Find adjacent triangles external point*/
			for(m=0; m<3 && A->points[m]->id > -1; m++);
			/*Check whether the convex hull criteria apply*/
			a = CCW(T->points[NEXT(e)], T->points[e],       A->points[T->points[NEXT(e)] == A->points[NEXT(m)] ? NEXT(m) : PREV(m)]);
			b = CCW(T->points[NEXT(e)], T->points[PREV(e)], A->points[T->points[NEXT(e)] == A->points[NEXT(m)] ? NEXT(m) : PREV(m)]);
			a*=b;
			if(a<0){
				if((i=swap(T, A))<0)return -721;;
				T = P0->id<0 || P1->id<0 || P2->id<0 ? T : A;
				goto check;
			}
		}

	}

	for(T=tHead, A=NULL; T; A=T, T=(A==NULL?T:T->next)){
		for(i=0, e=0; i<3; e+=(T->points[i]->id<0?1:0), ++i);
		if(e==0) continue;
		if(!A){
			A=T;
			T=T->next;
			free(A);
			A=NULL;
			tHead=T;
		} else {
			A->next = T->next;
			free(T);
			T=A;
		}
	}

	for(i=0; i<3; ++i){
		point=pHead;
		pHead=pHead->next;
		free(point);
	}

	//return 1;
	return len;
}
Exemplo n.º 3
0
// Please note that the edge to be flipped here is the 2nd and 4th parameters.
//
// flip <abd>,<dbc> adds 2 children to each, <abc>,<acd>
//
// the shared edge bd gets replaced with shared edge ac
void DirectedGraph::flipTriangles(int pIdx1, int pIdx2, int pIdx3, int pIdx4) {
	// XXX finish rename in DGraph::flipTri
	// shared edge ij; 124=kij is ccw, 423=jil is ccw.
	int kIdx = pIdx1;
	int iIdx = pIdx2;
	int lIdx = pIdx3;
	int jIdx = pIdx4;
#ifdef DIRECTEDGRAPH_CHECK
	cout << "DAG::flipTris, args=" << pIdx1 << "," << pIdx2 << "," << pIdx3 << "," << pIdx4 << "." << endl;

	cout << "Points: " << endl;
	cout << " 1. " << pointSet_[pIdx1] << endl;
	cout << " 2. " << pointSet_[pIdx2] << endl;
	cout << " 3. " << pointSet_[pIdx3] << endl;
	cout << " 4. " << pointSet_[pIdx4] << endl;

	assert(containsTri(dagNodes_, pIdx1, pIdx2, pIdx4));
	assert(isTriangleCCW(pointSet_, TriRecord(pIdx1, pIdx2, pIdx4)));
	assert(containsTri(dagNodes_, pIdx4, pIdx2, pIdx3));
	assert(isTriangleCCW(pointSet_, TriRecord(pIdx4, pIdx2, pIdx3)));
#endif

	// Seek the lowest DAGNode which contains the point.
	vector<shared_ptr<DAGNode>> nodes = DAGNode::leafNodesContainingEdge(root_, pointSet_, pIdx2, pIdx4);
#ifdef DIRECTEDGRAPH_CHECK
	// cout << "DAG.flipTriangles, numLeafNodes containing edge: " << nodes.size() << endl;
	// outputTriList(nodes);
	assert(nodes.size() == 2);
#endif

	// Ensure nodeIJK is the one with kIdx
	int nodesIJKIdx = (nodes[0]->tri_.hasPointIndex(kIdx)) ? 0 : 1;
	int nodesJILIdx = 1 - nodesIJKIdx;

	shared_ptr<DAGNode> nodeIJK = nodes[nodesIJKIdx];
	shared_ptr<DAGNode> nodeJIL = nodes[nodesJILIdx];

	// impl ASSUMPTION that TriR(x,y,z) == TriR(x,z,y), etc.
	// (as used in DirectedGraph).

	// swap 24 edge with 13 edge
	// ASSUMPTION that points for TriRecord are CCW
	// flip <abd>,<dbc> adds 2 children to each, <abc>,<acd> (preserves CCW)
	TriRecord triILK(iIdx, lIdx, kIdx);
	TriRecord triLJK(lIdx, jIdx, kIdx);
#ifdef DIRECTEDGRAPH_CHECK
	assert(isTriangleCCW(pointSet_, triILK));
	assert(isTriangleCCW(pointSet_, triLJK));
#endif

	shared_ptr<DAGNode> nodeILK(new DAGNode(triILK));
	shared_ptr<DAGNode> nodeLJK(new DAGNode(triLJK));

	nodeIJK->children_.push_back(nodeILK);
	nodeIJK->children_.push_back(nodeLJK);

	nodeJIL->children_.push_back(nodeILK);
	nodeJIL->children_.push_back(nodeLJK);

	// Add to instance's list of dagNodes
	dagNodes_.push_back(nodeILK);
	dagNodes_.push_back(nodeLJK);

	// Update triangulation
	delaunay::flipTriangles(trist_,
	                        nodeIJK->fIndex_,
	                        nodeJIL->fIndex_,
	                        nodeILK,
	                        nodeLJK);

#ifdef DIRECTEDGRAPH_CHECK
	checkConsistent();
#endif

	// legalizeEdge[FLIPTRIANGLE]

	legalizeEdge(pIdx1, pIdx2, pIdx3);
	legalizeEdge(pIdx1, pIdx3, pIdx4);
}
Exemplo n.º 4
0
void DirectedGraph::addVertex(int pIdx) {
#ifdef DIRECTEDGRAPH_CHECK
	cout << "DAG.addVertex(" << pIdx << ")" << endl;
#endif

	// Seek the lowest DAGNode which contains the point.
	vector<shared_ptr<DAGNode>> leaves = DAGNode::leafNodesContainingPoint(root_, pointSet_, pIdx);

#ifdef DIRECTEDGRAPH_CHECK
	cout << "DAG.addVertex, numLeafNodes containing pt: " << leaves.size() << endl;
	assert(leaves.size() == 1 || leaves.size() == 2);
#endif

	if (leaves.size() == 1) {
		// New point fits cleanly within another triangle,
		// split the triangle into three.

		shared_ptr<DAGNode> node = leaves[0];  // IJK

		TriRecord parentTri = node->tri_;
		int parentIdx1, parentIdx2, parentIdx3;
		parentTri.get(parentIdx1, parentIdx2, parentIdx3);

		// Construct 3 TriRecords, one for each child triangle
		// ASSUMPTION that points for TriRecord are CCW
		shared_ptr<DAGNode> child1(new DAGNode(TriRecord(pIdx, parentIdx1, parentIdx2)));  // RIJ
		shared_ptr<DAGNode> child2(new DAGNode(TriRecord(pIdx, parentIdx2, parentIdx3)));  // RJK
		shared_ptr<DAGNode> child3(new DAGNode(TriRecord(pIdx, parentIdx3, parentIdx1)));  // RKI
		node->children_.push_back(child1);
		node->children_.push_back(child2);
		node->children_.push_back(child3);

		// Add to instance's list of dagNodes
		dagNodes_.push_back(child1);
		dagNodes_.push_back(child2);
		dagNodes_.push_back(child3);

		// Update triangulation
		addVertexInTri(trist_,
		               node->fIndex_,
		               child1,
		               child2,
		               child3);

#ifdef DIRECTEDGRAPH_CHECK
		checkConsistent();
#endif

		// legalizeEdge[ADDVERT(A)]

		/// edges 12, 13, 23 are the "link" of the inserted point.
		/// So, here we 'flip edges' until things are locally delaunday.
		legalizeEdge(pIdx, parentIdx1, parentIdx2);
		legalizeEdge(pIdx, parentIdx2, parentIdx3);
		legalizeEdge(pIdx, parentIdx3, parentIdx1);
	} else if (leaves.size() == 2) {
		// New point on the edge of other triangles,
		// split the two triangles to get four triangles total.

		// new point R lies on edge IJ
		shared_ptr<DAGNode> nodeIJK = leaves[0];
		shared_ptr<DAGNode> nodeILJ = leaves[1];

		// need to sort out the point indices
		int iIdx, jIdx, kIdx, lIdx;
		getIndicesKIJL(nodeIJK->tri_, nodeILJ->tri_, kIdx, iIdx, jIdx, lIdx);

		// Create triangles RJK, RKI, RIL, RLJ
		shared_ptr<DAGNode> nodeRJK(new DAGNode(TriRecord(pIdx, jIdx, kIdx)));
		shared_ptr<DAGNode> nodeRKI(new DAGNode(TriRecord(pIdx, kIdx, iIdx)));
		shared_ptr<DAGNode> nodeRIL(new DAGNode(TriRecord(pIdx, iIdx, lIdx)));
		shared_ptr<DAGNode> nodeRLJ(new DAGNode(TriRecord(pIdx, lIdx, jIdx)));

		nodeIJK->children_.push_back(nodeRJK);
		nodeIJK->children_.push_back(nodeRKI);
		nodeILJ->children_.push_back(nodeRIL);
		nodeILJ->children_.push_back(nodeRLJ);

		dagNodes_.push_back(nodeRJK);
		dagNodes_.push_back(nodeRKI);
		dagNodes_.push_back(nodeRIL);
		dagNodes_.push_back(nodeRLJ);

		// Update triangulation
		addVertexOnEdge(trist_,
		                nodeIJK->fIndex_,
		                nodeILJ->fIndex_,
		                nodeRJK,
		                nodeRKI,
		                nodeRIL,
		                nodeRLJ);

#ifdef DIRECTEDGRAPH_CHECK
		checkConsistent();
#endif

		// legalizeEdge[ADDVERT(B)]
		// legalize il, lj, jk, ki
		legalizeEdge(pIdx, jIdx, kIdx);
		legalizeEdge(pIdx, kIdx, iIdx);
		legalizeEdge(pIdx, iIdx, lIdx);
		legalizeEdge(pIdx, lIdx, jIdx);
	}
}
Exemplo n.º 5
0
void ReTriangulation::delaunayTriangulation(std::vector<Vec3f>* point, Vec3i face, std::vector<int>& idx, std::vector<int>& pointOnEdge, std::vector<int>& pointOnFace, std::vector<Vec3i>& triangles, int preNbPoint)
{
	GeometricFunc func;
	std::vector<std::vector<int>> trianglesAroundEdge;
	std::vector<std::vector<int>> edgesInTriangle;
	std::vector<Vec2i> edges;
	Vec3f normal=func.computeNormal(point, face);

	triangles.push_back(face);

	for(int i=0;i<pointOnEdge.size();i++)
	{
		for(int j=0;j<triangles.size();j++)
		{
			int edgeIdx=-1;
			for(int k=0;k<3;k++)
			{
				Vec3f l1=(*point)[triangles[j][k]];
				Vec3f l2=(*point)[triangles[j][(k+1)%3]];
				Vec3f p=(*point)[pointOnEdge[i]];
				if(func.isPointInLine(l1, l2, p))
				{
					edgeIdx=(k+2)%3;
					break;
				}
			}
			if(edgeIdx>-1)
			{
				//add triangles and edges
				triangles.push_back(Vec3i(triangles[j][(edgeIdx+1)%3], pointOnEdge[i], triangles[j][edgeIdx]));
				triangles.push_back(Vec3i(pointOnEdge[i], triangles[j][(edgeIdx+2)%3], triangles[j][edgeIdx]));

				//remove triangle
				triangles[j]=triangles[triangles.size()-1];
				triangles.pop_back();
				break;
			}
		}
	}

	for(int i=0;i<pointOnFace.size();i++)
	{
		int count=0;
		for(int j=0;j<triangles.size();j++)
		{
			int edgeIdx=-1;
			for(int k=0;k<3;k++)
			{
				Vec3f l1=(*point)[triangles[j][k]];
				Vec3f l2=(*point)[triangles[j][(k+1)%3]];
				Vec3f p=(*point)[pointOnFace[i]];
				if(func.isPointInLine(l1, l2, p))
				{
					edgeIdx=(k+2)%3;
					break;
				}
			}
			if(edgeIdx>-1)
			{
				//add triangles and edges
				triangles.push_back(Vec3i(triangles[j][(edgeIdx+1)%3], pointOnFace[i], triangles[j][edgeIdx]));
				triangles.push_back(Vec3i(pointOnFace[i], triangles[j][(edgeIdx+2)%3], triangles[j][edgeIdx]));

				//remove triangle
				triangles[j]=triangles[triangles.size()-1];
				triangles.pop_back();
				count++;
				if(count>1)
					break;
			}
			else if(func.isPointInTri(point, triangles[j], pointOnFace[i]))
			{
				//add triangles
				triangles.push_back(Vec3i(pointOnFace[i], triangles[j][0], triangles[j][1]));
				triangles.push_back(Vec3i(pointOnFace[i], triangles[j][1], triangles[j][2]));
				triangles.push_back(Vec3i(pointOnFace[i], triangles[j][2], triangles[j][0]));

				//remove triangle
				triangles[j]=triangles[triangles.size()-1];
				triangles.pop_back();

				int triIdx=triangles.size()-2;
				legalizeEdge(point, pointOnFace[i], Vec2i(triangles[triIdx][1], triangles[triIdx][2]), triIdx, triangles);
				triIdx=triangles.size()-1;
				legalizeEdge(point, pointOnFace[i], Vec2i(triangles[triIdx][1], triangles[triIdx][2]), triIdx, triangles);
				triIdx=j;
				legalizeEdge(point, pointOnFace[i], Vec2i(triangles[triIdx][1], triangles[triIdx][2]), triIdx, triangles);
				break;
			}
		}
	}

	for(int i=0;i<idx.size();i++)
	{
		for(int j=0;j<triangles.size();j++)
		{
			for(int k=0;k<3;k++)
			{
				if(triangles[j][k]==idx[i])
				{
					triangles[j]=triangles[triangles.size()-1];
					triangles.pop_back();
					j--;
					break;
				}
			}
		}
	}
}
Exemplo n.º 6
0
int ReTriangulation::legalizeEdge(std::vector<Vec3f>* point, int pointIdx, Vec2i edge, int triIdx, std::vector<Vec3i>& triangles)
{
	GeometricFunc func;
	int _triIdx;
	int _pointIdx;
	bool flag=true;

	//1. find the triangle that contains the edge
	for(int i=0;i<triangles.size();i++)
	{
		if(func.isTriangleContainEdge(edge, triangles[i]))
		{
			if(i!=triIdx)
			{
				_triIdx=i;
				for(int j=0;j<3;j++)
				{
					if((triangles[i][j]!=edge[0])&&(triangles[i][j]!=edge[1]))
					{
						_pointIdx=triangles[i][j];
						break;
					}
				}
				flag=false;
				break;
			}
		}
	}
	if(flag)
	{
		return 0;
	}
	else
	{
		Vec3f faceNormal=func.computeNormal(point, triangles[_triIdx]);
		Vec3f circumCenter=func.computeCircumcenter(point, triangles[_triIdx], faceNormal);
		float radius=((*point)[edge[0]]-circumCenter).norm();

		if(((*point)[pointIdx]-circumCenter).norm()<radius)
		{
			Vec3i face1=Vec3i(pointIdx, _pointIdx, edge[0]);
			Vec3i face2=Vec3i(pointIdx, _pointIdx, edge[1]);
			Vec3f normal1=func.computeNormal(point, face1);
			if(normal1*faceNormal<0)
			{
				int temp=face1[2];
				face1[2]=face1[1];
				face1[1]=temp;
			}
			else
			{
				int temp=face2[2];
				face2[2]=face2[1];
				face2[1]=temp;
			}

			//replace triangles
			triangles[triIdx]=face1;
			triangles[_triIdx]=face2;

			legalizeEdge(point, pointIdx, Vec2i(_pointIdx, edge[0]), triIdx, triangles);
			legalizeEdge(point, pointIdx, Vec2i(_pointIdx, edge[1]), _triIdx, triangles);
		}
	}
	return 0;
}