MeshRepairPluginT.cc 11.7 KB
Newer Older
1
2
3
4
5
#define MESHREPAIRPLUGINT_CC

#include "MeshRepairPlugin.hh"


Matthias Möller's avatar
Matthias Möller committed
6
7
//-----------------------------------------------------------------------------

8
9
10
11
12
13
14
template<typename MeshT>
inline unsigned MeshRepairPlugin::n_verticesPerFace()
{
  // Reserve for a quad mesh, might be to small!
  return 4;
}

Matthias Möller's avatar
Matthias Möller committed
15
16
//-----------------------------------------------------------------------------

17
18
19
20
21
22
template<>
inline unsigned MeshRepairPlugin::n_verticesPerFace<TriMesh>()
{
  return 3;
}

Matthias Möller's avatar
Matthias Möller committed
23
//-----------------------------------------------------------------------------
24
25
26
27
28
29

template<typename MeshT>
void MeshRepairPlugin::flipOrientationSelected(MeshT *_mesh)
{
  typename MeshT::FaceIter f_it, f_end = _mesh->faces_end();

30
  std::vector< typename MeshT::VertexHandle > handles;
31
32
33
34
35
36
37
38
39
40
41
  std::vector< uint > valence;

  handles.reserve( _mesh->n_faces() * n_verticesPerFace<MeshT>() );
  valence.reserve( _mesh->n_faces() );


  for (f_it = _mesh->faces_begin(); f_it != f_end ; ++f_it) {

    if (_mesh->status(f_it).selected())
    {
      // Collect vertex handles
42
      typename MeshT::FaceVertexIter fv_it = _mesh->fv_iter(f_it);
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62


      valence.push_back( _mesh->valence(f_it) );
      while( fv_it) {
        handles.push_back( fv_it.handle() );
        ++fv_it;
      }

      // delete the corresponding face
      _mesh->delete_face(f_it, false);
    }
  }

  // clean the mesh
  _mesh->garbage_collection();

  // read the faces
  uint pos = 0;
  for (uint i=0; i < valence.size(); i++) {

63
    std::vector< typename MeshT::VertexHandle > faceVertices;
64
65
66
67
68
69

    pos += valence[i];

    // add valence vertices in the inverse order
    for (uint j = 1 ; j <= valence[i] ; ++j )
    {
70
      typename MeshT::VertexHandle handle = handles[pos - j];
71
72
73
74
75
76
77
78
79
80
81
82
83
84

      //if vertex is not isolated, it has a face and we have to add a new vertex to prevent holes
      //between the old flipped and not flipped faces
      if (!_mesh->is_isolated(handle))
        handle = _mesh->add_vertex(_mesh->point(handle));

      faceVertices.push_back(handle);
    }

    _mesh->add_face(faceVertices);
  }

  _mesh->update_normals();
}
85

Matthias Möller's avatar
Matthias Möller committed
86
87
//-----------------------------------------------------------------------------

88
89
90
91
92
93
template<typename MeshT>
bool MeshRepairPlugin::sort_less_pair_second(const std::pair<typename MeshT::VertexHandle,double> &lhs,const std::pair<typename MeshT::VertexHandle,double> &rhs)
{
  return lhs.second < rhs.second;
}

