45#include "HoleFillerT.hh"
55template<
class MeshT >
56HoleFillerT< MeshT >::HoleFillerT(MeshT &_mesh )
59 mesh_.request_vertex_status();
60 mesh_.request_edge_status();
62 if (! mesh_.get_property_handle(scale_,
"scale") )
63 mesh_.add_property( scale_ ,
"scale" );
71template<
class MeshT >
72HoleFillerT< MeshT >::~HoleFillerT()
74 mesh_.release_vertex_status();
75 mesh_.release_edge_status();
77 if ( mesh_.get_property_handle(scale_,
"scale") )
78 mesh_.remove_property( scale_ );
89template<
class MeshT >
96 std::vector< typename MeshT::EdgeHandle > bdry_edge;
98 for (
auto ei : mesh_.edges())
99 if ( ei.is_boundary() )
100 bdry_edge.push_back( ei );
105 for (
auto i : bdry_edge)
106 if ( mesh_.is_boundary( i ) )
109 omlog() <<
"Filling hole " << cnt <<
"\n";
110 fill_hole( i, _stages );
117 omlog() <<
"Stage 3 : Smoothing the hole fillings ... ";
121 Tangential_and_Normal,
135template<
class MeshT >
140 omlog() <<
" Stage 1 : Computing a minimal triangulation ... ";
143 typename MeshT::VertexHandle old_last_handle = *(--mesh_.vertices_end());
146 if ( ! mesh_.is_boundary( _eh ) ) {
147 omerr() <<
"fill_hole: Given edge handle is not a boundary edge at a hole!" << std::endl;
158 boundary_vertex_.clear();
159 opposite_vertex_.clear();
164 boundary_vertex_.push_back( ch.
from() );
165 opposite_vertex_.push_back( ch.
opp().
next().
to() );
171 if ( voh_it.is_boundary() )
176 typename MeshT::VertexOHalfedgeIter voh_it(mesh_,op);
182 }
while ( ch != hh );
185 int nv = boundary_vertex_.size();
189 w_.resize( nv, std::vector<Weight>( nv, Weight() ) );
192 l_.resize( nv, std::vector<int>( nv, 0 ) );
195 for (
int i = 0; i < nv - 1; ++i )
196 w_[i][i+1] = Weight( 0, 0 );
198 for (
int j = 2; j < nv; ++j )
200 #pragma omp parallel for shared(j, nv)
201 for(
int i = 0; i < nv-j; ++i)
205 for (
int m = i + 1; m < i + j; ++m )
207 Weight newval = w_[i][m] + w_[m][i+j] + weight( i, m, i+j );
208 if ( newval < valmin )
223 hole_triangle_.clear();
224 if ( fill( 0, nv - 1 ) ){
229 omlog() <<
" Stage 2 : Fairing the filling ... " << std::endl;
231 std::vector< OpenMesh::SmartFaceHandle > handles = hole_triangle_;
236 typename MeshT::VertexIter old_end = ++
typename MeshT::VertexIter(mesh_,old_last_handle);
237 typename MeshT::VertexIter v_end = mesh_.vertices_end();
239 for(; old_end != v_end; ++old_end)
240 if ( !mesh_.status(*old_end).deleted() )
241 mesh_.status(*old_end).set_selected(
true );
244 omerr() <<
"Could not create triangulation" << std::endl;
249template<
class MeshT >
256 hole_triangle_ = _faceHandles;
263 if (! mesh_.get_property_handle(edgeProp,
"edgeProp") )
264 mesh_.add_property( edgeProp,
"edgeProp" );
265 if (! mesh_.get_property_handle(vertexProp,
"vertexProp") )
266 mesh_.add_property( vertexProp,
"vertexProp" );
267 if (! mesh_.get_property_handle(faceProp,
"faceProp") )
268 mesh_.add_property( faceProp,
"faceProp" );
269 if (! mesh_.get_property_handle(orderProp,
"orderProp") )
270 mesh_.add_property( orderProp,
"orderProp" );
273 for (
auto fIt : mesh_.faces()) {
274 mesh_.property( orderProp, fIt ) =
false;
275 mesh_.property( faceProp, fIt ) =
false;
278 for (
auto eIt : mesh_.edges())
279 mesh_.property( edgeProp, eIt ) =
false;
281 for (
auto vIt : mesh_.vertices()) {
282 mesh_.property( vertexProp, vIt ) =
false;
286 for (uint i = 0; i < hole_triangle_.size(); i++){
287 mesh_.property( faceProp, hole_triangle_[i] ) =
true;
291 for (
unsigned int i = 0; i < hole_triangle_.size(); i++){
292 for (
auto fei : hole_triangle_[i].edges()) {
293 mesh_.status( fei ).set_locked(
true);
295 if (mesh_.property( faceProp, fei.h0().face() ) &&
296 mesh_.property( faceProp, fei.h1().face() ) ){
298 mesh_.property( edgeProp, fei ) =
true;
299 hole_edge_.push_back( fei );
300 mesh_.status( fei ).set_locked(
false);
305 for (
auto fvi : hole_triangle_[i].vertices()){
307 for (
auto vfi : fvi.faces() )
308 mesh_.property( vertexProp, fvi ) =
true;
313 for (
auto vIt : mesh_.vertices())
314 if (mesh_.property(vertexProp, vIt)){
319 for (
auto voh_it : vIt.outgoing_halfedges())
322 if (voh_it.face().is_valid() &&
323 voh_it.opp().face().is_valid() &&
324 mesh_.property(faceProp, voh_it.face() ) &&
325 mesh_.property(faceProp, voh_it.opp().face() ))
329 Point p0 = mesh_.point( vIt );
330 Point p1 = mesh_.point( voh_it.to() );
331 scale +=
norm( p1 - p0 );
337 mesh_.property( scale_, vIt ) = scale;
340 mesh_.remove_property(edgeProp);
341 mesh_.remove_property(vertexProp);
342 mesh_.remove_property(faceProp);
343 mesh_.remove_property(orderProp);
346 bool did_refine =
true;
348 for (
int k = 0; k < 40 && did_refine; ++k )
350 uint end = hole_triangle_.size();
353 for (
unsigned int j = 0; j < end; ++j )
354 did_refine |= refine( hole_triangle_[j] );
356 for (
int i = 0; i < 10; ++i )
357 for (
unsigned int j = 0; j < hole_edge_.size(); ++j )
358 relax_edge( hole_edge_[j] );
362 for (
auto ei : mesh_.edges())
363 mesh_.status( ei ).set_locked(
false );
375template<
class MeshT >
377HoleFillerT< MeshT >::refine(
typename MeshT::FaceHandle _fh )
382 typename MeshT::FEIter fei = mesh_.fe_iter( _fh );
390 typename MeshT::FVIter fvi = mesh_.fv_iter( _fh );
392 typename MeshT::VertexHandle v0 = *fvi; ++fvi;
393 typename MeshT::VertexHandle v1 = *fvi; ++fvi;
394 typename MeshT::VertexHandle v2 = *fvi; ++fvi;
396 Point p0 = mesh_.point( v0 );
397 Point p1 = mesh_.point( v1 );
398 Point p2 = mesh_.point( v2 );
400 Scalar scale0 = mesh_.property( scale_, v0 );
401 Scalar scale1 = mesh_.property( scale_, v1 );
402 Scalar scale2 = mesh_.property( scale_, v2 );
406 Scalar scale = ( scale0 + scale1 + scale2 ) / 3.0f;
407 Point center =
typename MeshT::Scalar(1.0/3.0) * ( p0 + p1 + p2 );
409 Scalar d0 = 1.0f *
norm( p0 - center );
410 Scalar d1 = 1.0f *
norm( p1 - center );
411 Scalar d2 = 1.0f *
norm( p2 - center );
415 if ( (d0 + d1 + d2) / 3.0f < scale)
return false;
421 if ( ( d0 > scale && d0 > scale0 ) ||
422 ( d1 > scale && d1 > scale1 ) ||
423 ( d2 > scale && d2 > scale2 ) )
427 mesh_.split( _fh, ch );
431 for (
auto vfi : ch.
faces() )
433 hole_triangle_.push_back( vfi );
437 for (
auto vei : ch.
edges() )
438 hole_edge_.push_back( vei );
442 mesh_.property( scale_, ch ) = scale;
463template<
class MeshT >
467 if ( mesh_.status( _eh ).locked() )
477 Point u( mesh_.point( h0.
to() ) );
478 Point v( mesh_.point( h1.
to() ) );
482 Point a( mesh_.point( h0.
next().
to() ) );
483 Point b( mesh_.point( h1.
next().
to() ) );
488 if ( in_circumsphere( a, u, v, b ) || in_circumsphere( b, u, v, a ) ){
489 if ( mesh_.is_flip_ok( _eh ) )
496 mesh_.status(_eh).set_selected(
true );
509template<
class MeshT >
511HoleFillerT< MeshT >::in_circumsphere(
const Point & _x,
514 const Point & _c )
const
519 Scalar a00 = -2.0f * (
dot(ab , _a ) );
520 Scalar a01 = -2.0f * (
dot(ab , _b ) );
521 Scalar a02 = -2.0f * (
dot(ab , _c ) );
524 Scalar a10 = -2.0f * (
dot(ac , _a ) );
525 Scalar a11 = -2.0f * (
dot(ac , _b ) );
526 Scalar a12 = -2.0f * (
dot(ac , _c ) );
529 typename MeshT::Scalar alpha = -(-a11*a02+a01*a12-a12*b0+b1*a02+a11*b0-a01*b1)
530 / (-a11*a00+a11*a02-a10*a02+a00*a12+a01*a10-a01*a12);
531 typename MeshT::Scalar beta = (a10*b0-a10*a02-a12*b0+a00*a12+b1*a02-a00*b1)
532 / (-a11*a00+a11*a02-a10*a02+a00*a12+a01*a10-a01*a12);
533 typename MeshT::Scalar gamma = (-a11*a00-a10*b0+a00*b1+a11*b0+a01*a10-a01*b1)
534 / (-a11*a00+a11*a02-a10*a02+a00*a12+a01*a10-a01*a12);
536 Point center = alpha * _a + beta * _b + gamma * _c;
538 return norm( _x - center ) *
norm( _x - center ) <
norm( _a - center ) *
norm( _a - center );
551template<
class MeshT >
553HoleFillerT< MeshT >::fill(
int _i,
int _j )
564 boundary_vertex_[ l_[_i][_j] ],
565 boundary_vertex_[_j] );
566 hole_triangle_.push_back( fh );
571 hole_edge_.push_back( mesh_.edge_handle
572 ( mesh_.find_halfedge( boundary_vertex_[_i],
573 boundary_vertex_[ l_[_i][_j] ] ) ) );
574 hole_edge_.push_back( mesh_.edge_handle
575 ( mesh_.find_halfedge( boundary_vertex_[ l_[_i][_j] ],
576 boundary_vertex_[_j] ) ) );
582 if (!fill( _i, l_[_i][_j] ) || !fill( l_[_i][_j], _j ))
597template<
class MeshT >
598typename HoleFillerT< MeshT >::Weight
599HoleFillerT< MeshT >::weight(
int _i,
int _j,
int _k )
604 if ( exists_edge( boundary_vertex_[_i], boundary_vertex_[_j] ) ||
605 exists_edge( boundary_vertex_[_j], boundary_vertex_[_k] ) ||
606 exists_edge( boundary_vertex_[_k], boundary_vertex_[_i] ) )
614 if ( l_[_i][_j] == -1 )
return Weight();
615 if ( l_[_j][_k] == -1 )
return Weight();
624 angle = std::max( angle, dihedral_angle( boundary_vertex_[_i],
625 boundary_vertex_[_j],
626 boundary_vertex_[_k],
627 opposite_vertex_[_i] ) );
629 angle = std::max( angle, dihedral_angle( boundary_vertex_[_i],
630 boundary_vertex_[_j],
631 boundary_vertex_[_k],
632 boundary_vertex_[l_[_i][_j]] ) );
635 angle = std::max( angle, dihedral_angle( boundary_vertex_[_j],
636 boundary_vertex_[_k],
637 boundary_vertex_[_i],
638 opposite_vertex_[_j] ) );
640 angle = std::max( angle, dihedral_angle( boundary_vertex_[_j],
641 boundary_vertex_[_k],
642 boundary_vertex_[_i],
643 boundary_vertex_[l_[_j][_k]] ) );
645 if ( _i == 0 && _k == (
int) boundary_vertex_.size() - 1 )
646 angle = std::max( angle, dihedral_angle( boundary_vertex_[_k],
647 boundary_vertex_[_i],
648 boundary_vertex_[_j],
649 opposite_vertex_[_k] ) );
652 return Weight( angle, area( boundary_vertex_[_i],
653 boundary_vertex_[_j],
654 boundary_vertex_[_k] ) );
666template<
class MeshT >
671 if ( ! vohi.edge().is_boundary() )
672 if ( vohi.to() == _w )
687template<
class MeshT >
688typename MeshT::Scalar
689HoleFillerT< MeshT >::area(
typename MeshT::VertexHandle _a,
typename MeshT::VertexHandle _b,
typename MeshT::VertexHandle _c )
691 Point a( mesh_.point( _a ) );
692 Point b( mesh_.point( _b ) );
693 Point c( mesh_.point( _c ) );
695 Point n(
cross(( b - a ) , ( c - b )) );
697 return 0.5 *
norm(n);
712template<
class MeshT >
713typename MeshT::Scalar
714HoleFillerT< MeshT >::dihedral_angle(
typename MeshT::VertexHandle _u,
typename MeshT::VertexHandle _v,
typename MeshT::VertexHandle _a,
typename MeshT::VertexHandle _b )
716 Point u( mesh_.point( _u ) );
717 Point v( mesh_.point( _v ) );
718 Point a( mesh_.point( _a ) );
719 Point b( mesh_.point( _b ) );
721 Point n0(
cross(( v - u ) , ( a - v )) );
722 Point n1(
cross(( u - v ) , ( b - u )) );
727 return acos(
dot(n0,n1) ) * 180.0 / M_PI;
732template<
class MeshT >
734HoleFillerT< MeshT >::removeDegeneratedFaces( std::vector< typename MeshT::FaceHandle >& _faceHandles ){
736 for (
int i = _faceHandles.size()-1; i >= 0 ; i--){
738 if ( mesh_.status( _faceHandles[i] ).deleted() ){
741 _faceHandles.erase( _faceHandles.begin() + i );
746 typename MeshT::FaceVertexIterator fvi = mesh_.fv_iter( _faceHandles[i] );
747 Point v0 = mesh_.point( *fvi);
749 Point v1 = mesh_.point( *fvi );
751 Point v2 = mesh_.point( *fvi );
754 Point v0v1 = v1 - v0;
755 Point v0v2 = v2 - v0;
756 Point n = v0v1 % v0v2;
757 double d = n.sqrnorm();
759 if (d < FLT_MIN && d > -FLT_MIN) {
761 typename MeshT::FaceHalfedgeIterator hIt = mesh_.fh_iter( _faceHandles[i] );
764 while (hIt.is_valid()){
765 if ( mesh_.is_collapse_ok( *hIt ) ){
767 mesh_.collapse( *hIt );
769 _faceHandles.erase( _faceHandles.begin() + i );
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
SmartVertexHandle make_smart(VertexHandle _vh, const PolyConnectivity *_mesh)
Creats a SmartVertexHandle from a VertexHandle and a Mesh.
Definition: SmartHandles.hh:265
T angle(T _cos_angle, T _sin_angle)
returns the angle determined by its cos and the sign of its sin result is positive if the angle is in...
Definition: MathDefs.hh:140
VectorT< Scalar, DIM > & normalize(VectorT< Scalar, DIM > &_v)
non-member normalize
Definition: Vector11T.hh:769
Scalar dot(const VectorT< Scalar, DIM > &_v1, const VectorT< Scalar, DIM > &_v2)
symmetric version of the dot product
Definition: Vector11T.hh:725
auto cross(const VectorT< LScalar, DIM > &_v1, const VectorT< RScalar, DIM > &_v2) -> decltype(_v1 % _v2)
symmetric version of the cross product
Definition: Vector11T.hh:733
Scalar norm(const VectorT< Scalar, DIM > &_v)
non-member norm
Definition: Vector11T.hh:749
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
bool is_boundary() const
Returns true iff the handle is boundary.
Definition: SmartHandles.hh:350
Smart version of VertexHandle contains a pointer to the corresponding mesh and allows easier access t...
Definition: SmartHandles.hh:110
PolyConnectivity::ConstVertexFaceRange faces() const
Returns a range of faces incident to the vertex (PolyConnectivity::vf_range())
Definition: PolyConnectivity_inline_impl.hh:972
PolyConnectivity::ConstVertexOHalfedgeRange outgoing_halfedges() const
Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_range())
Definition: PolyConnectivity_inline_impl.hh:992
PolyConnectivity::ConstVertexEdgeRange edges() const
Returns a range of edges incident to the vertex (PolyConnectivity::ve_range())
Definition: PolyConnectivity_inline_impl.hh:976
Definition: SmartHandles.hh:170
SmartVertexHandle from() const
Returns vertex at start of halfedge.
Definition: SmartHandles.hh:409
SmartHalfedgeHandle next() const
Returns next halfedge handle.
Definition: SmartHandles.hh:385
SmartHalfedgeHandle opp() const
Returns opposite halfedge handle.
Definition: SmartHandles.hh:397
SmartVertexHandle to() const
Returns vertex pointed to by halfedge.
Definition: SmartHandles.hh:403
Definition: SmartHandles.hh:197
SmartHalfedgeHandle h1() const
Shorthand for halfedge(1)
Definition: SmartHandles.hh:443
SmartHalfedgeHandle h0() const
Shorthand for halfedge(0)
Definition: SmartHandles.hh:438
Definition: SmartHandles.hh:228
Handle representing an edge property.
Definition: Property.hh:447
Definition: HoleFillerT.hh:54
Laplacian Smoothing.
Definition: JacobiLaplaceSmootherT.hh:76
void smooth(unsigned int _n)
Do _n smoothing iterations.
Definition: JacobiLaplaceSmootherT_impl.hh:74
Base class for smoothing algorithms.
Definition: SmootherT.hh:77