void Delaunay::removeBounding( TriangleVector inSet, TriangleVector &outSet, const int &index ) { for (TriangleVector::iterator iter = inSet.begin(); iter != inSet.end(); iter++) { if (iter->m_vertices[0].m_index >= 0 && iter->m_vertices[1].m_index >= 0 && iter->m_vertices[2].m_index >= 0 && iter->isVertex(index) && iter->angleCriterion(m_minAngle, m_maxAngle)) { outSet.push_back(*iter); } } }
void Delaunay::addBounding( const VertexVector &verSet, TriangleVector &triSet ) { double max_x = -100000, max_y = -100000; double min_x = 100000, min_y = 100000; for (int i = 0; i < verSet.size(); i++) { Vec3d v = verSet[i].m_xyz; max_x = max_x < v[0] ? v[0] : max_x; min_x = min_x > v[0] ? v[0] : min_x; max_y = max_y < v[1] ? v[1] : max_y; min_y = min_y > v[1] ? v[1] : min_y; } // 将矩形区域的外接三角形作为边界 double dx = max_x - min_x; double dy = max_y - min_y; double mid_x = (min_x + max_x) / 2; double mid_y = (min_y + max_y) / 2; // 为了去除边界方便讲边界点的索引置为负数 Vertex v0(Vec3d(mid_x, max_y + dy, 0.0f), -1); Vertex v1(Vec3d(mid_x - dx, min_y, 0.0f), -2); Vertex v2(Vec3d(mid_x + dx, min_y, 0.0f), -3); triSet.push_back(Triangle(v0, v1, v2)); }
void Delaunay::saveTriangles( const TriangleVector &triSet, char* file ) { ofstream ofs(file); if (ofs) { ofs << triSet.size() << endl; for (int i = 0; i < triSet.size(); i++) { Triangle t = triSet[i]; for (int j = 0; j < Triangle::Vertex_Size; j++) { ofs << t.m_vertices[j].m_xyz; } ofs << endl; } } }
void Delaunay::drawTrianglesOnPlane( const TriangleVector &triSet ) { int width = 1024, height = 768; Mat triangleImg(height, width, CV_8UC3, Scalar::all(0)); if (triSet.size() == 0) { imshow("Triangle", triangleImg); waitKey(); return; } double max_x = -100000, max_y = -100000; double min_x = 100000, min_y = 100000; for (int i = 0; i < triSet.size(); i++) { for (int j = 0; j < Triangle::Vertex_Size; j++) { Vec3d v = triSet[i].m_vertices[j].m_xyz; max_x = max_x < v[0] ? v[0] : max_x; min_x = min_x > v[0] ? v[0] : min_x; max_y = max_y < v[1] ? v[1] : max_y; min_y = min_y > v[1] ? v[1] : min_y; } } for (int i = 0; i < triSet.size(); i++) { Point ps[3]; for (int j = 0; j < Triangle::Vertex_Size; j++) { double tmpx = triSet[i].m_vertices[j].m_xyz[0]; double tmpy = triSet[i].m_vertices[j].m_xyz[1]; double x = (tmpx - min_x) * 800 / (max_x - min_x) + 100; double y = (max_y - tmpy) * 600 / (max_y - min_y) + 100; ps[j].x = (int)x; ps[j].y = (int)y; } line(triangleImg, ps[0], ps[1], Scalar::all(255)); line(triangleImg, ps[1], ps[2], Scalar::all(255)); line(triangleImg, ps[2], ps[0], Scalar::all(255)); } for (int i = 0; i < triSet.size(); i++) { for (int j = 0; j < 3; j++) { double tmpx = triSet[i].m_vertices[j].m_xyz[0]; double tmpy = triSet[i].m_vertices[j].m_xyz[1]; double fx = (tmpx - min_x) * 800 / (max_x - min_x) + 100; double fy = (max_y - tmpy) * 600 / (max_y - min_y) + 100; int x = (int)fx; int y = (int)fy; if (triSet[i].m_vertices[j].m_index < 0) { for (int m = -1; m <= 1; m++) { for (int n = -1; n <= 1; n++) { triangleImg.at<Vec3b>(y + m, x + n) = Vec3b(0, 255, 0); } } } else { for (int m = -1; m <= 1; m++) { for (int n = -1; n <= 1; n++) { triangleImg.at<Vec3b>(y + m, x + n) = Vec3b(255, 0, 255); } } } } } imshow("Triangle", triangleImg); waitKey(); }
bool Delaunay::flipTest( TriangleVector &triSet, Triangle t ) { bool flipped = false; Vertex a = t.m_vertices[0]; Vertex b = t.m_vertices[1]; Vertex c = t.m_vertices[2]; TriangleVector tSet; for (TriangleVector::iterator iter = triSet.begin(); iter != triSet.end();) { Vertex d; d.m_index = -100; // 寻找拥有相同边ab的三角形 int satisfy[3] = {0, 0, 0}; for (int j = 0, k = 1; j < Triangle::Vertex_Size; j++, k *= 2) { if (iter->m_vertices[j].m_index == a.m_index || iter->m_vertices[j].m_index == b.m_index) { satisfy[j] = k; } } switch (satisfy[0] | satisfy[1] | satisfy[2]) { case 3: // v2 if (Vertex::cross(a, c, iter->m_vertices[2]) != 0 && Vertex::cross(b, c, iter->m_vertices[2]) != 0) { d = iter->m_vertices[2]; } break; case 5: // v1 if (Vertex::cross(a, c, iter->m_vertices[1]) != 0 && Vertex::cross(b, c, iter->m_vertices[1]) != 0) { d = iter->m_vertices[1]; } break; case 6: // v0 if (Vertex::cross(a, c, iter->m_vertices[0]) != 0 && Vertex::cross(b, c, iter->m_vertices[0]) != 0) { d = iter->m_vertices[0]; } break; default: break; } if (d.m_index != -100) { if (inCircle(a, b, c, d)) // 判断d是否在三角形abc的外接圆内 { flipped = true; Triangle t0(a, d, c); Triangle t1(d, b, c); tSet.push_back(t0); tSet.push_back(t1); iter = triSet.erase(iter); break; } else { iter++; } } else { iter++; } } for (int i = 0; i < tSet.size(); i++) { if (!flipTest(triSet, tSet[i])) { triSet.push_back(tSet[i]); } } return flipped; }
void Delaunay::insertVertex( TriangleVector &triSet, const Vertex &v ) { TriangleVector tmp; for (TriangleVector::iterator iter = triSet.begin(); iter != triSet.end();) { int r = iter->inTriangle(v); // 判断点是否在三角形内 // cout << iter->m_vertices[0].m_xyz // << iter->m_vertices[1].m_xyz // << iter->m_vertices[2].m_xyz << endl; switch (r) { case 0: // in { Triangle t0(iter->m_vertices[0], iter->m_vertices[1], v); Triangle t1(iter->m_vertices[1], iter->m_vertices[2], v); Triangle t2(iter->m_vertices[2], iter->m_vertices[0], v); tmp.push_back(t0); tmp.push_back(t1); tmp.push_back(t2); iter = triSet.erase(iter); } break; case -1: // on v0v1 { Triangle t0(iter->m_vertices[1], iter->m_vertices[2], v); Triangle t1(iter->m_vertices[2], iter->m_vertices[0], v); tmp.push_back(t0); tmp.push_back(t1); iter = triSet.erase(iter); } break; case -2: // on v1v2 { Triangle t0(iter->m_vertices[0], iter->m_vertices[1], v); Triangle t1(iter->m_vertices[2], iter->m_vertices[0], v); tmp.push_back(t0); tmp.push_back(t1); iter = triSet.erase(iter); } break; case -3: // on v2v0 { Triangle t0(iter->m_vertices[0], iter->m_vertices[1], v); Triangle t1(iter->m_vertices[1], iter->m_vertices[2], v); tmp.push_back(t0); tmp.push_back(t1); iter = triSet.erase(iter); } break; default: iter++; break; } if (r <= 0) { break; } } for (int i = 0; i < tmp.size(); i++) { if (!flipTest(triSet, tmp[i])) // 优化delaunay三角 { triSet.push_back(tmp[i]); } /* drawTrianglesOnPlane(triSet);*/ } }
void Delaunay::computeDelaunay(Mesh &mesh) { int size = (int)mesh.getVerticesSize(); if (size == 0) { return; } mesh.computeVerticesNormals(); m_preSize = mesh.m_curIndex; TriangleSet triSet; // 依次遍历每个点,寻找最近邻,进行三角化 for (; mesh.m_curIndex < size; mesh.m_curIndex++) { Vertex v = mesh.getVertex(mesh.m_curIndex); if (v.m_isInner) { mesh.pushTriBeginIndex((int)triSet.size()); continue; } Vec3d normal = v.m_normal; int id = 2; // 判断法向量哪个不为0,z->y->x if (normal[2] != 0) // z { id = 2; } else if (normal[1] != 0)// y { id = 1; } else if (normal[0] != 0)// x { id = 0; } else // 法向量为(0, 0, 0), { mesh.pushTriBeginIndex((int)triSet.size()); continue; } double minDistance = -1; int cnt = v.m_neighbors[0]; // 最近邻数目 double dists[k]; for (int j = 1; j < cnt + 1; j++) { Vec3d dv = mesh.getVertex(v.m_neighbors[j]).m_xyz - v.m_xyz; dists[j] = dv.ddot(dv); } minDistance = dists[1]; VertexVector vVector, tmpvVector; // 将最近邻点投射到该点的切平面上 for (int j = 1; j < cnt + 1; j++) { Vertex tmpv = mesh.getVertex(v.m_neighbors[j]); if (dists[j] < u * minDistance || // 去除非常接近的点 (tmpv.m_index < v.m_index && tmpv.m_index >= m_preSize) || // 去除已遍历过的点 tmpv.m_isInner) // 去除内点 { continue; } Vec3d vv = tmpv.m_xyz - v.m_xyz; double dist2 = dists[j] * 0.75f; // sqrt double alpha = vv.dot(normal); alpha = alpha * alpha; if (alpha > dist2) // 去除与法向量夹角小于30度或大于150度的点 { continue; } Vec3d proj = tmpv.m_xyz - alpha * normal; // 投射到切平面 tmpvVector.push_back(Vertex(proj, v.m_neighbors[j])); } if (tmpvVector.size() < 3) // 少于3个不能构成三角形 { mesh.pushTriBeginIndex((int)triSet.size()); continue; } // 将切平面转换为x-y平面进行三角形计算 vVector.push_back(Vertex(Vec3d(0, 0, 0), mesh.m_curIndex)); // 原点 Vec3d vx = tmpvVector[0].m_xyz - v.m_xyz; // x轴 vx = normalize(vx); for (int j = 0; j < tmpvVector.size(); j++) { Vec3d vv = tmpvVector[j].m_xyz - v.m_xyz; double x = vv.dot(vx); double y = vx.cross(vv)[id] / normal[id]; Vec3d proj(x, y, 0); vVector.push_back(Vertex(proj, tmpvVector[j].m_index)); } TriangleVector tVector; computeDelaunay(vVector, tVector); // cout << vVector.size() << " " << tVector.size() << endl; // drawTrianglesOnPlane(tVector); for (int j = 0; j < tVector.size(); j++) { Triangle t = tVector[j]; t.m_vertices[0] = mesh.getVertex(t.m_vertices[0].m_index); t.m_vertices[1] = mesh.getVertex(t.m_vertices[1].m_index); t.m_vertices[2] = mesh.getVertex(t.m_vertices[2].m_index); triSet.insert(t); } mesh.pushTriBeginIndex((int)triSet.size()); } for (TriangleSet::iterator iter = triSet.begin(); iter != triSet.end(); iter++) { mesh.m_triangles.push_back(*iter); } }
virtual NxU32 * removeTjunctions(NxU32 vcount, const float *vertices, size_t tcount, const NxU32 *indices, size_t &tcount_out, const NxU32 * ids) { NxU32 *ret = 0; release(); mVcount = vcount; mVertices = vertices; mTcount = (NxU32)tcount; tcount_out = 0; mTcount = (NxU32)tcount; mMaxTcount = (NxU32)tcount*2; mInputTriangles = new Triangle[mMaxTcount]; Triangle *t = mInputTriangles; mEdges = new RtEdge[mMaxTcount*3]; mEdgeCount = 0; NxU32 id = 0; RtEdge *e = mEdges; for (NxU32 i=0; i<tcount; i++) { if ( ids ) id = *ids++; e =init(t,indices,vertices,e,id); indices+=3; t++; } { TriangleVector test; for (EdgeMap::Iterator i = mEdgeMap.getIterator(); !i.done(); ++i) { RtEdge *e = (*i).second; if ( e->mNextEdge == 0 ) // open edge! { Triangle *t = e->mTriangle; if ( !t->mPending ) { test.pushBack(t); t->mPending = true; } } } if ( !test.empty() ) { TriangleVector::Iterator i; for (i=test.begin(); i!=test.end(); ++i) { Triangle *t = (*i); locateIntersection(t); } } } while ( !mSplit.empty() ) { TriangleVector scan = mSplit; mSplit.clear(); TriangleVector::Iterator i; for (i=scan.begin(); i!=scan.end(); ++i) { Triangle *t = (*i); locateIntersection(t); } } mIndices.clear(); mIds.clear(); t = mInputTriangles; for (NxU32 i=0; i<mTcount; i++) { mIndices.pushBack(t->mI1); mIndices.pushBack(t->mI2); mIndices.pushBack(t->mI3); mIds.pushBack(t->mId); t++; } mEdgeMap.clear(); delete []mEdges; mEdges = 0; delete []mInputTriangles; mInputTriangles = 0; tcount_out = mIndices.size()/3; ret = tcount_out ? &mIndices[0] : 0; #ifdef _DEBUG if ( ret ) { const NxU32 *scan = ret; for (NxU32 i=0; i<tcount_out; i++) { NxU32 i1 = scan[0]; NxU32 i2 = scan[1]; NxU32 i3 = scan[2]; assert( i1 != i2 && i1 != i3 && i2 != i3 ); scan+=3; } } #endif return ret; }