Developer Documentation
BaseRemesherT_impl.hh
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 //=============================================================================
43 //
44 // CLASS BaseRemesherT - IMPLEMENTATION
45 //
46 //=============================================================================
47 
48 #define BASE_REMESHERT_C
49 
50 
51 //== INCLUDES =================================================================
52 
53 
54 #include "BaseRemesherT.hh"
55 
56 // Remshing
57 #include "DiffGeoT.hh"
58 
59 // OpenMesh
60 #include <OpenMesh/Core/Utils/Property.hh>
62 
63 // Selection Stuff
65 
66 
67 //== NAMESPACES ===============================================================
68 
69 namespace Remeshing {
70 
71 
72 //== IMPLEMENTATION ==========================================================
73 
74 
75 template <class Mesh>
76 BaseRemesherT<Mesh>::
77 BaseRemesherT(Mesh& _mesh, ProgressEmitter* _progress)
78  : mesh_(_mesh), refmesh_(0), bsp_(0), nothing_selected_(true),progress_(_progress) {
79 
80 }
81 
82 
83 //-----------------------------------------------------------------------------
84 
85 
86 template <class Mesh>
87 BaseRemesherT<Mesh>::
88 ~BaseRemesherT() {
89 
90  delete bsp_;
91  delete refmesh_;
92 }
93 
94 
95 //-----------------------------------------------------------------------------
96 
97 
98 template <class Mesh>
99 void
100 BaseRemesherT<Mesh>::
101 init_reference()
102 {
103  typename Mesh::VIter v_it, v_end;
104  typename Mesh::FIter f_it, f_end;
105  typename Mesh::CFVIter fv_it;
106  typename Mesh::VHandle v0, v1, v2;
107 
108 
109  // clear old stuff first
110  if (bsp_) delete_reference();
111 
112  // tag non-locked vertices + one ring
113  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
114  v_it!=v_end; ++v_it)
115  mesh_.status(*v_it).set_tagged(!mesh_.status(*v_it).locked());
116 
118 
119  // create reference mesh
120  refmesh_ = new Mesh();
121 
123  mesh_.add_property(vhandles);
124 
125  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
126  v_it!=v_end; ++v_it)
127  if (mesh_.status(*v_it).tagged())
128  mesh_.property(vhandles, *v_it) = refmesh_->add_vertex(mesh_.point(*v_it));
129 
130  for (f_it=mesh_.faces_begin(), f_end=mesh_.faces_end();
131  f_it!=f_end; ++f_it)
132  {
133  fv_it = mesh_.cfv_iter(*f_it);
134  v0 = *fv_it;
135  v1 = *(++fv_it);
136  v2 = *(++fv_it);
137 
138  if (mesh_.status(v0).tagged() &&
139  mesh_.status(v1).tagged() &&
140  mesh_.status(v2).tagged())
141  {
142  refmesh_->add_face( mesh_.property(vhandles, v0),
143  mesh_.property(vhandles, v1),
144  mesh_.property(vhandles, v2) );
145  }
146  }
147 
149  mesh_.remove_property(vhandles);
150 
151  // need vertex normals
152  refmesh_->request_face_normals();
153  refmesh_->request_vertex_normals();
154  refmesh_->update_normals(/*Mesh::ANGLE_WEIGHTED*/);
155 
156 
157  // build BSP
158  bsp_ = new BSP(*refmesh_);
159  bsp_->reserve(refmesh_->n_faces());
160  for (f_it=refmesh_->faces_begin(), f_end=refmesh_->faces_end();
161  f_it!=f_end; ++f_it)
162  bsp_->push_back(*f_it);
163  bsp_->build(10, 100);
164 }
165 
166 
167 //-----------------------------------------------------------------------------
168 
169 
170 template <class Mesh>
171 void
172 BaseRemesherT<Mesh>::
173 delete_reference()
174 {
175  delete bsp_; bsp_ = 0;
176  delete refmesh_; refmesh_ = 0;
177 }
178 
179 
180 //-----------------------------------------------------------------------------
181 
182 
183 template <class Mesh>
184 void
185 BaseRemesherT<Mesh>::
186 project_to_reference(typename Mesh::VertexHandle _vh) const
187 {
188  typename Mesh::Point p = mesh_.point(_vh);
189  typename Mesh::FaceHandle fh = bsp_->nearest(p).handle;
190 
191  if ( ! fh.is_valid() )
192  return;
193 
194  typename Mesh::CFVIter fv_it = refmesh_->cfv_iter(fh);
195 
196 
197  const typename Mesh::Point& p0 = refmesh_->point(*fv_it);
198  typename Mesh::Normal n0 = refmesh_->normal(*fv_it);
199  const typename Mesh::Point& p1 = refmesh_->point(*(++fv_it));
200  typename Mesh::Normal n1 = refmesh_->normal(*fv_it);
201  const typename Mesh::Point& p2 = refmesh_->point(*(++fv_it));
202  typename Mesh::Normal n2 = refmesh_->normal(*fv_it);
203 
204 
205  // project
206  ACG::Geometry::distPointTriangle(p, p0, p1, p2, p);
207  mesh_.set_point(_vh, p);
208 
209 
210  // get barycentric coordinates
211  if (!ACG::Geometry::baryCoord(p, p0, p1, p2, p))
212  p[0] = p[1] = p[2] = 1.0/3.0;
213 
214 
215  // interpolate normal
216  typename Mesh::Normal n;
217  n = (n0 *= p[0]);
218  n += (n1 *= p[1]);
219  n += (n2 *= p[2]);
220  n.normalize();
221  mesh_.set_normal(_vh, n);
222 }
223 
224 
225 //-----------------------------------------------------------------------------
226 
227 
228 template <class Mesh>
229 void
230 BaseRemesherT<Mesh>::
231 remesh(unsigned int _iters,
232  unsigned int _area_iters,
233  bool _use_projection,
234  Selection _selection) {
235 
236  try
237  {
238  if (_selection == VERTEX_SELECTION)
240  else if (_selection == FACE_SELECTION)
242  remeshh(_iters, _area_iters, _use_projection);
243  }
244  catch (std::bad_alloc&)
245  {
246  mesh_.clear();
247  omerr() << "Remeshig: Out of memory\n";
248  }
249 
250  cleanup();
251 }
252 
253 //-----------------------------------------------------------------------------
254 
255 template <class Mesh>
256 void
259 {
260  typename Mesh::EIter e_it, e_end;
261  typename Mesh::VIter v_it, v_end;
262  typename Mesh::FIter f_it, f_end;
263  typename Mesh::CFVIter fv_it;
264  typename Mesh::CVOHIter vh_it;
265  typename Mesh::VHandle v0, v1;
266  typename Mesh::FHandle f0, f1;
267 
268 
269  // need vertex and edge status
270  mesh_.request_vertex_status();
271  mesh_.request_edge_status();
272  mesh_.request_face_status();
273 
274 
275 
276  // if nothing selected -> select all
277  nothing_selected_ = true;
278  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
279  v_it!=v_end; ++v_it)
280  if (mesh_.status(*v_it).selected())
281  { nothing_selected_ = false; break; }
282 
283  if (nothing_selected_)
284  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
285  v_it!=v_end; ++v_it)
286  mesh_.status(*v_it).set_selected(true);
287 
288 
289 
290  // lock un-selected vertices & edges
291  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
292  v_it!=v_end; ++v_it)
293  mesh_.status(*v_it).set_locked(!mesh_.status(*v_it).selected());
294 
295  for (e_it=mesh_.edges_begin(), e_end=mesh_.edges_end();
296  e_it!=e_end; ++e_it)
297  {
298  v0 = mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 0));
299  v1 = mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 1));
300  mesh_.status(*e_it).set_locked(mesh_.status(v0).locked() ||
301  mesh_.status(v1).locked());
302  }
303 
304 
305 
306  // handle feature corners:
307  // lock corner vertices (>2 feature edges) and endpoints
308  // of feature lines (1 feature edge)
309  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
310  v_it!=v_end; ++v_it)
311  {
312  if (mesh_.status(*v_it).feature())
313  {
314  int c=0;
315  for (vh_it=mesh_.cvoh_iter(*v_it); vh_it.is_valid(); ++vh_it)
316  if (mesh_.status(mesh_.edge_handle(*vh_it)).feature())
317  ++c;
318  if (c!=2) mesh_.status(*v_it).set_locked(true);
319  }
320  }
321 
322 
323 
324  // build reference mesh
325  init_reference();
326 // if (emit_progress_) Progress().step(5);
327 
328 
329  // add properties
330  mesh_.add_property(valences_);
331  mesh_.add_property(update_);
332  mesh_.add_property(area_);
333 }
334 
335 //-----------------------------------------------------------------------------
336 
337 
338 template <class Mesh>
339 void
342 {
343  typename Mesh::EIter e_it, e_end;
344  typename Mesh::VIter v_it, v_end;
345  typename Mesh::FIter f_it, f_end;
346  typename Mesh::CFVIter fv_it;
347  typename Mesh::CVOHIter vh_it;
348  typename Mesh::VHandle v0, v1;
349  typename Mesh::FHandle f0, f1;
350 
351 
352  // need vertex and edge status
353  mesh_.request_vertex_status();
354  mesh_.request_edge_status();
355  mesh_.request_face_status();
356 
357  // if nothing selected -> select all
358  nothing_selected_ = true;
359  for (f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); f_it != f_end;
360  ++f_it)
361  {
362  if (mesh_.status(*f_it).selected())
363  {
364  nothing_selected_ = false;
365  break;
366  }
367  }
368 
369  if (nothing_selected_)
370  MeshSelection::selectAllFaces(&mesh_);
371 
372 
373 
374  // lock un-selected vertices & edges
375  for (v_it = mesh_.vertices_begin(), v_end = mesh_.vertices_end();
376  v_it != v_end; ++v_it)
377  {
378  bool all_faces_selected = true;
379 
380  for (typename Mesh::ConstVertexFaceIter vf_it = mesh_.cvf_iter(*v_it);
381  vf_it.is_valid(); ++vf_it)
382  {
383  if (!mesh_.status(*vf_it).selected())
384  {
385  all_faces_selected = false;
386  break;
387  }
388  }
389  mesh_.status(*v_it).set_locked(!all_faces_selected);
390  }
391 
392  for (e_it = mesh_.edges_begin(), e_end = mesh_.edges_end();
393  e_it != e_end; ++e_it)
394  {
395  if (mesh_.is_boundary(*e_it))
396  {
397  mesh_.status(*e_it).set_locked(true);
398  }
399  else
400  {
401  f0 = mesh_.face_handle(mesh_.halfedge_handle(*e_it, 0));
402  f1 = mesh_.face_handle(mesh_.halfedge_handle(*e_it, 1));
403 
404  mesh_.status(*e_it).set_locked(!(mesh_.status(f0).selected() && mesh_.status(f1).selected()));
405  }
406  }
407 
408  MeshSelection::clearFaceSelection(&mesh_);
409 
410  // handle feature corners:
411  // lock corner vertices (>2 feature edges) and endpoints
412  // of feature lines (1 feature edge)
413  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
414  v_it!=v_end; ++v_it)
415  {
416  if (mesh_.status(*v_it).feature())
417  {
418  int c=0;
419  for (vh_it=mesh_.cvoh_iter(*v_it); vh_it.is_valid(); ++vh_it)
420  if (mesh_.status(mesh_.edge_handle(*vh_it)).feature())
421  ++c;
422  if (c!=2) mesh_.status(*v_it).set_locked(true);
423  }
424  }
425 
426 
427 
428  // build reference mesh
429  init_reference();
430 // if (emit_progress_) Progress().step(5);
431 
432 
433  // add properties
434  mesh_.add_property(valences_);
435  mesh_.add_property(update_);
436  mesh_.add_property(area_);
437 }
438 
439 
440 //-----------------------------------------------------------------------------
441 
442 
443 template <class Mesh>
444 void
446 remeshh(unsigned int _iters,
447  unsigned int _area_iters, bool _use_projection) {
448 
449  double progress_step = 100.0 / (((double)_iters/4.0 + (double)_area_iters));
450  double total_progress = 0.0;
451 
452  for (unsigned int i = 0; i < _iters; ++i) {
453 
454  split_long_edges();
455  if(progress_ != NULL) {
456  total_progress += progress_step;
457  progress_->sendProgressSignal(total_progress);
458  }
459 
460  collapse_short_edges();
461  if(progress_ != NULL) {
462  total_progress += progress_step;
463  progress_->sendProgressSignal(total_progress);
464  }
465 
466  flip_edges();
467  if(progress_ != NULL) {
468  total_progress += progress_step;
469  progress_->sendProgressSignal(total_progress);
470  }
471 
472  tangential_smoothing(_use_projection);
473  if(progress_ != NULL) {
474  total_progress += progress_step;
475  progress_->sendProgressSignal(total_progress);
476  }
477  }
478 
479  if (_area_iters) {
480  balanace_area(_area_iters, _use_projection);
481  if(progress_ != NULL) {
482  total_progress += progress_step;
483  progress_->sendProgressSignal(total_progress);
484  }
485  }
486 
487  // feature edges block flips -> might lead to caps
488  remove_caps();
489 }
490 
491 
492 //-----------------------------------------------------------------------------
493 
494 
495 template <class Mesh>
496 void
498 cleanup()
499 {
500  typename Mesh::EIter e_it, e_end;
501  typename Mesh::VIter v_it, v_end;
502  typename Mesh::FIter f_it, f_end;
503  typename Mesh::CFVIter fv_it;
504  typename Mesh::CVOHIter vh_it;
505  typename Mesh::VHandle v0, v1;
506  typename Mesh::FHandle f0, f1;
507 
508 
509  // remove properties
510  mesh_.remove_property(valences_);
511  mesh_.remove_property(update_);
512  mesh_.remove_property(area_);
513 
514 
515  // remove reference again
516  delete_reference();
517 
518 
519  // unlock all vertices & edges
520  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
521  v_it!=v_end; ++v_it)
522  {
523  mesh_.status(*v_it).set_locked(false);
524  }
525  for (e_it=mesh_.edges_begin(), e_end=mesh_.edges_end();
526  e_it!=e_end; ++e_it)
527  {
528  mesh_.status(*e_it).set_locked(false);
529  }
530 
531 
532  // de-select if nothing was selected before
533  if (nothing_selected_)
534  for (v_it=mesh_.vertices_begin(), v_end=mesh_.vertices_end();
535  v_it!=v_end; ++v_it)
536  mesh_.status(*v_it).set_selected(false);
537 
538 
539 
540  // free vertex and edge status
541  mesh_.release_vertex_status();
542  mesh_.release_edge_status();
543  mesh_.release_face_status();
544 }
545 
546 
547 //-----------------------------------------------------------------------------
548 
549 
550 template <class Mesh>
551 void
554 {
555  typename Mesh::VIter v_it, v_end;
556  typename Mesh::EIter e_it, e_end;
557  typename Mesh::VHandle v0, v1, vh;
558  typename Mesh::EHandle eh, e0, e1;
559  typename Mesh::FHandle f0, f1, f2, f3;
560 
561  bool ok, is_feature, is_boundary;
562  int i;
563 
564  // un-tagg
565  for (v_it = mesh_.vertices_begin(), v_end = mesh_.vertices_end(); v_it != v_end; ++v_it)
566  mesh_.status(*v_it).set_tagged(false);
567 
568  // handle Nastran PIDs during refinement
570  mesh_.get_property_handle(pids, "Nastran PIDs");
571 
572  // split long edges
573  for (ok = false, i = 0; !ok && i < 100; ++i) {
574  ok = true;
575 
576  for (e_it = mesh_.edges_begin(), e_end = mesh_.edges_end(); e_it != e_end; ++e_it) {
577  v0 = mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 0));
578  v1 = mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 1));
579 
580  if (!mesh_.status(*e_it).locked() && is_too_long(v0, v1)) {
581  const typename Mesh::Point& p0 = mesh_.point(v0);
582  const typename Mesh::Point& p1 = mesh_.point(v1);
583 
584  is_feature = mesh_.status(*e_it).feature();
585  is_boundary = mesh_.is_boundary(*e_it);
586 
587  vh = mesh_.add_vertex((p0 + p1) * 0.5);
588  mesh_.split(*e_it, vh);
589 
590  mesh_.status(vh).set_selected(true);
591 
592  if (is_feature) {
593  eh = (is_boundary ? mesh_.edge_handle(mesh_.n_edges() - 2) : mesh_.edge_handle(mesh_.n_edges() - 3));
594 
595  mesh_.status(eh).set_feature(true);
596  mesh_.status(vh).set_feature(true);
597  } else {
598  project_to_reference(vh);
599  }
600 
601  if (pids.is_valid()) {
602  e0 = *e_it;
603  e1 = (is_boundary ? mesh_.edge_handle(mesh_.n_edges() - 2) : mesh_.edge_handle(mesh_.n_edges() - 3));
604 
605  f0 = mesh_.face_handle(mesh_.halfedge_handle(e0, 0));
606  f1 = mesh_.face_handle(mesh_.halfedge_handle(e0, 1));
607  f2 = mesh_.face_handle(mesh_.halfedge_handle(e1, 0));
608  f3 = mesh_.face_handle(mesh_.halfedge_handle(e1, 1));
609 
610  if (f0.is_valid() && f3.is_valid()) mesh_.property(pids, f3) = mesh_.property(pids, f0);
611 
612  if (f1.is_valid() && f2.is_valid()) mesh_.property(pids, f2) = mesh_.property(pids, f1);
613  }
614 
615  ok = false;
616  }
617  }
618  }
619 
620  if (i == 100) omlog() << "split break\n";
621 }
622 
623 
624 //-----------------------------------------------------------------------------
625 
626 
627 template <class Mesh>
628 void
631 {
632  typename Mesh::EIter e_it, e_end;
633  typename Mesh::CVVIter vv_it;
634  typename Mesh::VHandle v0, v1;
635  typename Mesh::HHandle h0, h1, h01, h10;
636  typename Mesh::Point p;
637  bool ok, skip, b0, b1, l0, l1, f0, f1;
638  int i;
639  bool hcol01, hcol10;
640 
641  for (ok = false, i = 0; !ok && i < 100; ++i) {
642  ok = true;
643 
644  for (e_it = mesh_.edges_begin(), e_end = mesh_.edges_end(); e_it != e_end; ++e_it) {
645  if (!mesh_.status(*e_it).deleted() && !mesh_.status(*e_it).locked()) {
646  h10 = mesh_.halfedge_handle(*e_it, 0);
647  h01 = mesh_.halfedge_handle(*e_it, 1);
648  v0 = mesh_.to_vertex_handle(h10);
649  v1 = mesh_.to_vertex_handle(h01);
650 
651  if (is_too_short(v0, v1)) {
652  // get status
653  b0 = mesh_.is_boundary(v0);
654  b1 = mesh_.is_boundary(v1);
655  l0 = mesh_.status(v0).locked();
656  l1 = mesh_.status(v1).locked();
657  f0 = mesh_.status(v0).feature();
658  f1 = mesh_.status(v1).feature();
659  hcol01 = hcol10 = true;
660 
661  if (mesh_.status(*e_it).feature() && !f0 && !f1)
662  std::cerr << "Bad luck" << std::endl;
663 
664  // boundary rules
665  if (b0 && b1) {
666  if (!mesh_.is_boundary(*e_it))
667  continue;
668  } else if (b0)
669  hcol01 = false;
670  else if (b1)
671  hcol10 = false;
672 
673  // locked rules
674  if (l0 && l1)
675  continue;
676  else if (l0)
677  hcol01 = false;
678  else if (l1)
679  hcol10 = false;
680 
681  // feature rules
682 
683  // the other two edges removed by collapse must not be features
684  h0 = mesh_.prev_halfedge_handle(h01);
685  h1 = mesh_.next_halfedge_handle(h10);
686  if (mesh_.status(mesh_.edge_handle(h0)).feature() || mesh_.status(mesh_.edge_handle(h1)).feature())
687  hcol01 = false;
688  h0 = mesh_.prev_halfedge_handle(h10);
689  h1 = mesh_.next_halfedge_handle(h01);
690  if (mesh_.status(mesh_.edge_handle(h0)).feature() || mesh_.status(mesh_.edge_handle(h1)).feature())
691  hcol10 = false;
692 
693  if (f0 && f1) {
694  // edge must be feature
695  if (!mesh_.status(*e_it).feature())
696  continue;
697 
698  // the other two edges removed by collapse must not be features
699  h0 = mesh_.prev_halfedge_handle(h01);
700  h1 = mesh_.next_halfedge_handle(h10);
701  if (mesh_.status(mesh_.edge_handle(h0)).feature() || mesh_.status(mesh_.edge_handle(h1)).feature())
702  hcol01 = false;
703  h0 = mesh_.prev_halfedge_handle(h10);
704  h1 = mesh_.next_halfedge_handle(h01);
705  if (mesh_.status(mesh_.edge_handle(h0)).feature() || mesh_.status(mesh_.edge_handle(h1)).feature())
706  hcol10 = false;
707  } else if (f0)
708  hcol01 = false;
709  else if (f1)
710  hcol10 = false;
711 
712  // topological rules
713  if (hcol01)
714  hcol01 = mesh_.is_collapse_ok(h01);
715  if (hcol10)
716  hcol10 = mesh_.is_collapse_ok(h10);
717 
718  // both collapses possible: collapse into vertex w/ higher valence
719  if (hcol01 && hcol10) {
720  if (mesh_.valence(v0) < mesh_.valence(v1))
721  hcol10 = false;
722  else
723  hcol01 = false;
724  }
725 
726  // try v1 -> v0
727  if (hcol10) {
728  // don't create too long edges
729  skip = false;
730  for (vv_it = mesh_.cvv_iter(v1); vv_it.is_valid() && !skip; ++vv_it)
731  if (is_too_long(v0, *vv_it))
732  skip = true;
733 
734  if (!skip) {
735  mesh_.collapse(h10);
736  ok = false;
737  }
738  }
739 
740  // try v0 -> v1
741  else if (hcol01) {
742  // don't create too long edges
743  skip = false;
744  for (vv_it = mesh_.cvv_iter(v0); vv_it.is_valid() && !skip; ++vv_it)
745  if (is_too_long(v1, *vv_it))
746  skip = true;
747 
748  if (!skip) {
749  mesh_.collapse(h01);
750  ok = false;
751  }
752  }
753  }
754  }
755  }
756  }
757 
758  mesh_.garbage_collection();
759 
760  if (i == 100)
761  omlog() << "collapse break\n";
762 }
763 
764 
765 //-----------------------------------------------------------------------------
766 
767 
768 template <class Mesh>
769 void
771 flip_edges()
772 {
773  typename Mesh::EIter e_it, e_end;
774  typename Mesh::VIter v_it, v_end;
775  typename Mesh::VHandle v0, v1, v2, v3, vh;
776  typename Mesh::HHandle hh;
777  typename Mesh::Point p;
778  typename Mesh::FHandle fh;
779 
780  int val0, val1, val2, val3;
781  int val_opt0, val_opt1, val_opt2, val_opt3;
782  int ve0, ve1, ve2, ve3, ve_before, ve_after;
783  bool ok;
784  int i;
785 
786  // compute vertex valences
787  for (v_it = mesh_.vertices_begin(), v_end = mesh_.vertices_end(); v_it != v_end; ++v_it)
788  mesh_.property(valences_, *v_it) = mesh_.valence(*v_it);
789 
790  // flip all edges
791  for (ok = false, i = 0; !ok && i < 100; ++i) {
792  ok = true;
793 
794  for (e_it = mesh_.edges_begin(), e_end = mesh_.edges_end(); e_it != e_end; ++e_it) {
795  if (!mesh_.status(*e_it).locked() && !mesh_.status(*e_it).feature()) {
796  hh = mesh_.halfedge_handle(*e_it, 0);
797  v0 = mesh_.to_vertex_handle(hh);
798  v2 = mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh));
799  if ( !mesh_.next_halfedge_handle(hh).is_valid() ) {
800  std::cerr << "Error v2" << std::endl;
801  continue;
802  }
803  hh = mesh_.halfedge_handle(*e_it, 1);
804  v1 = mesh_.to_vertex_handle(hh);
805  v3 = mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh));
806  if ( !mesh_.next_halfedge_handle(hh).is_valid() ) {
807  std::cerr << "Error v3" << std::endl;
808  continue;
809  }
810 
811  if ( !v2.is_valid())
812  continue;
813 
814  if (!mesh_.status(v0).locked() && !mesh_.status(v1).locked() && !mesh_.status(v2).locked()
815  && !mesh_.status(v3).locked()) {
816  val0 = mesh_.property(valences_, v0);
817  val1 = mesh_.property(valences_, v1);
818  val2 = mesh_.property(valences_, v2);
819  val3 = mesh_.property(valences_, v3);
820 
821  val_opt0 = (mesh_.is_boundary(v0) ? 4 : 6);
822  val_opt1 = (mesh_.is_boundary(v1) ? 4 : 6);
823  val_opt2 = (mesh_.is_boundary(v2) ? 4 : 6);
824  val_opt3 = (mesh_.is_boundary(v3) ? 4 : 6);
825 
826  ve0 = (val0 - val_opt0);
827  ve0 *= ve0;
828  ve1 = (val1 - val_opt1);
829  ve1 *= ve1;
830  ve2 = (val2 - val_opt2);
831  ve2 *= ve2;
832  ve3 = (val3 - val_opt3);
833  ve3 *= ve3;
834 
835  ve_before = ve0 + ve1 + ve2 + ve3;
836 
837  --val0;
838  --val1;
839  ++val2;
840  ++val3;
841 
842  ve0 = (val0 - val_opt0);
843  ve0 *= ve0;
844  ve1 = (val1 - val_opt1);
845  ve1 *= ve1;
846  ve2 = (val2 - val_opt2);
847  ve2 *= ve2;
848  ve3 = (val3 - val_opt3);
849  ve3 *= ve3;
850 
851  ve_after = ve0 + ve1 + ve2 + ve3;
852 
853  if (ve_before > ve_after && mesh_.is_flip_ok(*e_it)) {
854  mesh_.flip(*e_it);
855  --mesh_.property(valences_, v0);
856  --mesh_.property(valences_, v1);
857  ++mesh_.property(valences_, v2);
858  ++mesh_.property(valences_, v3);
859  ok = false;
860  }
861  }
862  }
863  }
864  }
865 
866  if (i == 100)
867  omlog() << "flip break\n";
868 }
869 
870 
871 //-----------------------------------------------------------------------------
872 
873 
874 template <class Mesh>
875 void
877 tangential_smoothing(bool _use_projection)
878 {
879  typename Mesh::VIter v_it, v_end(mesh_.vertices_end());
880  typename Mesh::CVVIter vv_it;
881  typename Mesh::Scalar valence;
882  typename Mesh::Point u, n;
883 
884 
885  // tag active vertices
886  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
887  mesh_.status(*v_it).set_tagged( !mesh_.status(*v_it).locked() &&
888  !mesh_.status(*v_it).feature() &&
889  !mesh_.is_boundary(*v_it) );
890 
891 
892  // smooth
893  for (int iters=0; iters<10; ++iters)
894  {
895  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
896  {
897  if (mesh_.status(*v_it).tagged())
898  {
899  u.vectorize(0.0);
900  valence = 0;
901 
902  for (vv_it=mesh_.cvv_iter(*v_it); vv_it.is_valid(); ++vv_it)
903  {
904  u += mesh_.point(*vv_it);
905  ++valence;
906  }
907 
908  if (valence)
909  {
910  u *= (1.0/valence);
911  u -= mesh_.point(*v_it);
912  n = mesh_.normal(*v_it);
913  n *= (u | n);
914  u -= n;
915  }
916 
917  mesh_.property(update_, *v_it) = u;
918  }
919  }
920 
921  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
922  if (mesh_.status(*v_it).tagged())
923  mesh_.point(*v_it) += mesh_.property(update_, *v_it);
924  }
925 
926 
927  // reset tagged status
928  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
929  mesh_.status(*v_it).set_tagged(false);
930 
931 
932  // project
933  if (_use_projection)
934  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
935  if (!mesh_.status(*v_it).locked() && !mesh_.status(*v_it).feature())
936  project_to_reference(*v_it);
937 }
938 
939 
940 //-----------------------------------------------------------------------------
941 
942 
943 template <class Mesh>
944 void
946 balanace_area(unsigned int _iters, bool _use_projection)
947 {
948  typename Mesh::VIter v_it, v_end(mesh_.vertices_end());
949  typename Mesh::CVVIter vv_it;
950  typename Mesh::Scalar w, ww;
951  typename Mesh::Point u, n;
952 
953 
954  DiffGeoT<Mesh> diffgeo(mesh_);
955 
956 
957  // tag active vertices
958  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
959  {
960  bool active = ( !mesh_.status(*v_it).locked() &&
961  !mesh_.status(*v_it).feature() &&
962  !mesh_.is_boundary(*v_it) );
963 
964  // don't move neighbors of boundary vertices
965  for (vv_it=mesh_.cvv_iter(*v_it); active && vv_it.is_valid(); ++vv_it)
966  if (mesh_.is_boundary(*vv_it))
967  active = false;
968 
969  mesh_.status(*v_it).set_tagged( active );
970  }
971 
972 
973  // tag2 vertices for which area has to be computed
974  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
975  {
976  mesh_.status(*v_it).set_tagged2(false);
977  for (vv_it=mesh_.cvv_iter(*v_it); vv_it.is_valid(); ++vv_it)
978  {
979  if (mesh_.status(*vv_it).tagged())
980  {
981  mesh_.status(*v_it).set_tagged2(true);
982  break;
983  }
984  }
985  }
986 
987 
988 
989  for (unsigned int bla=0; bla<_iters; ++bla)
990  {
991  // compute vertex areas
992  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
993  if (mesh_.status(*v_it).tagged2())
994  mesh_.property(area_, *v_it) = pow(diffgeo.compute_area(*v_it), 2);
995 
996 
997 
998  // smooth
999  for (int iters=0; iters<10; ++iters)
1000  {
1001  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
1002  {
1003  if (mesh_.status(*v_it).tagged())
1004  {
1005  u.vectorize(0.0);
1006  ww = 0;
1007 
1008  for (vv_it=mesh_.cvv_iter(*v_it); vv_it.is_valid(); ++vv_it)
1009  {
1010  w = mesh_.property(area_, *vv_it);
1011  u += mesh_.point(*vv_it) * w;
1012  ww += w;
1013  }
1014 
1015  if (ww)
1016  {
1017  u *= (1.0/ww);
1018  u -= mesh_.point(*v_it);
1019  n = mesh_.normal(*v_it);
1020  n *= (u | n);
1021  u -= n;
1022 
1023  u *= 0.1;
1024  }
1025 
1026  mesh_.property(update_, *v_it) = u;
1027  }
1028  }
1029 
1030  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
1031  if (!mesh_.status(*v_it).locked() &&
1032  !mesh_.status(*v_it).feature() &&
1033  !mesh_.is_boundary(*v_it))
1034  mesh_.point(*v_it) += mesh_.property(update_, *v_it);
1035  }
1036 
1037 
1038  // project
1039  if (_use_projection)
1040  for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
1041  if (!mesh_.status(*v_it).locked() && !mesh_.status(*v_it).feature())
1042  project_to_reference(*v_it);
1043 
1044 
1045 // if (emit_progress_)
1046 // if (!Progress().step(3))
1047 // break;
1048  }
1049 }
1050 
1051 
1052 //-----------------------------------------------------------------------------
1053 
1054 
1055 template <class Mesh>
1056 void
1058 remove_caps()
1059 {
1060  typename Mesh::EdgeIter e_it, e_end(mesh_.edges_end());
1061  typename Mesh::HalfedgeHandle h;
1062  typename Mesh::Scalar a0, a1, amin, aa(cos(170.0 * M_PI / 180.0));
1063  typename Mesh::VHandle v, vb, vd;
1064  typename Mesh::FHandle fb, fd;
1065  typename Mesh::Point a, b, c, d;
1066 
1067 
1068  // handle Nastran PIDs for edge flips
1070  mesh_.get_property_handle(pids, "Nastran PIDs");
1071 
1072 
1073  for (e_it=mesh_.edges_begin(); e_it!=e_end; ++e_it)
1074  {
1075  if (!mesh_.status(*e_it).locked() &&
1076  mesh_.is_flip_ok(*e_it))
1077  {
1078  h = mesh_.halfedge_handle(*e_it, 0);
1079  a = mesh_.point(mesh_.to_vertex_handle(h));
1080 
1081  h = mesh_.next_halfedge_handle(h);
1082  b = mesh_.point(vb=mesh_.to_vertex_handle(h));
1083 
1084  h = mesh_.halfedge_handle(*e_it, 1);
1085  c = mesh_.point(mesh_.to_vertex_handle(h));
1086 
1087  h = mesh_.next_halfedge_handle(h);
1088  d = mesh_.point(vd=mesh_.to_vertex_handle(h));
1089 
1090  a0 = ( (a-b).normalize() | (c-b).normalize() );
1091  a1 = ( (a-d).normalize() | (c-d).normalize() );
1092 
1093  if (a0 < a1) { amin = a0; v = vb; }
1094  else { amin = a1; v = vd; }
1095 
1096  // is it a cap?
1097  if (amin < aa)
1098  {
1099  // feature edge and feature vertex -> seems to be intended
1100  if (mesh_.status(*e_it).feature() && mesh_.status(v).feature())
1101  continue;
1102 
1103  // handle PIDs: flip = split + collapse
1104  if (pids.is_valid())
1105  {
1106  fb = mesh_.face_handle(mesh_.halfedge_handle(*e_it, 0));
1107  fd = mesh_.face_handle(mesh_.halfedge_handle(*e_it, 1));
1108 
1109  if (v == vb)
1110  mesh_.property(pids, fb) = mesh_.property(pids, fd);
1111  else
1112  mesh_.property(pids, fd) = mesh_.property(pids, fb);
1113  }
1114 
1115  // project v onto feature edge
1116  if (mesh_.status(*e_it).feature())
1117  mesh_.set_point(v, (a+c)*0.5);
1118 
1119  // flip
1120  mesh_.flip(*e_it);
1121  }
1122  }
1123  }
1124 }
1125 
1126 
1127 //=============================================================================
1128 } // namespace Remeshing
1129 //=============================================================================
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
NearestNeighbor nearest(const Point &_p) const
Return handle of the nearest neighbor face.
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:235
void growVertexSelection(MeshT *_mesh)
Grow vertex selection.
void prepare_vertex_selection()
prepare for remeshing only selected vertices (if no vertex was selected, remesh whole mesh) ...
Kernel::Scalar Scalar
Scalar type.
Definition: PolyMeshT.hh:110
void prepare_face_selection()
prepare for remeshing only vertices which are fully surrounded by selected faces (if no face was sele...
Kernel::ConstVertexFaceIter ConstVertexFaceIter
Circulator.
Definition: PolyMeshT.hh:176
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
Kernel::Normal Normal
Normal type.
Definition: PolyMeshT.hh:114
Functions for selection on a mesh.
Vec::value_type distPointTriangle(const Vec &_p, const Vec &_v0, const Vec &_v1, const Vec &_v2, Vec &_nearestPoint)
distance from point _p to triangle (_v0, _v1, _v2)
Definition: Algorithms.hh:326
void clearVertexSelection(MeshT *_mesh)
Set all vertices to unselected.
void push_back(Handle _h)
Add a handle to the BSP.
void reserve(size_t _n)
Reserve memory for _n entries.
bool baryCoord(const VectorT< Scalar, 3 > &_p, const VectorT< Scalar, 3 > &_u, const VectorT< Scalar, 3 > &_v, const VectorT< Scalar, 3 > &_w, VectorT< Scalar, 3 > &_result)
Definition: Algorithms.cc:83
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
void build(unsigned int _max_handles, unsigned int _max_depth)
void update_normals()
Compute normals for all primitives.
VertexHandle split(EdgeHandle _eh, const Point &_p)
Edge split (= 2-to-4 split)
Definition: TriMeshT.hh:267