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; }
// 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); }
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); } }
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; } } } } }
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; }