Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
BoundarySnappingT.cc
Go to the documentation of this file.
1 
2 /*===========================================================================*\
3  * *
4  * OpenMesh *
5  * Copyright (c) 2001-2015, RWTH-Aachen University *
6  * Department of Computer Graphics and Multimedia *
7  * All rights reserved. *
8  * www.openflipper.org *
9  * *
10  *---------------------------------------------------------------------------*
11  * This file is part of OpenFlipper. *
12  *---------------------------------------------------------------------------*
13  * *
14  * Redistribution and use in source and binary forms, with or without *
15  * modification, are permitted provided that the following conditions *
16  * are met: *
17  * *
18  * 1. Redistributions of source code must retain the above copyright notice, *
19  * this list of conditions and the following disclaimer. *
20  * *
21  * 2. Redistributions in binary form must reproduce the above copyright *
22  * notice, this list of conditions and the following disclaimer in the *
23  * documentation and/or other materials provided with the distribution. *
24  * *
25  * 3. Neither the name of the copyright holder nor the names of its *
26  * contributors may be used to endorse or promote products derived from *
27  * this software without specific prior written permission. *
28  * *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
32  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
33  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
34  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
35  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
36  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
37  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
38  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
39  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
40  * *
41  \*===========================================================================*/
42 
43 /*===========================================================================*\
44  * *
45  * $Revision$ *
46  * $Date$ *
47  * *
48  \*===========================================================================*/
49 
53 //=============================================================================
54 //
55 // CLASS MeshFixing - IMPLEMENTATION
56 //
57 //=============================================================================
58 
59 #define BOUNDARYSNAPPING_CC
60 
61 //== INCLUDES =================================================================
62 
63 #include "BoundarySnappingT.hh"
64 
65 //== NAMESPACE ===============================================================
66 
67 
68 //== IMPLEMENTATION ==========================================================
69 
70 
71 template<class MeshT>
73 mesh_(_mesh)
74 {
75 }
76 
77 template<typename MeshT>
78 bool sort_less_pair_second(const std::pair<typename MeshT::VertexHandle,double> &lhs,const std::pair<typename MeshT::VertexHandle,double> &rhs)
79 {
80  return lhs.second < rhs.second;
81 }
82 
83 template<class MeshT>
84 void BoundarySnappingT<MeshT>::snap(double _epsilon)
85 {
86  std::vector<typename MeshT::VertexHandle> v_boundary;
87 
88  // collect all boundary vertices
89  for (typename MeshT::VertexIter v_iter = mesh_.vertices_begin(); v_iter != mesh_.vertices_end(); ++v_iter)
90  if (mesh_.is_boundary(*v_iter) && mesh_.status(*v_iter).selected())
91  v_boundary.push_back(*v_iter);
92 
93  //two maps
94  // vertexDistMap saves the vertex and his distances as pairs
95  // vertexVertexMap saves the vertices of a vertex in range and the distances
96  std::vector< std::pair<typename MeshT::VertexHandle,double> > vertexDistMap;
97  std::map<typename MeshT::VertexHandle,std::vector<std::pair<typename MeshT::VertexHandle,double> > > vertexVertexMap;
98 
99  // get all boundary vertices in range and save them into the maps
100  for (typename std::vector< typename MeshT::VertexHandle >::iterator oIter = v_boundary.begin(); oIter != v_boundary.end(); ++oIter)
101  {
102  typename MeshT::Point pos = mesh_.point(*oIter);
103  if (!mesh_.status(*oIter).deleted())
104  {
105  std::vector< std::pair<typename MeshT::VertexHandle,double> > verticesInRange;
106 
107  //collect all vertices in range
108  for (typename std::vector<typename MeshT::VertexHandle>::iterator cIter = v_boundary.begin(); cIter != v_boundary.end(); ++cIter)
109  {
110  if ( !mesh_.status(*cIter).deleted() && cIter != oIter)
111  {
112  double dist = (pos - mesh_.point(*cIter)).length();
113 
114  if ( dist <= _epsilon )
115  verticesInRange.push_back(std::make_pair(*cIter,dist));
116  }
117  }
118 
119  // sort them, so nearest vertex is on position 0 (if exist)
120  if (!verticesInRange.empty())
121  {
122  std::sort( verticesInRange.begin(),verticesInRange.end(),&sort_less_pair_second<MeshT> );
123  vertexDistMap.push_back(std::make_pair(*oIter,verticesInRange[0].second));
124  vertexVertexMap[*oIter] = verticesInRange;
125  }
126  }
127  }
128 
129  bool finished = false;
130  while(!finished)
131  {
132  finished = true;
133 
134  double min = _epsilon;
135  typename MeshT::VertexHandle v_old;//will be replaced by v_new
136  typename MeshT::VertexHandle v_new;
137  typename std::vector<std::pair<typename MeshT::VertexHandle,double> >::iterator v_oldIter = vertexDistMap.end();
138  typename std::vector<std::pair<typename MeshT::VertexHandle,double> >::iterator v_newIter;
139 
140  // find next min pair
141  for (typename std::vector<std::pair<typename MeshT::VertexHandle,double> >::iterator vd_iter = vertexDistMap.begin(); vd_iter != vertexDistMap.end(); ++vd_iter)
142  {
143  typename MeshT::VertexHandle v_1 = vd_iter->first;
144  if (v_1.is_valid() && !mesh_.status(v_1).deleted() && vertexVertexMap.find(v_1) != vertexVertexMap.end())
145  {
146  typename MeshT::VertexHandle v_2;
147  std::vector<std::pair<typename MeshT::VertexHandle,double> >& verticesInRange = vertexVertexMap[v_1];
148 
149  for (typename std::vector<std::pair<typename MeshT::VertexHandle,double> >::iterator iter = verticesInRange.begin(); iter != verticesInRange.end(); ++iter)
150  {
151  //check if v_2 shares a face with v_1
152  //if so, it is not usable
153  v_2 = iter->first;
154 
155  for(typename MeshT::VertexFaceIter vf_iter = mesh_.vf_begin(v_1); vf_iter.is_valid() && v_2.is_valid(); ++vf_iter)
156  for (typename MeshT::FaceVertexIter fv_iter = mesh_.fv_begin(*vf_iter); fv_iter.is_valid() && v_2.is_valid(); ++fv_iter)
157  if (*fv_iter == v_2)
158  v_2 = typename MeshT::VertexHandle();
159 
160  const bool validPair = v_2.is_valid() && !mesh_.status(v_2).deleted() && mesh_.is_boundary(v_2);
161 
162  //if v_2 is valid, save it, or erase it if not, because v_2 will not be valid in the future
163  if (validPair && iter->second <= min)
164  {
165  //new min pair found
166  min = iter->second;
167  v_old = v_1;
168  v_new = v_2;
169  finished = false;
170  v_oldIter = vd_iter;
171  v_newIter = iter;
172  }
173  }
174  }
175 
176  }
177  // merge, if not finished (pair found)
178  if (!finished)
179  {
180  //remove the vertex since we will proceed with it
181  vertexVertexMap[v_old].erase(v_newIter);
182  //save all faces, because faces will be added/deleted
183  std::vector<typename MeshT::FaceHandle> faces;
184  for (typename MeshT::VertexFaceIter vf_iter = mesh_.vf_begin(v_old); vf_iter.is_valid(); ++vf_iter)
185  if (!mesh_.status(*vf_iter).deleted())
186  faces.push_back(*vf_iter);
187 
188  //replace v_old with v_new by creating new faces with v_new instead of v_old if possible
189  for (typename std::vector<typename MeshT::FaceHandle>::iterator f_iter = faces.begin(); f_iter !=faces.end(); ++f_iter)
190  {
191  typename MeshT::FaceHandle fHandle = *f_iter;
192  if (!fHandle.is_valid() || mesh_.status(fHandle).deleted())
193  continue;
194 
195  //get face vertices
196  std::vector<typename MeshT::VertexHandle> f_vertices;
197  for(typename MeshT::FaceVertexIter fv_iter = mesh_.fv_begin(fHandle); fv_iter.is_valid(); ++fv_iter)
198  f_vertices.push_back( *fv_iter );
199 
200  mesh_.delete_face(fHandle,false);
201 
202  //try to add new face
203  std::vector<typename MeshT::VertexHandle> newFace_vertices(f_vertices);
204  std::replace(newFace_vertices.begin(),newFace_vertices.end(),v_old,v_new);
205  typename MeshT::FaceHandle faceH = mesh_.add_face(newFace_vertices);
206 
207  if (!faceH.is_valid())
208  {
209  //failed, try reverse direction
210  std::reverse(newFace_vertices.begin(),newFace_vertices.end());
211  faceH = mesh_.add_face(newFace_vertices);
212  if (!faceH.is_valid())
213  {
214  //failed, so add the old one
215  mesh_.add_face(f_vertices);
216  }
217  }
218  }
219  }
220  vertexDistMap.erase(v_oldIter);
221 
222  //todo: delete vertex before proceed. Now, they will be deleted at the end resulting worse snap
223  }
224  mesh_.delete_isolated_vertices();
225 
226  mesh_.garbage_collection();
227 
228 }
void snap(double _epsilon)
snaps boundary vertices
Snaps selected vertices at boundaries.