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
50template<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 (auto f_it : _mesh.faces())
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 (auto v_it : _mesh.vertices()) {
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 (auto v_it : _mesh.vertices()) {
91
92 typename MeshT::VertexHandle vh = v_it;
93
94 if (_mesh.status(v_it).tagged() )
95 for (auto vf_it : v_it.faces())
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 (auto f_it : _mesh.faces()) {
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(f_it.valence());
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 (auto v_it : _mesh.vertices())
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 (auto f_it : _mesh.faces()) {
168
169 valence.push_back( f_it.valence() );
170
171 for (auto fv_it : f_it.vertices())
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.
VertexHandle add_vertex(const VecT &_p)
Add a geometric point to the mesh.
size_t n_vertices() const override
Get number of vertices in mesh.
virtual FaceIter delete_face(FaceHandle _h)
Delete face from mesh.
virtual FaceHandle add_face(std::vector< HalfEdgeHandle > _halfedges, bool _topologyCheck=false)
Add face via incident edges.
size_t n_faces() const override
Get number of faces in mesh.