45#define ISOTROPICREMESHER_C
47#include "IsotropicRemesherT.hh"
49#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
51#include <ACG/Geometry/Algorithms.hh>
54#include <ACG/Geometry/bsp/TriangleBSPT.hh>
57template<
class MeshT >
60 const double low = (4.0 / 5.0) * _targetEdgeLength;
61 const double high = (4.0 / 3.0) * _targetEdgeLength;
63 MeshT meshCopy = _mesh;
66 for (
int i=0; i < 10; i++){
68 prgEmt_->sendProgressSignal(10*i + 0);
71 splitLongEdges(_mesh, high);
73 prgEmt_->sendProgressSignal(10*i + 2);
76 collapseShortEdges(_mesh, low, high);
78 prgEmt_->sendProgressSignal(10*i + 4);
81 equalizeValences(_mesh);
83 prgEmt_->sendProgressSignal(10*i + 6);
86 tangentialRelaxation(_mesh);
88 prgEmt_->sendProgressSignal(10*i + 8);
91 projectToSurface(_mesh, meshCopy, triangleBSP);
93 prgEmt_->sendProgressSignal(10*i + 10);
99template<
class MeshT >
108 for (
auto f_it : _mesh.faces())
111 triangle_bsp->
build(10, 100);
118template<
class MeshT >
122 const double _maxEdgeLengthSqr = _maxEdgeLength * _maxEdgeLength;
125 for (
auto e_it : _mesh.edges()) {
128 const typename MeshT::VertexHandle & v0 = hh.
from();
129 const typename MeshT::VertexHandle & v1 = hh.
to();
131 typename MeshT::Point vec = _mesh.point(v1) - _mesh.point(v0);
134 if ( vec.sqrnorm() > _maxEdgeLengthSqr ){
136 const typename MeshT::Point midPoint = _mesh.point(v0) + ( 0.5 * vec );
139 typename MeshT::VertexHandle vh = _mesh.
add_vertex( midPoint );
141 bool hadFeature = _mesh.status(e_it).feature();
143 _mesh.split(e_it, vh);
147 for (
auto voh_it : _mesh.voh_range(vh))
148 if ( voh_it.to() == v0 || voh_it.to() == v1 )
149 _mesh.status( voh_it.edge() ).set_feature(
true );
156template<
class MeshT >
159 const double _minEdgeLengthSqr = _minEdgeLength * _minEdgeLength;
160 const double _maxEdgeLengthSqr = _maxEdgeLength * _maxEdgeLength;
164 if ( !_mesh.get_property_handle(checked,
"Checked Property") )
165 _mesh.add_property(checked,
"Checked Property" );
168 for (
auto e_it : _mesh.edges())
169 _mesh.property(checked, e_it) =
false;
172 bool finished =
false;
178 for (
auto e_it : _mesh.edges()) {
180 if ( _mesh.property(checked, e_it) )
183 _mesh.property(checked, e_it) =
true;
187 const typename MeshT::VertexHandle & v0 = hh.
from();
188 const typename MeshT::VertexHandle & v1 = hh.
to();
190 const typename MeshT::Point vec = _mesh.point(v1) - _mesh.point(v0);
192 const double edgeLength = vec.sqrnorm();
195 if ( (edgeLength < _minEdgeLengthSqr) && (edgeLength > DBL_EPSILON) ){
198 const typename MeshT::Point & B = _mesh.point(v1);
200 bool collapse_ok =
true;
202 for (
auto voh_it : _mesh.voh_range(v0))
203 if ( (( B - _mesh.point( voh_it.to() ) ).sqrnorm() > _maxEdgeLengthSqr )
204 || ( _mesh.status( voh_it.edge() ).feature())
205 || ( voh_it.edge().is_boundary() ) ){
210 if( collapse_ok && _mesh.is_collapse_ok(hh) ) {
211 _mesh.collapse( hh );
221 _mesh.remove_property(checked);
223 _mesh.garbage_collection();
226template<
class MeshT >
230 for (
auto e_it : _mesh.edges()) {
232 if ( !_mesh.is_flip_ok(e_it) )
continue;
233 if ( _mesh.status( e_it ).feature() )
continue;
248 const int deviation_pre = abs((
int)(a.
valence() - targetValence(_mesh, a)))
249 +abs((
int)(b.
valence() - targetValence(_mesh, b)))
250 +abs((
int)(c.
valence() - targetValence(_mesh, c)))
251 +abs((
int)(d.
valence() - targetValence(_mesh, d)));
254 const int deviation_post = abs((
int)(a.
valence() - targetValence(_mesh, a)))
255 +abs((
int)(b.
valence() - targetValence(_mesh, b)))
256 +abs((
int)(c.
valence() - targetValence(_mesh, c)))
257 +abs((
int)(d.
valence() - targetValence(_mesh, d)));
259 if (deviation_pre <= deviation_post)
266template<
class MeshT >
270 if (isBoundary(_mesh,_vh))
276template<
class MeshT >
280 for (
auto voh_it : _mesh.voh_range(_vh))
281 if ( voh_it.edge().is_boundary() )
287template<
class MeshT >
291 for (
auto voh_it : _mesh.voh_range(_vh))
292 if ( _mesh.status( voh_it.edge()).feature() )
298template<
class MeshT >
301 _mesh.update_normals();
305 if ( !_mesh.get_property_handle(q,
"q Property") )
306 _mesh.add_property(q,
"q Property" );
309 for (
auto v_it : _mesh.vertices()){
311 typename MeshT::Point tmp(0.0, 0.0, 0.0);
314 for (
auto vv_it : v_it.vertices()){
315 tmp += _mesh.point(vv_it);
322 _mesh.property(q, v_it) = tmp;
326 for (
auto v_it : _mesh.vertices()){
327 if ( !v_it.is_boundary() && !v_it.feature() )
328 _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));
331 _mesh.remove_property(q);
334template <
class MeshT>
335template <
class SpatialSearchT>
338 const typename MeshT::Point& _point,
339 typename MeshT::FaceHandle& _fh,
340 SpatialSearchT* _ssearch,
344 typename MeshT::Point p_best = _mesh.point(_mesh.vertex_handle(0));
345 typename MeshT::Scalar d_best = (_point-p_best).
sqrnorm();
347 typename MeshT::FaceHandle fh_best;
352 for (
auto cf_it : _mesh.faces()) {
353 typename MeshT::ConstFaceVertexIter cfv_it = _mesh.cfv_iter(cf_it);
355 const typename MeshT::Point& pt0 = _mesh.point( *cfv_it);
356 const typename MeshT::Point& pt1 = _mesh.point( *(++cfv_it));
357 const typename MeshT::Point& pt2 = _mesh.point( *(++cfv_it));
359 typename MeshT::Point ptn;
361 typename MeshT::Scalar d = ACG::Geometry::distPointTriangleSquared( _point,
367 if( d < d_best && d >= 0.0)
381 *_dbest = sqrt(d_best);
388 typename MeshT::FaceHandle fh = _ssearch->nearest(_point).handle;
389 typename MeshT::CFVIter fv_it = _mesh.cfv_iter(fh);
391 const typename MeshT::Point& pt0 = _mesh.point( *( fv_it));
392 const typename MeshT::Point& pt1 = _mesh.point( *(++fv_it));
393 const typename MeshT::Point& pt2 = _mesh.point( *(++fv_it));
396 d_best = ACG::Geometry::distPointTriangleSquared(_point, pt0, pt1, pt2, p_best);
403 *_dbest = sqrt(d_best);
410template<
class MeshT >
411template<
class SpatialSearchT >
415 for (
auto v_it : _mesh.vertices()){
417 if ( v_it.is_boundary() )
continue;
418 if ( v_it.feature() )
continue;
420 typename MeshT::Point p = _mesh.point(v_it);
421 typename MeshT::FaceHandle fhNear;
424 typename MeshT::Point pNear = findNearestPoint(_original, p, fhNear, _ssearch, &distance);
426 _mesh.set_point(v_it, pNear);
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 remesh(MeshT &_mesh, const double _targetEdgeLength)
do the remeshing
void splitLongEdges(MeshT &_mesh, const double _maxEdgeLength)
performs edge splits until all edges are shorter than the threshold
int targetValence(MeshT &_mesh, const typename MeshT::VertexHandle &_vh)
returns 4 for boundary vertices and 6 otherwise
bool is_valid() const
The handle is valid iff the index is not negative.
Scalar sqrnorm(const VectorT< Scalar, DIM > &_v)
VertexHandle add_vertex(const VecT &_p)
Add a geometric point to the mesh.
PointT normal(HalfFaceHandle _hfh) const
size_t n_faces() const override
Get number of faces in mesh.
void build(unsigned int _max_handles, unsigned int _max_depth)
void push_back(Handle _h)
Add a handle to the BSP.
void reserve(size_t _n)
Reserve memory for _n entries.
SmartFaceHandle face() const
Returns incident face of halfedge.
SmartVertexHandle from() const
Returns vertex at start of halfedge.
SmartHalfedgeHandle next() const
Returns next halfedge handle.
SmartVertexHandle to() const
Returns vertex pointed to by halfedge.
Smart version of VertexHandle contains a pointer to the corresponding mesh and allows easier access t...
uint valence() const
Returns valence of the vertex.