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