Developer Documentation
MeshRepairPluginT_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 #define MESHREPAIRPLUGINT_CC
45 
46 #include "MeshRepairPlugin.hh"
47 
48 //-----------------------------------------------------------------------------
49 
50 template<typename MeshT>
52 {
53 
54 
55  std::vector< unsigned int > valence;
56  std::vector< typename MeshT::VertexHandle > vhandles;
57 
58 
59 
60  bool selected = false;
61 
62  // Check if a face is selected
63  for (typename MeshT::FaceIter f_it = _mesh.faces_begin(); f_it != _mesh.faces_end() ; ++f_it)
64  if ( _mesh.status(*f_it).selected() ) {
65  selected = true;
66  break;
67  }
68 
69  // Two ways to go
70  // if something is selected, we have to duplicate some vertices in order to get a manifold mesh
71  if ( selected ) {
72 
73  // Tag all vertices adjacent to selected faces
74  for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
75 
76  bool tagged = false;
77 
78  for (typename MeshT::VertexFaceIter vf_it = _mesh.vf_iter(*v_it); !tagged && vf_it.is_valid(); ++vf_it)
79  if (_mesh.status(*vf_it).selected())
80  tagged = true;
81 
82  _mesh.status(*v_it).set_tagged(tagged);
83  }
84 
85  // Remember the vertex mapping for the duplication
87  _mesh.add_property(vmap);
88 
89  // duplicate vertices that are incident to tagged and un-tagged faces
90  for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
91 
92  typename MeshT::VertexHandle vh = *v_it;
93 
94  if (_mesh.status(*v_it).tagged() )
95  for (typename MeshT::VertexFaceIter vf_it = _mesh.vf_iter(*v_it); vf_it.is_valid(); ++vf_it)
96 
97  if (!_mesh.status(*vf_it).tagged()) {
98 
99  typename MeshT::Point tmpPoint = _mesh.point(*v_it);
100 
101  // Duplicate the vertex
102  vh = _mesh.add_vertex( tmpPoint );
103 
104  // The next vertex should be tagged
105  _mesh.status(vh).set_tagged(true);
106 
107  // The original vertex is already duplicated, so we don't need to do it again!
108  _mesh.status(*v_it).set_tagged(false);
109  break;
110  }
111 
112  _mesh.property(vmap, *v_it) = vh;
113  }
114 
115  // Delete the old faces and collect their information
116  for (typename MeshT::FaceIter f_it = _mesh.faces_begin(); f_it != _mesh.faces_end(); ++f_it) {
117 
118  if (_mesh.status(*f_it).selected()) {
119 
120  // Collect vertex handles
121  typename MeshT::FaceVertexIter fv_it = _mesh.fv_iter(*f_it);
122 
123  valence.push_back(_mesh.valence(*f_it));
124  while (fv_it.is_valid()) {
125  vhandles.push_back(*fv_it);
126  ++fv_it;
127  }
128 
129  // delete the corresponding face
130  _mesh.delete_face(*f_it, false);
131  }
132 
133  }
134 
135  // Rebuild the faces in the opposite order
136  std::size_t pos = 0;
137  for (std::size_t i = 0; i < valence.size(); i++) {
138 
139  std::vector<typename MeshT::VertexHandle> faceVertices;
140 
141  pos += valence[i];
142 
143  // add valence vertices in the inverse order
144  for (unsigned int j = 1; j <= valence[i]; ++j)
145  faceVertices.push_back(_mesh.property(vmap,vhandles[pos - j]) );
146 
147  _mesh.add_face(faceVertices);
148  }
149 
150  _mesh.remove_property(vmap);
151 
152  } else {
153 
154  std::vector < typename MeshT::Point > points;
155 
156  // store vertices
157  points.reserve(_mesh.n_vertices() );
158  for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it)
159  points.push_back(_mesh.point(*v_it));
160 
161  // Better approximation of vector size for storing the handles
162  const unsigned int n_VerticesPerFace = _mesh.is_trimesh() ? 3 : 4;
163 
164  // Remember vertex handles for each face and its valence
165  std::vector< typename MeshT::VertexHandle > vhandles;
166  vhandles.reserve( _mesh.n_faces() * n_VerticesPerFace);
167  for (typename MeshT::FaceIter f_it = _mesh.faces_begin(); f_it != _mesh.faces_end(); ++f_it) {
168 
169  valence.push_back( _mesh.valence(*f_it) );
170 
171  for (typename MeshT::FaceVertexIter fv_it = _mesh.fv_iter(*f_it); fv_it.is_valid(); ++fv_it)
172  vhandles.push_back(*fv_it);
173  }
174 
175  // Remove all entities from the mesh
176  _mesh.clean();
177 
178  // Restore vertices
179  for (unsigned int i = 0; i < points.size(); ++i)
180  _mesh.add_vertex(points[i]);
181 
182 
183  // Add back the faces
184  std::size_t pos = 0;
185  for (std::size_t i = 0; i < valence.size(); i++) {
186 
187  std::vector<typename MeshT::VertexHandle> faceVertices;
188 
189  pos += valence[i];
190 
191  // add valence vertices in the inverse order
192  for (unsigned int j = 1; j <= valence[i]; ++j)
193  faceVertices.push_back(vhandles[pos - j]);
194 
195  _mesh.add_face(faceVertices);
196  }
197 
198  }
199 
200 
201  _mesh.garbage_collection();
202  _mesh.update_normals();
203 }
204 
205 //-----------------------------------------------------------------------------
206 
void flipOrientation(int _objectId)
Flips the normals of all selected faces by changing the vertex order.