// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2015 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_COLLAPSE_EDGE_H #define IGL_COLLAPSE_EDGE_H #include "igl_inline.h" #include "COLLAPSE_EDGE_NULL.h" #include #include namespace igl { /// Attempt to collapse a given edge of a mesh. Assumes (V,F) is a closed /// manifold mesh (except for previously collapsed faces which should be set /// to: [IGL_COLLAPSE_EDGE_NULL IGL_COLLAPSE_EDGE_NULL /// IGL_COLLAPSE_EDGE_NULL]. Collapses exactly two faces and exactly 3 edges /// from E (e and one side of each face gets collapsed to the other). This is /// implemented in a way that it can be repeatedly called until satisfaction /// and then the garbage in F can be collected by removing NULL faces. /// /// @param[in] e index into E of edge to try to collapse. E(e,:) = [s d] or [d s] so /// that sj) is the edge of /// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) " /// e=(j->i) /// @param[in,out] EI #E by 2 list of edge flap corners (see above). /// [mesh inputs] /// @param[out] e1 index into E of edge collpased on left /// @param[out] e2 index into E of edge collpased on right /// @param[out] f1 index into F of face collpased on left /// @param[out] f2 index into F of face collpased on right /// @return true if edge was collapsed /// /// /// Define [s,d] = sort(E(e,:)) so that sd) then e1 will be the edge after e within f1: /// /// s>d /// ✅s----e-----d☠️ /// \ ← / /// \ ↘f₁↗ / /// \ e₁ /// \ / /// \/ /// /// /// ¹Or at least it would if we templated these functions to allow using /// RowMajor V. /// /// It really seems that this callback should provide a meaningful edge on the /// _new_ mesh. Meanwhile – Oof – You can use this gross mechanism to find the faces incident on the /// collapsed vertex: /// /// ```cpp /// const auto survivors = /// [&F,&e,&EMAP](const int f1, const int e1, int & d1) /// { /// for(int c=0;c<3;c++) /// { /// d1 = EMAP(f1+c*F.rows()); /// if((d1 != e) && (d1 != e1)) { break; } /// } /// }; /// int d1,d2; /// survivors(f1,e1,d1); /// survivors(f2,e2,d2); /// // Will circulating by continuing in the CCW direction of E(d1,:) /// // encircle the common edge? That is, is E(d1,1) the common vertex? /// const bool ccw = E(d1,1) == E(d2,0) || E(d1,1) == E(d2,1); /// std::vector Nf; /// { /// std::vector Nv; /// igl::circulation(d1,ccw,F,EMAP,EF,EI,Nv,Nf); /// } /// ``` template < typename Derivedp, typename DerivedV, typename DerivedF, typename DerivedE, typename DerivedEMAP, typename DerivedEF, typename DerivedEI> IGL_INLINE bool collapse_edge( const int e, const Eigen::MatrixBase & p, Eigen::MatrixBase & V, Eigen::MatrixBase & F, Eigen::MatrixBase & E, Eigen::MatrixBase & EMAP, Eigen::MatrixBase & EF, Eigen::MatrixBase & EI, int & e1, int & e2, int & f1, int & f2); /// \overload /// /// @param[in] Nsv #Nsv vertex circulation around s (see circulation) /// @param[in] Nsf #Nsf face circulation around s /// @param[in] Ndv #Ndv vertex circulation around d /// @param[in] Ndf #Ndf face circulation around d template < typename Derivedp, typename DerivedV, typename DerivedF, typename DerivedE, typename DerivedEMAP, typename DerivedEF, typename DerivedEI> IGL_INLINE bool collapse_edge( const int e, const Eigen::MatrixBase & p, /*const*/ std::vector & Nsv, const std::vector & Nsf, /*const*/ std::vector & Ndv, const std::vector & Ndf, Eigen::MatrixBase & V, Eigen::MatrixBase & F, Eigen::MatrixBase & E, Eigen::MatrixBase & EMAP, Eigen::MatrixBase & EF, Eigen::MatrixBase & EI, int & a_e1, int & a_e2, int & a_f1, int & a_f2); } #ifndef IGL_STATIC_LIBRARY # include "collapse_edge.cpp" #endif #endif