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