45 #define ISOTROPICREMESHER_C 47 #include "IsotropicRemesherT.hh" 49 #include <ACG/Geometry/Algorithms.hh> 52 #include <ACG/Geometry/bsp/TriangleBSPT.hh> 55 template<
class MeshT >
58 const double low = (4.0 / 5.0) * _targetEdgeLength;
59 const double high = (4.0 / 3.0) * _targetEdgeLength;
61 MeshT meshCopy = _mesh;
64 for (
int i=0; i < 10; i++){
66 prgEmt_->sendProgressSignal(10*i + 0);
69 splitLongEdges(_mesh, high);
71 prgEmt_->sendProgressSignal(10*i + 2);
74 collapseShortEdges(_mesh, low, high);
76 prgEmt_->sendProgressSignal(10*i + 4);
79 equalizeValences(_mesh);
81 prgEmt_->sendProgressSignal(10*i + 6);
84 tangentialRelaxation(_mesh);
86 prgEmt_->sendProgressSignal(10*i + 8);
89 projectToSurface(_mesh, meshCopy, triangleBSP);
91 prgEmt_->sendProgressSignal(10*i + 10);
97 template<
class MeshT >
104 triangle_bsp->
reserve(_mesh.n_faces());
106 typename MeshT::FIter f_it = _mesh.faces_begin();
107 typename MeshT::FIter f_end = _mesh.faces_end();
109 for (; f_it!=f_end; ++f_it)
112 triangle_bsp->
build(10, 100);
119 template<
class MeshT >
123 const double _maxEdgeLengthSqr = _maxEdgeLength * _maxEdgeLength;
125 typename MeshT::EdgeIter e_it;
126 typename MeshT::EdgeIter e_end = _mesh.edges_end();
129 for (e_it = _mesh.edges_begin(); e_it != e_end; ++e_it){
130 const typename MeshT::HalfedgeHandle & hh = _mesh.halfedge_handle( *e_it, 0 );
132 const typename MeshT::VertexHandle & v0 = _mesh.from_vertex_handle(hh);
133 const typename MeshT::VertexHandle & v1 = _mesh.to_vertex_handle(hh);
135 typename MeshT::Point vec = _mesh.point(v1) - _mesh.point(v0);
138 if ( vec.sqrnorm() > _maxEdgeLengthSqr ){
140 const typename MeshT::Point midPoint = _mesh.point(v0) + ( 0.5 * vec );
143 typename MeshT::VertexHandle vh = _mesh.add_vertex( midPoint );
145 bool hadFeature = _mesh.status(*e_it).feature();
147 _mesh.split(*e_it, vh);
151 typename MeshT::VOHIter vh_it;
152 for (vh_it = _mesh.voh_iter(vh); vh_it.is_valid(); ++vh_it)
153 if ( _mesh.to_vertex_handle(*vh_it) == v0 || _mesh.to_vertex_handle(*vh_it) == v1 )
154 _mesh.status( _mesh.edge_handle( *vh_it ) ).set_feature(
true );
161 template<
class MeshT >
164 const double _minEdgeLengthSqr = _minEdgeLength * _minEdgeLength;
165 const double _maxEdgeLengthSqr = _maxEdgeLength * _maxEdgeLength;
169 if ( !_mesh.get_property_handle(checked,
"Checked Property") )
170 _mesh.add_property(checked,
"Checked Property" );
173 typename MeshT::ConstEdgeIter e_it;
174 typename MeshT::ConstEdgeIter e_end = _mesh.edges_end();
176 for (e_it = _mesh.edges_begin(); e_it != e_end; ++e_it)
177 _mesh.property(checked, *e_it) =
false;
180 bool finished =
false;
186 for (e_it = _mesh.edges_begin(); e_it != _mesh.edges_end() ; ++e_it){
188 if ( _mesh.property(checked, *e_it) )
191 _mesh.property(checked, *e_it) =
true;
193 const typename MeshT::HalfedgeHandle & hh = _mesh.halfedge_handle( *e_it, 0 );
195 const typename MeshT::VertexHandle & v0 = _mesh.from_vertex_handle(hh);
196 const typename MeshT::VertexHandle & v1 = _mesh.to_vertex_handle(hh);
198 const typename MeshT::Point vec = _mesh.point(v1) - _mesh.point(v0);
200 const double edgeLength = vec.sqrnorm();
203 if ( (edgeLength < _minEdgeLengthSqr) && (edgeLength > DBL_EPSILON) ){
206 const typename MeshT::Point & B = _mesh.point(v1);
208 bool collapse_ok =
true;
210 for(
typename MeshT::VOHIter vh_it = _mesh.voh_iter(v0); vh_it.is_valid(); ++vh_it)
211 if ( (( B - _mesh.point( _mesh.to_vertex_handle(*vh_it) ) ).sqrnorm() > _maxEdgeLengthSqr )
212 || ( _mesh.status( _mesh.edge_handle( *vh_it ) ).feature())
213 || ( _mesh.is_boundary( _mesh.edge_handle( *vh_it ) ) )){
218 if( collapse_ok && _mesh.is_collapse_ok(hh) ) {
219 _mesh.collapse( hh );
229 _mesh.remove_property(checked);
231 _mesh.garbage_collection();
234 template<
class MeshT >
238 typename MeshT::EdgeIter e_it;
239 typename MeshT::EdgeIter e_end = _mesh.edges_end();
241 for (e_it = _mesh.edges_sbegin(); e_it != e_end; ++e_it){
243 if ( !_mesh.is_flip_ok(*e_it) )
continue;
244 if ( _mesh.status( *e_it ).feature() )
continue;
247 const typename MeshT::HalfedgeHandle & h0 = _mesh.halfedge_handle( *e_it, 0 );
248 const typename MeshT::HalfedgeHandle & h1 = _mesh.halfedge_handle( *e_it, 1 );
250 if (h0.is_valid() && h1.is_valid())
252 if (_mesh.face_handle(h0).is_valid() && _mesh.face_handle(h1).is_valid()){
254 const typename MeshT::VertexHandle & a = _mesh.to_vertex_handle(h0);
255 const typename MeshT::VertexHandle & b = _mesh.to_vertex_handle(h1);
256 const typename MeshT::VertexHandle & c = _mesh.to_vertex_handle(_mesh.next_halfedge_handle(h0));
257 const typename MeshT::VertexHandle & d = _mesh.to_vertex_handle(_mesh.next_halfedge_handle(h1));
259 const int deviation_pre = abs((
int)(_mesh.valence(a) - targetValence(_mesh, a)))
260 +abs((
int)(_mesh.valence(b) - targetValence(_mesh, b)))
261 +abs((
int)(_mesh.valence(c) - targetValence(_mesh, c)))
262 +abs((
int)(_mesh.valence(d) - targetValence(_mesh, d)));
265 const int deviation_post = abs((
int)(_mesh.valence(a) - targetValence(_mesh, a)))
266 +abs((
int)(_mesh.valence(b) - targetValence(_mesh, b)))
267 +abs((
int)(_mesh.valence(c) - targetValence(_mesh, c)))
268 +abs((
int)(_mesh.valence(d) - targetValence(_mesh, d)));
270 if (deviation_pre <= deviation_post)
277 template<
class MeshT >
281 if (isBoundary(_mesh,_vh))
287 template<
class MeshT >
291 typename MeshT::ConstVertexOHalfedgeIter voh_it;
293 for (voh_it = _mesh.voh_iter( _vh ); voh_it.is_valid(); ++voh_it )
294 if ( _mesh.is_boundary( _mesh.edge_handle( *voh_it ) ) )
300 template<
class MeshT >
304 typename MeshT::ConstVertexOHalfedgeIter voh_it;
306 for (voh_it = _mesh.voh_iter( _vh ); voh_it.is_valid(); ++voh_it )
307 if ( _mesh.status( _mesh.edge_handle( *voh_it ) ).feature() )
313 template<
class MeshT >
316 _mesh.update_normals();
320 if ( !_mesh.get_property_handle(q,
"q Property") )
321 _mesh.add_property(q,
"q Property" );
323 typename MeshT::ConstVertexIter v_it;
324 typename MeshT::ConstVertexIter v_end = _mesh.vertices_end();
327 for (v_it = _mesh.vertices_sbegin(); v_it != v_end; ++v_it){
329 typename MeshT::Point tmp(0.0, 0.0, 0.0);
332 typename MeshT::VVIter vv_it;
333 for (vv_it = _mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it){
334 tmp += _mesh.point(*vv_it);
341 _mesh.property(q, *v_it) = tmp;
345 for (v_it = _mesh.vertices_sbegin(); v_it != v_end; ++v_it){
346 if ( !isBoundary(_mesh, *v_it) && !isFeature(_mesh, *v_it) )
347 _mesh.set_point(*v_it, _mesh.property(q, *v_it) + (_mesh.normal(*v_it)| (_mesh.point(*v_it) - _mesh.property(q, *v_it) ) ) * _mesh.normal(*v_it));
350 _mesh.remove_property(q);
353 template <
class MeshT>
354 template <
class SpatialSearchT>
355 typename MeshT::Point
357 const typename MeshT::Point& _point,
358 typename MeshT::FaceHandle& _fh,
359 SpatialSearchT* _ssearch,
363 typename MeshT::Point p_best = _mesh.point(_mesh.vertex_handle(0));
364 typename MeshT::Scalar d_best = (_point-p_best).
sqrnorm();
366 typename MeshT::FaceHandle fh_best;
371 typename MeshT::ConstFaceIter cf_it = _mesh.faces_begin();
372 typename MeshT::ConstFaceIter cf_end = _mesh.faces_end();
374 for(; cf_it != cf_end; ++cf_it)
376 typename MeshT::ConstFaceVertexIter cfv_it = _mesh.cfv_iter(*cf_it);
378 const typename MeshT::Point& pt0 = _mesh.point( *cfv_it);
379 const typename MeshT::Point& pt1 = _mesh.point( *(++cfv_it));
380 const typename MeshT::Point& pt2 = _mesh.point( *(++cfv_it));
382 typename MeshT::Point ptn;
384 typename MeshT::Scalar d = ACG::Geometry::distPointTriangleSquared( _point,
390 if( d < d_best && d >= 0.0)
404 *_dbest = sqrt(d_best);
411 typename MeshT::FaceHandle fh = _ssearch->nearest(_point).handle;
412 typename MeshT::CFVIter fv_it = _mesh.cfv_iter(fh);
414 const typename MeshT::Point& pt0 = _mesh.point( *( fv_it));
415 const typename MeshT::Point& pt1 = _mesh.point( *(++fv_it));
416 const typename MeshT::Point& pt2 = _mesh.point( *(++fv_it));
419 d_best = ACG::Geometry::distPointTriangleSquared(_point, pt0, pt1, pt2, p_best);
426 *_dbest = sqrt(d_best);
433 template<
class MeshT >
434 template<
class SpatialSearchT >
438 typename MeshT::VertexIter v_it;
439 typename MeshT::VertexIter v_end = _mesh.vertices_end();
441 for (v_it = _mesh.vertices_begin(); v_it != v_end; ++v_it){
443 if (isBoundary(_mesh, *v_it))
continue;
444 if ( isFeature(_mesh, *v_it))
continue;
446 typename MeshT::Point p = _mesh.point(*v_it);
447 typename MeshT::FaceHandle fhNear;
450 typename MeshT::Point pNear = findNearestPoint(_original, p, fhNear, _ssearch, &distance);
452 _mesh.set_point(*v_it, pNear);
void remesh(MeshT &_mesh, const double _targetEdgeLength)
do the remeshing
Scalar sqrnorm(const VectorT< Scalar, DIM > &_v)
void build(unsigned int _max_handles, unsigned int _max_depth)
void push_back(Handle _h)
Add a handle to the BSP.
int targetValence(MeshT &_mesh, const typename MeshT::VertexHandle &_vh)
returns 4 for boundary vertices and 6 otherwise
void splitLongEdges(MeshT &_mesh, const double _maxEdgeLength)
performs edge splits until all edges are shorter than the threshold
void collapseShortEdges(MeshT &_mesh, const double _minEdgeLength, const double _maxEdgeLength)
collapse edges shorter than minEdgeLength if collapsing doesn't result in new edge longer than maxEdg...
void reserve(size_t _n)
Reserve memory for _n entries.