Matthias Möller's avatar
Matthias Möller committed
94
95
//-----------------------------------------------------------------------------

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
template<typename MeshT>
void MeshRepairPlugin::snapBoundary(MeshT *_mesh, double _eps)
{
  std::vector<typename MeshT::VertexHandle> v_boundary;

  //collect all boundary vertices
  for (typename MeshT::VertexIter v_iter = _mesh->vertices_begin(); v_iter != _mesh->vertices_end(); ++v_iter)
    if (_mesh->is_boundary(v_iter) && _mesh->status(v_iter).selected())
      v_boundary.push_back(v_iter);

  //two maps
  //vertexDistMap saves the vertex and his distanceas a pair
  //vertexVertexMap saves the vertices of a vertex in range and the distances
  std::vector< std::pair<typename MeshT::VertexHandle,double> > vertexDistMap;
  std::map<typename MeshT::VertexHandle,std::vector<std::pair<typename MeshT::VertexHandle,double> > > vertexVertexMap;

  //get all boundary vertices in range and save them into the maps
  for (typename std::vector< typename MeshT::VertexHandle >::iterator oIter = v_boundary.begin(); oIter != v_boundary.end(); ++oIter)
  {
    typename MeshT::Point pos = _mesh->point(*oIter);
    if (!_mesh->status(*oIter).deleted())
    {
      std::vector< std::pair<typename MeshT::VertexHandle,double> > verticesInRange;

      //collect all vertices in range
      for (typename std::vector<typename MeshT::VertexHandle>::iterator cIter = v_boundary.begin(); cIter != v_boundary.end(); ++cIter)
      {
        if ( !_mesh->status(*cIter).deleted() && cIter != oIter)
        {
          double dist = (pos - _mesh->point(*cIter)).length();

          if ( dist <= _eps )
            verticesInRange.push_back(std::make_pair(*cIter,dist));
        }
      }

      //sort them, so nearest vertex is on position 0 (if exist)
      if (!verticesInRange.empty())
      {
        std::sort(verticesInRange.begin(),verticesInRange.end(),sort_less_pair_second<MeshT>);
        vertexDistMap.push_back(std::make_pair(*oIter,verticesInRange[0].second));
        vertexVertexMap[*oIter] = verticesInRange;
      }
    }
  }

  bool finished = false;
  while(!finished)
  {
    finished = true;

    double min = _eps;
    typename MeshT::VertexHandle v_old;//will be replaced by v_new
    typename MeshT::VertexHandle v_new;
150
151
    typename std::vector<std::pair<typename MeshT::VertexHandle,double> >::iterator v_oldIter = vertexDistMap.end();
    typename std::vector<std::pair<typename MeshT::VertexHandle,double> >::iterator v_newIter;
152
153
154
155
156

    //find next min pair
    for (typename std::vector<std::pair<typename MeshT::VertexHandle,double> >::iterator vd_iter = vertexDistMap.begin(); vd_iter != vertexDistMap.end(); ++vd_iter)
    {
      typename MeshT::VertexHandle v_1 = vd_iter->first;
157
      if (v_1.is_valid() && !_mesh->status(v_1).deleted() && vertexVertexMap.find(v_1) != vertexVertexMap.end())
158
159
160
161
162
163
      {
        typename MeshT::VertexHandle v_2;
        std::vector<std::pair<typename MeshT::VertexHandle,double> >& verticesInRange = vertexVertexMap[v_1];

        bool validPair = false;

164
        for (typename std::vector<std::pair<typename MeshT::VertexHandle,double> >::iterator iter = verticesInRange.begin(); iter != verticesInRange.end(); ++iter)
165
166
167
        {
          //check if v_2 shares a face with v_1
          //if so, it is not usable
168
          v_2 = iter->first;
169
170
171
172
173
174
175
176
177

          for(typename MeshT::VertexFaceIter vf_iter = _mesh->vf_begin(v_1); vf_iter && v_2.is_valid(); ++vf_iter)
            for (typename MeshT::FaceVertexIter fv_iter = _mesh->fv_begin(vf_iter.handle()); fv_iter && v_2.is_valid(); ++fv_iter)
              if (fv_iter.handle() == v_2)
                v_2 = typename MeshT::VertexHandle();

          validPair = v_2.is_valid() && !_mesh->status(v_2).deleted() && _mesh->is_boundary(v_2);

          //if v_2 is valid, save it, or erase it if not, because v_2 will not be valid in the future
178
          if (validPair && iter->second <= min)
179
          {
180
181
182
183
184
185
186
            //new min pair found
            min = iter->second;
            v_old = v_1;
            v_new = v_2;
            finished = false;
            v_oldIter = vd_iter;
            v_newIter = iter;
187
188
189
190
          }
        }
      }

191
    }
192
193
194
    //merge, if not finished (pair found)
    if (!finished)
    {
195
196
      //remove the vertex since we will proceed with it
      vertexVertexMap[v_old].erase(v_newIter);
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
      //save all faces, because faces will be added/deleted
      std::vector<typename MeshT::FaceHandle> faces;
      for (typename MeshT::VertexFaceIter vf_iter = _mesh->vf_begin(v_old); vf_iter; ++vf_iter)
        if (!_mesh->status(vf_iter).deleted())
          faces.push_back(vf_iter);

      //replace v_old with v_new by creating new faces with v_new instead of v_old if possible
      for (typename std::vector<typename MeshT::FaceHandle>::iterator f_iter = faces.begin(); f_iter !=faces.end(); ++f_iter)
      {
        typename MeshT::FaceHandle fHandle = *f_iter;
        if (!fHandle.is_valid() || _mesh->status(fHandle).deleted())
          continue;

        //get face vertices
        std::vector<typename MeshT::VertexHandle> f_vertices;
        for(typename MeshT::FaceVertexIter fv_iter = _mesh->fv_begin(fHandle); fv_iter; ++fv_iter)
          f_vertices.push_back( fv_iter.handle() );

        _mesh->delete_face(fHandle,false);

        //try to add new face
        std::vector<typename MeshT::VertexHandle> newFace_vertices(f_vertices);
        std::replace(newFace_vertices.begin(),newFace_vertices.end(),v_old,v_new);
        typename MeshT::FaceHandle faceH = _mesh->add_face(newFace_vertices);

        if (!faceH.is_valid())
        {
          //failed, try reverse direction
          std::reverse(newFace_vertices.begin(),newFace_vertices.end());
          faceH = _mesh->add_face(newFace_vertices);
          if (!faceH.is_valid())
228
          {
229
230
            //failed, so add the old one
            _mesh->add_face(f_vertices);
231
          }
232
233
234
        }
      }
    }
235
236
    vertexDistMap.erase(v_oldIter);
    //todo: delete vertex before proceed. Now, they will be deleted at the end resulting worse snap
237
  }
238
239
  _mesh->delete_isolated_vertices();

240
241
242
  _mesh->garbage_collection();

}
Matthias Möller's avatar
Matthias Möller committed
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

