Developer Documentation
MeshFunctionsT_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 
45 
46 
47 //=============================================================================
48 //
49 // IMPLEMENTATION
50 //
51 //=============================================================================
52 
53 #define MESHFUNCTIONS_C
54 
55 //== INCLUDES =================================================================
56 
57 #include "MeshFunctions.hh"
58 
59 #include <ACG/Geometry/Algorithms.hh>
60 #include "Math_Tools/Math_Tools.hh"
61 
62 #include <set>
63 
64 #include <iostream>
65 
66 #include <OpenMesh/Core/Geometry/MathDefs.hh>
68 
69 //== NAMESPACES ===============================================================
70 
71 namespace MeshFunctions {
72 
73 //== IMPLEMENTATION ==========================================================
74 
75 template < typename MeshT , typename VectorT >
76 bool get_boundary(MeshT& _mesh,
77  typename MeshT::VertexHandle _vh,
78  std::vector< std::pair< VectorT , typename MeshT::VertexHandle > >& _boundary)
79 {
80  _boundary.clear();
81  typename MeshT::VertexHandle last = _vh;
82  const typename MeshT::VertexHandle begin = _vh;
83 
84  std::set< typename MeshT::VertexHandle > set;
85 
86  //walk along boundary
87  do {
88  //insert current Vertex (which is on boundary to set (needed to detect loops)
89  set.insert( _vh );
90 
91  // store the current vertex in the boundary list
92  _boundary.push_back(std::pair< VectorT , typename MeshT::VertexHandle > ( (VectorT)_mesh.point(_vh) , _vh ) );
93 
94  // iterate over all outgoing halfedges of the current vertex to find next one
95  for (typename MeshT::VertexOHalfedgeIter vohe_it(_mesh,_vh); vohe_it.is_valid() ; ++vohe_it) {
96 
97  //if vertex is on the boundary use it as the next one (if its not the one, we are comming from)
98  if ( _mesh.is_boundary(*vohe_it) && ( _mesh.to_vertex_handle(*vohe_it) != last ) ) {
99  last = _vh;
100  _vh = _mesh.to_vertex_handle(*vohe_it);
101  break;
102  }
103  }
104  // stop if we find a vertex which is already in the list (can also detect partial loops)
105  } while ( set.count( _vh ) == 0 );
106 
107  if ( begin != _vh ) {
108  std::cout << "Warning in ( GeometryFunctions.cc get_boundary ) : boundary loop may be partial ( start- != endpoint ) " << std::endl;
109  }
110 
111  return true;
112 }
113 
114 template < typename MeshT , typename VectorT >
115 bool get_boundary(MeshT& _mesh,
116  std::vector< std::pair< VectorT , typename MeshT::VertexHandle > >& _boundary)
117 {
118  typename MeshT::VertexHandle vh;
119 
120  // Search for one Vertex on boundary
121  bool found = false;
122  for (typename MeshT::HalfedgeIter he_it=_mesh.halfedges_begin() ; he_it != _mesh.halfedges_end() ; ++he_it) {
123  if ( _mesh.is_boundary(he_it) ) {
124  vh = _mesh.from_vertex_handle(he_it);
125  found = true;
126  break;
127  }
128  }
129 
130  if ( found )
131  return get_boundary(_mesh , vh , _boundary);
132  else {
133  std::cerr << "Did not find Mesh boundary!! ( GeometryFunctions.cc get_boundary )" << std::endl;
134  return false;
135  }
136 }
137 
138 template < typename MeshT , typename VectorT >
139 void smooth_boundary(MeshT& _mesh,
140  typename MeshT::VertexHandle _vh)
141 {
142  std::vector< std::pair< VectorT , typename MeshT::VertexHandle > > boundary;
143 
144  //get the boundary
145  get_boundary (_mesh , _vh , boundary);
146 
147  for (uint i = 1 ; i <= boundary.size() ; ++i ) {
148  _mesh.point( boundary[ i % boundary.size() ].second ) = ( boundary[ ( i - 1) % boundary.size() ].first
149  + boundary[ ( i ) % boundary.size() ].first * 2.0
150  + boundary[ ( i + 1) % boundary.size() ].first ) * 0.25;
151 
152  }
153 }
154 
155 template < typename MeshT >
156 bool neighbour(const MeshT& _mesh ,
157  const typename MeshT::FaceHandle& _fh1 ,
158  const typename MeshT::FaceHandle& _fh2 )
159 {
160  for ( typename MeshT::FaceFaceIter ff_it(_mesh,_fh1) ; ff_it ; ++ff_it)
161  if (*ff_it == _fh2)
162  return true;
163  return false;
164 }
165 
166 
167 template <class MeshT , typename VectorT >
168 bool
169 cut_face(const VectorT& _porigin,
170  const VectorT& _pnormal,
171  const MeshT& _mesh,
172  const typename MeshT::FaceHandle& _fh)
173 {
174  typename MeshT::ConstFaceVertexIter fv_it = _mesh.cfv_iter(_fh);
175  const VectorT p0 = _mesh.point( fv_it);
176  const VectorT p1 = _mesh.point(++fv_it);
177  const VectorT p2 = _mesh.point(++fv_it);
178 
179  unsigned int npos(0), nneg(0);
180 
181  if( ACG::Geometry::distPointPlane< VectorT , double >( _porigin, _pnormal, p0) > 0 ) ++npos; else ++nneg;
182  if( ACG::Geometry::distPointPlane< VectorT , double >( _porigin, _pnormal, p1) > 0 ) ++npos; else ++nneg;
183  if( ACG::Geometry::distPointPlane< VectorT , double >( _porigin, _pnormal, p2) > 0 ) ++npos; else ++nneg;
184 
185 
186  if( npos && nneg ) return true;
187  else return false;
188 }
189 
190 template < typename MeshT >
191 double
192 calc_area( const MeshT& _mesh)
193 {
194  double area = 0.0;
195  for ( typename MeshT::ConstFaceIter f_it = _mesh.faces_begin() ; f_it != _mesh.faces_end() ; ++f_it) {
196  typename MeshT::ConstFaceVertexIter fv_it = _mesh.cfv_iter(f_it);
197  const ACG::Vec3d vertex1 = (ACG::Vec3d)_mesh.point( fv_it );
198  const ACG::Vec3d vertex2 = (ACG::Vec3d)_mesh.point( ++fv_it );
199  const ACG::Vec3d vertex3 = (ACG::Vec3d)_mesh.point( ++fv_it );
200 
201  area += ((vertex1 - vertex2) % (vertex3-vertex2)).norm();
202  }
203 
204  return (0.5 * area);
205 
206 }
207 
208 template < typename MeshT >
209 double
210 calc_angle_around( const MeshT& _mesh , const typename MeshT::VertexHandle& _vh)
211 {
212  double angle = 0.0;
213 
214  const typename MeshT::Point p0 = _mesh.point(_vh);
215 
216  typename MeshT::ConstVertexOHalfedgeIter voh_it(_mesh,_vh);
217  typename MeshT::ConstVertexOHalfedgeIter nx_voh_it = voh_it;
218 
219  ++nx_voh_it;
220 
221  for ( ; voh_it; ++voh_it , ++nx_voh_it) {
222  const typename MeshT::Point edge_1 = MathTools::sane_normalized( _mesh.point(_mesh.to_vertex_handle(voh_it)) - p0);
223  const typename MeshT::Point edge_2 = MathTools::sane_normalized( (_mesh.point(_mesh.to_vertex_handle(nx_voh_it))) - p0);
224  angle += acos(OpenMesh::sane_aarg(edge_1 | edge_2));
225  }
226 
227  return angle;
228 }
229 
230 template< typename MeshT >
231 void transformMesh(ACG::Matrix4x4d _matrix , MeshT& _mesh) {
232 
233  // Get the inverse matrix of the transformation for the normals
234  ACG::Matrix4x4d invTranspMat = _matrix;
235 
236  // Build inverse transposed matrix of _matrix
237  invTranspMat.invert();
238  invTranspMat.transpose();
239 
240  typename MeshT::VertexIter v_it = _mesh.vertices_begin();
241  typename MeshT::VertexIter v_end = _mesh.vertices_end();
242  for (; v_it != v_end; ++v_it) {
243 
244  // Transform the mesh vertex
245  _mesh.set_point(*v_it, _matrix.transform_point(_mesh.point(*v_it)));
246 
247  // Transform the vertex normal
248  if(_mesh.has_vertex_normals()) {
249  typename MeshT::Normal n = invTranspMat.transform_vector(_mesh.normal(*v_it));
250  n.normalize();
251  _mesh.set_normal(*v_it, n);
252  }
253  }
254 
255  typename MeshT::FaceIter f_it = _mesh.faces_begin();
256  typename MeshT::FaceIter f_end = _mesh.faces_end();
257  for (; f_it != f_end; ++f_it) {
258 
259  // Transform the face normal
260  if(_mesh.has_face_normals()) {
261  typename MeshT::Normal n = invTranspMat.transform_vector(_mesh.normal(*f_it));
262  n.normalize();
263  _mesh.set_normal(*f_it, n);
264  }
265  }
266 }
267 
268 template< typename MeshT >
269 void transformHandleVertices(ACG::Matrix4x4d _matrix , MeshT& _mesh) {
270 
271  // Get the inverse matrix of the transformation for the normals
272  ACG::Matrix4x4d invTranspMat = _matrix;
273 
274  // Build inverse transposed matrix of _matrix
275  invTranspMat.invert();
276  invTranspMat.transpose();
277 
278  typename MeshT::VertexIter v_it = _mesh.vertices_begin();
279  typename MeshT::VertexIter v_end = _mesh.vertices_end();
280  for (; v_it != v_end; ++v_it) {
281 
282  if(!_mesh.status(*v_it).is_bit_set(HANDLEAREA)) continue;
283 
284  // Transform the mesh vertex
285  _mesh.set_point(*v_it, _matrix.transform_point(_mesh.point(*v_it)));
286 
287  // Transform the vertex normal
288  if(_mesh.has_vertex_normals()) {
289  typename MeshT::Normal n = invTranspMat.transform_vector(_mesh.normal(*v_it));
290  n.normalize();
291  _mesh.set_normal(*v_it, n);
292  }
293  }
294 
295  // Transform the face normal
296  if(_mesh.has_face_normals()) {
297  _mesh.update_face_normals();
298  }
299 }
300 
301 //=============================================================================
302 } // MeshFunctions Namespace
303 //=============================================================================
bool get_boundary(MeshT &_mesh, typename MeshT::VertexHandle _vh, std::vector< std::pair< VectorT, typename MeshT::VertexHandle > > &_boundary)
bool neighbour(const MeshT &_mesh, const typename MeshT::FaceHandle &_fh1, const typename MeshT::FaceHandle &_fh2)
double calc_area(const MeshT &_mesh)
void transformHandleVertices(ACG::Matrix4x4d _matrix, MeshT &_mesh)
void transpose()
transpose matrix
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x&#39;,y&#39;,z&#39;,1) = M * (x,y,z,1)
T sane_aarg(T _aarg)
Trigonometry/angles - related.
Definition: MathDefs.hh:122
void transformMesh(ACG::Matrix4x4d _matrix, MeshT &_mesh)
bool invert()
matrix inversion (returns true on success)
bool cut_face(const VectorT &_porigin, const VectorT &_pnormal, const MeshT &_mesh, const typename MeshT::FaceHandle &_fh)
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x&#39;,y&#39;,z&#39;,0) = A * (x,y,z,0)
Functions for modifying a Mesh.
void smooth_boundary(MeshT &_mesh, typename MeshT::VertexHandle _vh)
Namespace providing different Mesh editing functions.
double calc_angle_around(const MeshT &_mesh, const typename MeshT::VertexHandle &_vh)
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121