void Mesh::Clip(const Plane & plane, SArray< Vec3<double> > & positivePart, SArray< Vec3<double> > & negativePart) const { const size_t nV = GetNPoints(); if (nV == 0) { return; } double d; for (size_t v = 0; v < nV; v++) { const Vec3<double> & pt = GetPoint(v); d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d; if (d > 0.0) { positivePart.PushBack(pt); } else if (d < 0.0) { negativePart.PushBack(pt); } else { positivePart.PushBack(pt); negativePart.PushBack(pt); } } }
ICHullError ICHull::Process() { unsigned int addedPoints = 0; if (m_mesh.GetNVertices() < 3) { return ICHullErrorNotEnoughPoints; } if (m_mesh.GetNVertices() == 3) { m_isFlat = true; CircularListElement<TMMTriangle>* t1 = m_mesh.AddTriangle(); CircularListElement<TMMTriangle>* t2 = m_mesh.AddTriangle(); CircularListElement<TMMVertex>* v0 = m_mesh.m_vertices.GetHead(); CircularListElement<TMMVertex>* v1 = v0->GetNext(); CircularListElement<TMMVertex>* v2 = v1->GetNext(); // Compute the normal to the plane Vec3<double> p0 = v0->GetData().m_pos; Vec3<double> p1 = v1->GetData().m_pos; Vec3<double> p2 = v2->GetData().m_pos; m_normal = (p1 - p0) ^ (p2 - p0); m_normal.Normalize(); t1->GetData().m_vertices[0] = v0; t1->GetData().m_vertices[1] = v1; t1->GetData().m_vertices[2] = v2; t2->GetData().m_vertices[0] = v1; t2->GetData().m_vertices[1] = v2; t2->GetData().m_vertices[2] = v2; return ICHullErrorOK; } if (m_isFlat) { m_mesh.m_edges.Clear(); m_mesh.m_triangles.Clear(); m_isFlat = false; } if (m_mesh.GetNTriangles() == 0) // we have to create the first polyhedron { ICHullError res = DoubleTriangle(); if (res != ICHullErrorOK) { return res; } else { addedPoints += 3; } } CircularList<TMMVertex>& vertices = m_mesh.GetVertices(); // go to the first added and not processed vertex while (!(vertices.GetHead()->GetPrev()->GetData().m_tag)) { vertices.Prev(); } while (!vertices.GetData().m_tag) // not processed { vertices.GetData().m_tag = true; if (ProcessPoint()) { addedPoints++; CleanUp(addedPoints); vertices.Next(); if (!GetMesh().CheckConsistancy()) { size_t nV = m_mesh.GetNVertices(); CircularList<TMMVertex>& vertices = m_mesh.GetVertices(); for (size_t v = 0; v < nV; ++v) { if (vertices.GetData().m_name == sc_dummyIndex) { vertices.Delete(); break; } vertices.Next(); } return ICHullErrorInconsistent; } } } if (m_isFlat) { SArray<CircularListElement<TMMTriangle>*> trianglesToDuplicate; size_t nT = m_mesh.GetNTriangles(); for (size_t f = 0; f < nT; f++) { TMMTriangle& currentTriangle = m_mesh.m_triangles.GetHead()->GetData(); if (currentTriangle.m_vertices[0]->GetData().m_name == sc_dummyIndex || currentTriangle.m_vertices[1]->GetData().m_name == sc_dummyIndex || currentTriangle.m_vertices[2]->GetData().m_name == sc_dummyIndex) { m_trianglesToDelete.PushBack(m_mesh.m_triangles.GetHead()); for (int k = 0; k < 3; k++) { for (int h = 0; h < 2; h++) { if (currentTriangle.m_edges[k]->GetData().m_triangles[h] == m_mesh.m_triangles.GetHead()) { currentTriangle.m_edges[k]->GetData().m_triangles[h] = 0; break; } } } } else { trianglesToDuplicate.PushBack(m_mesh.m_triangles.GetHead()); } m_mesh.m_triangles.Next(); } size_t nE = m_mesh.GetNEdges(); for (size_t e = 0; e < nE; e++) { TMMEdge& currentEdge = m_mesh.m_edges.GetHead()->GetData(); if (currentEdge.m_triangles[0] == 0 && currentEdge.m_triangles[1] == 0) { m_edgesToDelete.PushBack(m_mesh.m_edges.GetHead()); } m_mesh.m_edges.Next(); } size_t nV = m_mesh.GetNVertices(); CircularList<TMMVertex>& vertices = m_mesh.GetVertices(); for (size_t v = 0; v < nV; ++v) { if (vertices.GetData().m_name == sc_dummyIndex) { vertices.Delete(); } else { vertices.GetData().m_tag = false; vertices.Next(); } } CleanEdges(); CleanTriangles(); CircularListElement<TMMTriangle>* newTriangle; for (size_t t = 0; t < trianglesToDuplicate.Size(); t++) { newTriangle = m_mesh.AddTriangle(); newTriangle->GetData().m_vertices[0] = trianglesToDuplicate[t]->GetData().m_vertices[1]; newTriangle->GetData().m_vertices[1] = trianglesToDuplicate[t]->GetData().m_vertices[0]; newTriangle->GetData().m_vertices[2] = trianglesToDuplicate[t]->GetData().m_vertices[2]; } } return ICHullErrorOK; }
bool MeshDecimator::EdgeCollapse(double & qem) { MDEdgePriorityQueue currentEdge; long v1, v2; bool done = false; do { done = false; if (m_pqueue.size() == 0) { done = true; break; } else { currentEdge = m_pqueue.top(); m_pqueue.pop(); } } while ( (!m_edges[currentEdge.m_name].m_tag) || (m_edges[currentEdge.m_name].m_qem != currentEdge.m_qem)); if (done) return false; v1 = m_edges[currentEdge.m_name].m_v1; v2 = m_edges[currentEdge.m_name].m_v2; qem = currentEdge.m_qem; EdgeCollapse(v1, v2); m_points[v1] = m_edges[currentEdge.m_name].m_pos ; for(int k = 0; k < 10; k++) m_vertices[v1].m_Q[k] += m_vertices[v2].m_Q[k]; // Update priority queue long idEdge; long a, b; SArray<long, SARRAY_DEFAULT_MIN_SIZE> incidentVertices; for(size_t itE = 0; itE < m_vertices[v1].m_edges.Size(); ++itE) { idEdge = m_vertices[v1].m_edges[itE]; a = m_edges[idEdge].m_v1; b = m_edges[idEdge].m_v2; incidentVertices.PushBack((a != v1)?a:b); MDEdgePriorityQueue pqEdge; pqEdge.m_qem = m_edges[idEdge].m_qem = ComputeEdgeCost(a, b, m_edges[idEdge].m_pos); pqEdge.m_name = idEdge; m_pqueue.push(pqEdge); } long idVertex; for(size_t itV = 0; itV< incidentVertices.Size(); ++itV) { idVertex = incidentVertices[itV]; for(size_t itE = 0; itE < m_vertices[idVertex].m_edges.Size(); ++itE) { idEdge = m_vertices[idVertex].m_edges[itE]; a = m_edges[idEdge].m_v1; b = m_edges[idEdge].m_v2; if ( a!=v1 && b!=v1) { MDEdgePriorityQueue pqEdge; pqEdge.m_qem = m_edges[idEdge].m_qem = ComputeEdgeCost(a, b, m_edges[idEdge].m_pos); pqEdge.m_name = idEdge; m_pqueue.push(pqEdge); } } } return true; }
void MeshDecimator::EdgeCollapse(long v1, long v2) { long u, w; int shift; long idTriangle; for(size_t itT = 0; itT < m_vertices[v2].m_triangles.Size(); ++itT) { idTriangle = m_vertices[v2].m_triangles[itT]; if (m_triangles[idTriangle].X() == v2) { shift = 0; u = m_triangles[idTriangle].Y(); w = m_triangles[idTriangle].Z(); } else if (m_triangles[idTriangle].Y() == v2) { shift = 1; u = m_triangles[idTriangle].X(); w = m_triangles[idTriangle].Z(); } else { shift = 2; u = m_triangles[idTriangle].X(); w = m_triangles[idTriangle].Y(); } if ((u == v1) || (w == v1)) { m_trianglesTags[idTriangle] = false; m_vertices[u].m_triangles.Erase(idTriangle); m_vertices[w].m_triangles.Erase(idTriangle); m_nTriangles--; } else if (GetTriangle(v1, u, w) == -1) { m_vertices[v1].m_triangles.Insert(idTriangle); m_triangles[idTriangle][shift] = v1; } else { m_trianglesTags[idTriangle] = false; m_vertices[u].m_triangles.Erase(idTriangle); m_vertices[w].m_triangles.Erase(idTriangle); m_nTriangles--; } } long idEdge = 0; for(size_t itE = 0; itE < m_vertices[v2].m_edges.Size(); ++itE) { idEdge = m_vertices[v2].m_edges[itE]; w = (m_edges[idEdge].m_v1 == v2)? m_edges[idEdge].m_v2 : m_edges[idEdge].m_v1; if (w==v1) { m_edges[idEdge].m_tag = false; m_vertices[w].m_edges.Erase(idEdge); m_nEdges--; } else if ( GetEdge(v1, w) == -1) { if (m_edges[idEdge].m_v1 == v2) m_edges[idEdge].m_v1 = v1; else m_edges[idEdge].m_v2 = v1; m_vertices[v1].m_edges.Insert(idEdge); } else { m_edges[idEdge].m_tag = false; m_vertices[w].m_edges.Erase(idEdge); m_nEdges--; } } m_vertices[v2].m_tag = false; m_nVertices--; // update boundary edges SArray<long, 64> incidentVertices; incidentVertices.PushBack(v1); for(size_t itE = 0; itE < m_vertices[v1].m_edges.Size(); ++itE) { incidentVertices.PushBack((m_edges[idEdge].m_v1!= v1)?m_edges[idEdge].m_v1:m_edges[idEdge].m_v2); idEdge = m_vertices[v1].m_edges[itE]; m_edges[idEdge].m_onBoundary = (IsBoundaryEdge(m_edges[idEdge].m_v1, m_edges[idEdge].m_v2) != -1); } // update boundary vertices long idVertex; for(size_t itV = 0; itV < incidentVertices.Size(); ++itV) { idVertex = incidentVertices[itV]; m_vertices[idVertex].m_onBoundary = false; for(size_t itE = 0; itE < m_vertices[idVertex].m_edges.Size(); ++itE) { idEdge = m_vertices[idVertex].m_edges[itE]; if (m_edges[idEdge].m_onBoundary) { m_vertices[idVertex].m_onBoundary = true; break; } } } }