//-----------------------------------------------------------------------------
template<typename MeshT>
void MeshRepairPlugin::fixTopology(MeshT *_mesh)
{
  OpenMesh::FPropHandleT< size_t > component;
  if ( !_mesh->get_property_handle(component,"component") )
    _mesh->add_property(component, "component");

  for (typename MeshT::VertexIter v_iter = _mesh->vertices_begin(); v_iter != _mesh->vertices_end(); ++v_iter)
  {
    //unmark all faces
    for (typename MeshT::VertexFaceIter vf_iter = _mesh->vf_begin(v_iter); vf_iter; ++vf_iter)
      _mesh->property(component,vf_iter.handle()) = 0;

    size_t componentCount = 1;


    //search and isolate new components
    //shared vertices will be doublicated
    for (typename MeshT::VertexFaceIter vf_iter = _mesh->vf_begin(v_iter); vf_iter; ++vf_iter)
    {
      //get the first face in the component
      std::vector<typename MeshT::FaceHandle> checkNeighbour;
      if(_mesh->property(component,vf_iter.handle()) == 0)
      {
        _mesh->property(component,vf_iter.handle()) = componentCount;
        checkNeighbour.push_back(vf_iter.handle());
      }

      //if a reference face was found, it exists a new component
      //and a new vertex is required (except for the first component)
      typename MeshT::VertexHandle v_new;
      if (componentCount > 1 && !checkNeighbour.empty())
      {
        typename MeshT::Point p = _mesh->point(v_iter.handle());
        v_new = _mesh->add_vertex(p);
      }

      //check all adjacent faces of our reference
      while(!checkNeighbour.empty())
      {
        typename MeshT::FaceHandle face = checkNeighbour.back();
        checkNeighbour.pop_back();

        std::vector<typename MeshT::VertexHandle> f_vertices;
        //get all neighbour faces of face
        for (typename MeshT::FaceVertexIter fv_iter = _mesh->fv_begin(face); fv_iter; ++fv_iter)
        {
          f_vertices.push_back(fv_iter.handle());
          if (fv_iter.handle() != v_iter)
          {
            //find the next neighbour face over edge v_iter and fv_iter
            typename MeshT::FaceHandle nf;
            for (typename MeshT::VertexFaceIter nf_iter = _mesh->vf_begin(v_iter); nf_iter && !nf.is_valid(); ++nf_iter)
            {
              if (nf_iter.handle() != face)
                for (typename MeshT::FaceVertexIter nfv_iter = _mesh->fv_begin(nf_iter); nfv_iter && !nf.is_valid(); ++nfv_iter)
                  if (nfv_iter.handle() == fv_iter.handle())
                    nf = nf_iter.handle();
            }

            //if such a face was found, it is in the same component as the reference face
            if (nf.is_valid() && !_mesh->property(component,nf))
            {
              _mesh->property(component,nf) = componentCount;
              checkNeighbour.push_back(nf);
            }
          }
        }

        //if one face wasn't found in the component = 1 run, then it is a new component, due split it
        if (componentCount > 1 && v_new.is_valid())
        {
          std::replace(f_vertices.begin(),f_vertices.end(),v_iter.handle(),v_new);

          _mesh->delete_face(face,false);
          _mesh->add_face(f_vertices);

        }
      }

      //all faces which belongs to v_iter and inside same component found
      //the next face will be in a new component
      ++componentCount;
    }
  }

  _mesh->remove_property(component);
  _mesh->garbage_collection();
}

//-----------------------------------------------------------------------------