Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1d808e9bd | ||
|
|
0b0cdea5a6 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++)
|
||||
/// {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user