You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
6.1 KiB

// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2019 Hanxiao Shen <hanxiao@cims.nyu.edu>
//
// 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/.
#include "cut_mesh.h"
#include "triangle_triangle_adjacency.h"
#include "HalfEdgeIterator.h"
#include "is_border_vertex.h"
// wrapper for input/output style
template <typename DerivedV, typename DerivedF, typename DerivedC>
IGL_INLINE void igl::cut_mesh(
const Eigen::MatrixBase<DerivedV>& V,
const Eigen::MatrixBase<DerivedF>& F,
const Eigen::MatrixBase<DerivedC>& C,
Eigen::PlainObjectBase<DerivedV>& Vn,
Eigen::PlainObjectBase<DerivedF>& Fn
){
Vn = V;
Fn = F;
typedef typename DerivedF::Scalar Index;
Eigen::Matrix<Index,Eigen::Dynamic,1> _I;
cut_mesh(Vn,Fn,C,_I);
}
template <typename DerivedV, typename DerivedF, typename DerivedC, typename DerivedI>
IGL_INLINE void igl::cut_mesh(
const Eigen::MatrixBase<DerivedV>& V,
const Eigen::MatrixBase<DerivedF>& F,
const Eigen::MatrixBase<DerivedC>& C,
Eigen::PlainObjectBase<DerivedV>& Vn,
Eigen::PlainObjectBase<DerivedF>& Fn,
Eigen::PlainObjectBase<DerivedI>& I
){
Vn = V;
Fn = F;
cut_mesh(Vn,Fn,C,I);
}
template <typename DerivedV, typename DerivedF, typename DerivedC, typename DerivedI>
IGL_INLINE void igl::cut_mesh(
Eigen::PlainObjectBase<DerivedV>& V,
Eigen::PlainObjectBase<DerivedF>& F,
const Eigen::MatrixBase<DerivedC>& C,
Eigen::PlainObjectBase<DerivedI>& I
){
DerivedF FF, FFi;
igl::triangle_triangle_adjacency(F,FF,FFi);
igl::cut_mesh(V,F,FF,FFi,C,I);
}
template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedFFi, typename DerivedC, typename DerivedI>
IGL_INLINE void igl::cut_mesh(
Eigen::PlainObjectBase<DerivedV>& V,
Eigen::PlainObjectBase<DerivedF>& F,
Eigen::MatrixBase<DerivedFF>& FF,
Eigen::MatrixBase<DerivedFFi>& FFi,
const Eigen::MatrixBase<DerivedC>& C,
Eigen::PlainObjectBase<DerivedI>& I
){
typedef typename DerivedF::Scalar Index;
// store current number of occurance of each vertex as the alg proceed
Eigen::Matrix<Index,Eigen::Dynamic,1> occurence(V.rows());
occurence.setConstant(1);
// set eventual number of occurance of each vertex expected
Eigen::Matrix<Index,Eigen::Dynamic,1> eventual(V.rows());
eventual.setZero();
for(Index i=0;i<F.rows();i++){
for(Index k=0;k<3;k++){
Index u = F(i,k);
Index v = F(i,(k+1)%3);
if(FF(i,k) == -1){
// add one extra occurance for boundary vertices
eventual(u) += 1;
}else if(
(u < v) &&
(C(i,k) || C(FF(i,k),FFi(i,k))) )
{
// only compute every (undirected) edge ones
eventual(u) += 1;
eventual(v) += 1;
}
}
}
// original number of vertices
Index n_v = V.rows();
// estimate number of new vertices and resize V
Index n_new = 0;
for(Index i=0;i<eventual.rows();i++)
n_new += ((eventual(i) > 0) ? eventual(i)-1 : 0);
V.conservativeResize(n_v+n_new,Eigen::NoChange);
I = DerivedI::LinSpaced(V.rows(),0,V.rows());
// pointing to the current bottom of V
Index pos = n_v;
for(Index f=0;f<C.rows();f++){
for(Index k=0;k<3;k++){
Index v0 = F(f,k);
if(F(f,k) >= n_v) continue; // ignore new vertices
if(C(f,k) == 1 && occurence(v0) != eventual(v0)){
igl::HalfEdgeIterator<DerivedF,DerivedF,DerivedF> he(F,FF,FFi,f,k);
// rotate clock-wise around v0 until hit another cut
std::vector<Index> fan;
Index fi = he.Fi();
Index ei = he.Ei();
do{
fan.push_back(fi);
he.flipE();
he.flipF();
fi = he.Fi();
ei = he.Ei();
}while(C(fi,ei) == 0 && !he.isBorder());
// make a copy
V.row(pos) << V.row(v0);
I(pos) = v0;
// add one occurance to v0
occurence(v0) += 1;
// replace old v0
for(Index f0: fan)
for(Index j=0;j<3;j++)
if(F(f0,j) == v0)
F(f0,j) = pos;
// mark cuts as boundary
FF(f,k) = -1;
FF(fi,ei) = -1;
pos++;
}
}
}
}
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
template void igl::cut_mesh<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
template void igl::cut_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
template void igl::cut_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
template void igl::cut_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
#endif