Developer Documentation
Loading...
Searching...
No Matches
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
71namespace MeshFunctions {
72
73//== IMPLEMENTATION ==========================================================
74
75template < typename MeshT , typename VectorT >
76bool 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
114template < typename MeshT , typename VectorT >
115bool 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
138template < typename MeshT , typename VectorT >
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
155template < typename MeshT >
156bool 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
167template <class MeshT , typename VectorT >
168bool
169cut_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
190template < typename MeshT >
191double
192calc_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
208template < typename MeshT >
209double
210calc_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
230template< typename MeshT >
231void 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
268template< typename MeshT >
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//=============================================================================
Functions for modifying a Mesh.
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x',y',z',0) = A * (x,y,z,0)
bool invert()
matrix inversion (returns true on success)
void transpose()
transpose matrix
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x',y',z',1) = M * (x,y,z,1)
PointT normal(HalfFaceHandle _hfh) const
VertexHandle from_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge starts from.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.
VectorT< double, 3 > Vec3d
Definition VectorT.hh:121
Namespace providing different Mesh editing functions.
double calc_angle_around(const MeshT &_mesh, const typename MeshT::VertexHandle &_vh)
bool get_boundary(MeshT &_mesh, typename MeshT::VertexHandle _vh, std::vector< std::pair< VectorT, typename MeshT::VertexHandle > > &_boundary)
void transformHandleVertices(ACG::Matrix4x4d _matrix, MeshT &_mesh)
bool neighbour(const MeshT &_mesh, const typename MeshT::FaceHandle &_fh1, const typename MeshT::FaceHandle &_fh2)
void smooth_boundary(MeshT &_mesh, typename MeshT::VertexHandle _vh)
void transformMesh(ACG::Matrix4x4d _matrix, MeshT &_mesh)
bool cut_face(const VectorT &_porigin, const VectorT &_pnormal, const MeshT &_mesh, const typename MeshT::FaceHandle &_fh)
double calc_area(const MeshT &_mesh)
T sane_aarg(T _aarg)
Trigonometry/angles - related.
Definition MathDefs.hh:122