// 3 - 2 3 - 2 // | / | or | \ | // 0 - 1 0 - 1 FaceIndexPair addFace (const VertexIndex& idx_v_0, const VertexIndex& idx_v_1, const VertexIndex& idx_v_2, const VertexIndex& idx_v_3, const FaceData& face_data = FaceData ()) { // Try to add two faces // 3 - 2 // | / | // 0 - 1 FaceIndex idx_face_0 = this->addFace (idx_v_0, idx_v_1, idx_v_2, face_data); FaceIndex idx_face_1 = this->addFace (idx_v_0, idx_v_2, idx_v_3, face_data); if (idx_face_0.isValid ()) { return (std::make_pair (idx_face_0, idx_face_1)); } else if (idx_face_1.isValid ()) { idx_face_0 = this->addFace (idx_v_0, idx_v_1, idx_v_2, face_data); // might be possible to add now return (std::make_pair (idx_face_1, idx_face_0)); } // Try to add two faces // 3 - 2 // | \ | // 0 - 1 idx_face_0 = this->addFace (idx_v_1, idx_v_2, idx_v_3, face_data); idx_face_1 = this->addFace (idx_v_0, idx_v_1, idx_v_3, face_data); if (idx_face_0.isValid ()) { return (std::make_pair (idx_face_0, idx_face_1)); } else if (idx_face_1.isValid ()) { idx_face_0 = this->addFace (idx_v_1, idx_v_2, idx_v_3, face_data); // might be possible to add now return (std::make_pair (idx_face_1, idx_face_0)); } // Connect the triangle pair if possible if (!idx_v_0.isValid () || !idx_v_1.isValid () || !idx_v_2.isValid () || !idx_v_3.isValid ()) { return (std::make_pair (FaceIndex (), FaceIndex ())); } VertexIndexes vi; vi.reserve (4); vi.push_back (idx_v_0); vi.push_back (idx_v_1); vi.push_back (idx_v_2); vi.push_back (idx_v_3); if (!this->uniqueCheck (vi)) { return (std::make_pair (FaceIndex (), FaceIndex ())); } HalfEdgeIndex idx_he_01, idx_he_12, idx_he_23, idx_he_30; // Check manifoldness bool is_new_01 = true; bool is_new_12 = true; bool is_new_23 = true; bool is_new_30 = true; if (!Base::checkTopology1 (idx_v_0,idx_v_1, idx_he_01, is_new_01) || !Base::checkTopology1 (idx_v_1,idx_v_2, idx_he_12, is_new_12) || !Base::checkTopology1 (idx_v_2,idx_v_3, idx_he_23, is_new_23) || !Base::checkTopology1 (idx_v_3,idx_v_0, idx_he_30, is_new_30)) { return (std::make_pair (FaceIndex (), FaceIndex ())); } // Connect the triangle pair if (!is_new_01 && is_new_12 && !is_new_23 && is_new_30) { return (this->connectTrianglePair (idx_he_01, idx_he_23, idx_v_0, idx_v_1, idx_v_2, idx_v_3, face_data)); } else if (is_new_01 && !is_new_12 && is_new_23 && !is_new_30) { return (this->connectTrianglePair (idx_he_12, idx_he_30, idx_v_1, idx_v_2, idx_v_3, idx_v_0, face_data)); } else { assert (true); // This should not happen! return (std::make_pair (FaceIndex (), FaceIndex ())); } }
FaceIndex addFace (const VertexIndex& idx_v_0, const VertexIndex& idx_v_1, const VertexIndex& idx_v_2, const FaceData& face_data = FaceData ()) { if (!idx_v_0.isValid () || !idx_v_1.isValid () || !idx_v_2.isValid ()) { return (FaceIndex ()); } VertexIndexes vi; vi.reserve (3); vi.push_back (idx_v_0); vi.push_back (idx_v_1); vi.push_back (idx_v_2); if (!this->uniqueCheck (vi)) { return (FaceIndex ()); } HalfEdgeIndex idx_he_01, idx_he_12, idx_he_20; HalfEdgeIndex idx_he_10, idx_he_21, idx_he_02; if (Base::getElement (idx_v_0).isIsolated () && Base::getElement (idx_v_1).isIsolated () && Base::getElement (idx_v_2).isIsolated ()) { Base::addHalfEdgePair (idx_v_0,idx_v_1, HalfEdgeData (),HalfEdgeData (), idx_he_01,idx_he_10); Base::addHalfEdgePair (idx_v_1,idx_v_2, HalfEdgeData (),HalfEdgeData (), idx_he_12,idx_he_21); Base::addHalfEdgePair (idx_v_2,idx_v_0, HalfEdgeData (),HalfEdgeData (), idx_he_20,idx_he_02); Base::connectHalfEdges (true,true, idx_he_01,idx_he_10, idx_he_12,idx_he_21, idx_v_1); Base::connectHalfEdges (true,true, idx_he_12,idx_he_21, idx_he_20,idx_he_02, idx_v_2); Base::connectHalfEdges (true,true, idx_he_20,idx_he_02, idx_he_01,idx_he_10, idx_v_0); return (this->connectFace (face_data, idx_he_01,idx_he_12,idx_he_20)); } // Check for topological errors bool is_new_01 = true; bool is_new_12 = true; bool is_new_20 = true; if (!Base::checkTopology1 (idx_v_0,idx_v_1, idx_he_01, is_new_01) || !Base::checkTopology1 (idx_v_1,idx_v_2, idx_he_12, is_new_12) || !Base::checkTopology1 (idx_v_2,idx_v_0, idx_he_20, is_new_20)) { return (FaceIndex ()); } if (!Base::checkTopology2 (is_new_01,is_new_12, Base::getElement (idx_v_1).isIsolated ()) || !Base::checkTopology2 (is_new_12,is_new_20, Base::getElement (idx_v_2).isIsolated ()) || !Base::checkTopology2 (is_new_20,is_new_01, Base::getElement (idx_v_0).isIsolated ())) { return (FaceIndex ()); } // Reconnect the existing half-edges if needed bool make_adjacent_01_12 = false; bool make_adjacent_12_20 = false; bool make_adjacent_20_01 = false; HalfEdgeIndex idx_he_boundary_01_12; HalfEdgeIndex idx_he_boundary_12_20; HalfEdgeIndex idx_he_boundary_20_01; if (!Base::checkAdjacency (idx_he_01,idx_he_12, is_new_01,is_new_12, make_adjacent_01_12, idx_he_boundary_01_12) || !Base::checkAdjacency (idx_he_12,idx_he_20, is_new_12,is_new_20, make_adjacent_12_20, idx_he_boundary_12_20) || !Base::checkAdjacency (idx_he_20,idx_he_01, is_new_20,is_new_01, make_adjacent_20_01, idx_he_boundary_20_01)) { return (FaceIndex ()); } Base::makeAdjacent (idx_he_01,idx_he_12, make_adjacent_01_12, idx_he_boundary_01_12); Base::makeAdjacent (idx_he_12,idx_he_20, make_adjacent_12_20, idx_he_boundary_12_20); Base::makeAdjacent (idx_he_20,idx_he_01, make_adjacent_20_01, idx_he_boundary_20_01); // Add the new half-edges if needed if (is_new_01) Base::addHalfEdgePair (idx_v_0,idx_v_1, HalfEdgeData (),HalfEdgeData (), idx_he_01,idx_he_10); else idx_he_10 = Base::getElement (idx_he_01).getOppositeHalfEdgeIndex (); if (is_new_12) Base::addHalfEdgePair (idx_v_1,idx_v_2, HalfEdgeData (),HalfEdgeData (), idx_he_12,idx_he_21); else idx_he_21 = Base::getElement (idx_he_12).getOppositeHalfEdgeIndex (); if (is_new_20) Base::addHalfEdgePair (idx_v_2,idx_v_0, HalfEdgeData (),HalfEdgeData (), idx_he_20,idx_he_02); else idx_he_02 = Base::getElement (idx_he_20).getOppositeHalfEdgeIndex (); // Connect the half-edges and vertexes Base::connectHalfEdges (is_new_01,is_new_12, idx_he_01,idx_he_10, idx_he_12,idx_he_21, idx_v_1); Base::connectHalfEdges (is_new_12,is_new_20, idx_he_12,idx_he_21, idx_he_20,idx_he_02, idx_v_2); Base::connectHalfEdges (is_new_20,is_new_01, idx_he_20,idx_he_02, idx_he_01,idx_he_10, idx_v_0); // Connect the face return (this->connectFace (face_data, idx_he_01,idx_he_12,idx_he_20)); }