Compare commits

...
Author SHA1 Message Date
Alec Jacobson b1d808e9bd fix doc 2023-08-23 12:54:59 -04:00
Alec Jacobson 0b0cdea5a6 boundaries 2023-08-23 12:54:52 -04:00
4 changed files with 84 additions and 6 deletions
+32 -4
View File
@@ -7,8 +7,9 @@
// obtain one at http://mozilla.org/MPL/2.0/.
#include "euler_characteristic.h"
#include "edge_topology.h"
#include "edges.h"
#include "unique_edge_map.h"
#include <cassert>
template <typename DerivedF>
IGL_INLINE int igl::euler_characteristic(
const Eigen::MatrixBase<DerivedF> & F)
@@ -16,9 +17,36 @@ IGL_INLINE int igl::euler_characteristic(
const int nf = F.rows();
const int nv = F.maxCoeff()+1;
Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> E;
edges(F,E);
Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,1> EMAP;
Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> uE;
unique_edge_map(F,E,uE,EMAP);
// The input is assumed manifold so boundary edges are those with exactly one
// incident face
Eigen::VectorXi count = Eigen::VectorXi::Zero(uE.rows(),1);
for(int e = 0;e<EMAP.size();e++)
{
count(EMAP(e))++;
}
std::vector<Eigen::Triplet<int> > IJV;
for(int u = 0;u<uE.rows();u++)
{
if(count(u) == 1)
{
IJV.emplace_back(uE(u,0),uE(u,1),1);
IJV.emplace_back(uE(u,1),uE(u,0),1);
}
assert(count(u) == 2);
}
Eigen::SparseMatrix<int> A(nv,nv);
A.setFromTriplets(IJV.begin(),IJV.end());
Eigen::VectorXi _C,_K;
// Number of boundary connected components
const int nb = connected_components(A,_C,_K);
std::cout<<"nb: "<<nb<<std::endl;
const int ne = E.rows();
return nv - ne + nf;
return nv - ne + nf + nb;
}
#ifdef IGL_STATIC_LIBRARY
+12 -1
View File
@@ -15,7 +15,18 @@
#include <vector>
namespace igl
{
/// Computes the Euler characteristic of a given mesh (V,F)
/// Computes the Euler characteristic of a given _manifold_ mesh (V,F) with
/// boundary.
///
/// V - E + F + B = (2-2g) = χ
///
/// With:
/// - V number of vertices (assumed to be F.maxCoeff()+1)
/// - E number of edges
/// - F number of faces
/// - B number of boundary components
/// - g genus
/// - χ Euler characteristic
///
/// @param[in] F #F by dim list of mesh faces (must be triangles)
/// @return An int containing the Euler characteristic
+1 -1
View File
@@ -75,7 +75,7 @@ namespace igl
///
/// \code{cpp}
/// // Using uEC,uEE
/// for(int u = 0;u<uE.size();u++)
/// for(int u = 0;u<uE.rows();u++)
/// {
/// for(int j = uEC(u);j<uEC(u+1);j++)
/// {
+39
View File
@@ -0,0 +1,39 @@
#include <test_common.h>
#include <igl/euler_characteristic.h>
TEST_CASE("euler_characteristic: cube", "[igl]" )
{
Eigen::MatrixXi F(12,3);
F <<
0,1,2,
0,2,3,
0,4,5,
0,5,1,
0,3,7,
0,7,4,
6,5,4,
6,4,7,
6,7,3,
6,3,2,
6,2,1,
6,1,5;
const int chi = igl::euler_characteristic(F);
REQUIRE(chi == 2);
}
TEST_CASE("euler_characteristic: square", "[igl]" )
{
Eigen::MatrixXi F;
igl::triangulated_grid(3,3,F);
const int chi = igl::euler_characteristic(F);
REQUIRE(chi == 1);
}
TEST_CASE("euler_characteristic: torus", "[igl]" )
{
Eigen::MatrixXd V;
Eigen::MatrixXi F;
igl::read_triangle_mesh(test_common::data_path("TinyTorus.obj"), V, F);
const int chi = igl::euler_characteristic(F);
REQUIRE(chi == 0);
}