2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file CorrectedNormalCurrentComputer.ih
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
24 * Implementation of inline methods defined in CorrectedNormalCurrentComputer.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
32//////////////////////////////////////////////////////////////////////////////
34///////////////////////////////////////////////////////////////////////////////
35// IMPLEMENTATION of inline methods.
36///////////////////////////////////////////////////////////////////////////////
38///////////////////////////////////////////////////////////////////////////////
39// ----------------------- Standard services ------------------------------
41//-----------------------------------------------------------------------------
42template <typename TRealPoint, typename TRealVector>
43DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
44CorrectedNormalCurrentComputer( ConstAlias< SurfaceMesh > aMesh,
46 : myMesh( aMesh ), myUnitU( unit_u )
49//-----------------------------------------------------------------------------
50template <typename TRealPoint, typename TRealVector>
51typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
52DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
55 if ( ! myMesh.vertexNormals().empty() ) return computeMu0InterpolatedU();
56 if ( ! myMesh.faceNormals().empty() ) return computeMu0ConstantU();
57 trace.warning() << "[CorrectedNormalCurrentComputer::computeInterpolatedMu0]"
58 << " Unable to compute measures without vertex or face normals."
60 return ScalarMeasure( &myMesh, 0.0 );
63//-----------------------------------------------------------------------------
64template <typename TRealPoint, typename TRealVector>
65typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
66DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
69 if ( ! myMesh.vertexNormals().empty() ) return computeMu1InterpolatedU();
70 if ( ! myMesh.faceNormals().empty() ) return computeMu1ConstantU();
71 trace.warning() << "[CorrectedNormalCurrentComputer::computeInterpolatedMu1]"
72 << " Unable to compute measures without vertex or face normals."
74 return ScalarMeasure( &myMesh, 0.0 );
77//-----------------------------------------------------------------------------
78template <typename TRealPoint, typename TRealVector>
79typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
80DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
83 if ( ! myMesh.vertexNormals().empty() ) return computeMu2InterpolatedU();
84 if ( ! myMesh.faceNormals().empty() ) return computeMu2ConstantU();
85 trace.warning() << "[CorrectedNormalCurrentComputer::computeInterpolatedMu2]"
86 << " Unable to compute measures without vertex or face normals."
88 return ScalarMeasure( &myMesh, 0.0 );
91//-----------------------------------------------------------------------------
92template <typename TRealPoint, typename TRealVector>
93typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::TensorMeasure
94DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
97 const RealTensor zeroT { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
98 if ( ! myMesh.vertexNormals().empty() ) return computeMuXYInterpolatedU();
99 if ( ! myMesh.faceNormals().empty() ) return computeMuXYConstantU();
100 trace.warning() << "[CorrectedNormalCurrentComputer::computeInterpolatedMuXY]"
101 << " Unable to compute measures without vertex or face normals."
103 return TensorMeasure( &myMesh, zeroT );
106//-----------------------------------------------------------------------------
107template <typename TRealPoint, typename TRealVector>
108typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
109DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
110computeMu0InterpolatedU() const
112 ScalarMeasure mu0( &myMesh, 0.0 );
113 ASSERT( ! myMesh.vertexNormals().empty() );
114 auto& face_mu0 = mu0.kMeasures( 2 );
115 face_mu0.resize( myMesh.nbFaces() );
117 for ( const auto& f : myMesh.allIncidentVertices() )
119 RealPoints p( f.size() );
120 RealVectors u( f.size() );
121 for ( Index idx_v = 0; idx_v < f.size(); ++idx_v )
123 p[ idx_v ] = myMesh.positions() [ f[ idx_v ] ];
124 u[ idx_v ] = myMesh.vertexNormals()[ f[ idx_v ] ];
126 face_mu0[ idx_f++ ] = Formula::mu0InterpolatedU( p, u, myUnitU );
131//-----------------------------------------------------------------------------
132template <typename TRealPoint, typename TRealVector>
133typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
134DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
135computeMu1InterpolatedU() const
137 ScalarMeasure mu1( &myMesh, 0.0 );
138 ASSERT( ! myMesh.vertexNormals().empty() );
139 auto& face_mu1 = mu1.kMeasures( 2 );
140 face_mu1.resize( myMesh.nbFaces() );
142 for ( const auto& f : myMesh.allIncidentVertices() )
144 RealPoints p( f.size() );
145 RealVectors u( f.size() );
146 for ( Index idx_v = 0; idx_v < f.size(); ++idx_v )
148 p[ idx_v ] = myMesh.positions() [ f[ idx_v ] ];
149 u[ idx_v ] = myMesh.vertexNormals()[ f[ idx_v ] ];
151 face_mu1[ idx_f++ ] = Formula::mu1InterpolatedU( p, u, myUnitU );
156//-----------------------------------------------------------------------------
157template <typename TRealPoint, typename TRealVector>
158typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
159DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
160computeMu2InterpolatedU() const
162 ScalarMeasure mu2( &myMesh, 0.0 );
163 ASSERT( ! myMesh.vertexNormals().empty() );
164 auto& face_mu2 = mu2.kMeasures( 2 );
165 face_mu2.resize( myMesh.nbFaces() );
167 for ( const auto& f : myMesh.allIncidentVertices() )
169 RealPoints p( f.size() );
170 RealVectors u( f.size() );
171 for ( Index idx_v = 0; idx_v < f.size(); ++idx_v )
173 p[ idx_v ] = myMesh.positions() [ f[ idx_v ] ];
174 u[ idx_v ] = myMesh.vertexNormals()[ f[ idx_v ] ];
176 face_mu2[ idx_f++ ] = Formula::mu2InterpolatedU( p, u, myUnitU );
181//-----------------------------------------------------------------------------
182template <typename TRealPoint, typename TRealVector>
183typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::TensorMeasure
184DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
185computeMuXYInterpolatedU() const
187 const RealTensor zeroT { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
188 TensorMeasure muXY( &myMesh, zeroT );
189 ASSERT( ! myMesh.vertexNormals().empty() );
190 auto& face_muXY = muXY.kMeasures( 2 );
191 face_muXY.resize( myMesh.nbFaces() );
193 for ( const auto& f : myMesh.allIncidentVertices() )
195 RealPoints p( f.size() );
196 RealVectors u( f.size() );
197 for ( Index idx_v = 0; idx_v < f.size(); ++idx_v )
199 p[ idx_v ] = myMesh.positions() [ f[ idx_v ] ];
200 u[ idx_v ] = myMesh.vertexNormals()[ f[ idx_v ] ];
202 face_muXY[ idx_f++ ] = Formula::muXYInterpolatedU( p, u, myUnitU );
207//-----------------------------------------------------------------------------
208template <typename TRealPoint, typename TRealVector>
209typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
210DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
211computeMu0ConstantU() const
213 ScalarMeasure mu0( &myMesh, 0.0 );
214 ASSERT( ! myMesh.faceNormals().empty() );
215 auto& face_mu0 = mu0.kMeasures( 2 );
216 face_mu0.resize( myMesh.nbFaces() );
218 for ( const auto& f : myMesh.allIncidentVertices() )
220 RealPoints p( f.size() );
221 const RealVector& u = myMesh.faceNormal( idx_f );
222 for ( Index idx_v = 0; idx_v < f.size(); ++idx_v )
223 p[ idx_v ] = myMesh.positions() [ f[ idx_v ] ];
224 face_mu0[ idx_f ] = Formula::mu0ConstantU( p, u );
230//-----------------------------------------------------------------------------
231template <typename TRealPoint, typename TRealVector>
232typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
233DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
234computeMu1ConstantU() const
236 ScalarMeasure mu1( &myMesh, 0.0 );
237 ASSERT( ! myMesh.faceNormals().empty() );
238 auto& edge_mu1 = mu1.kMeasures( 1 );
239 edge_mu1.resize( myMesh.nbEdges() );
241 for ( Index idx_e = 0; idx_e < myMesh.nbEdges(); ++idx_e )
243 const auto& right_f = myMesh.edgeRightFaces( idx_e );
244 const auto& left_f = myMesh.edgeLeftFaces ( idx_e );
245 if ( right_f.size() == 1 && left_f.size() == 1 )
247 const auto ab = myMesh.edgeVertices( idx_e );
248 const RealPoint& xa = myMesh.position( ab.first );
249 const RealPoint& xb = myMesh.position( ab.second );
250 const RealVector& ur = myMesh.faceNormal( right_f.front() );
251 const RealVector& ul = myMesh.faceNormal( left_f.front() );
252 edge_mu1[ idx_e ] = Formula::mu1ConstantUAtEdge( xa, xb, ur, ul );
255 edge_mu1[ idx_e ] = 0.0;
260//-----------------------------------------------------------------------------
261template <typename TRealPoint, typename TRealVector>
262typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::ScalarMeasure
263DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
264computeMu2ConstantU() const
266 ScalarMeasure mu2( &myMesh, 0.0 );
267 ASSERT( ! myMesh.faceNormals().empty() );
268 auto& vertex_mu2 = mu2.kMeasures( 0 );
269 vertex_mu2.resize( myMesh.nbVertices() );
271 for ( const auto& faces_v : myMesh.allIncidentFaces() )
273 const RealPoint a = myMesh.positions()[ idx_v ];
274 std::vector< Index > faces;
275 std::vector< Index > prev;
276 std::vector< Index > next;
277 for ( auto f : faces_v )
279 const auto & vtcs = myMesh.allIncidentVertices()[ f ];
280 const auto nbv = vtcs.size();
281 Index j = std::find( vtcs.cbegin(), vtcs.cend(), idx_v ) - vtcs.cbegin();
282 if ( j == nbv ) continue;
283 faces.push_back( f );
284 prev.push_back( vtcs[ ( j + nbv - 1 ) % nbv ] );
285 next.push_back( vtcs[ ( j + nbv + 1 ) % nbv ] );
287 // Try to reorder faces as an umbrella. If this is not possible,
288 // the vertex is not a manifold point and its measure is set to
290 bool manifold = true;
291 const Index nb = faces.size();
292 for ( Index i = 1; i < nb && manifold; i++ )
294 Index j = std::find( next.cbegin() + i, next.cend(), prev[ i - 1 ] )
296 if ( j == nb ) manifold = false;
299 std::swap( faces[ i ], faces[ j ] );
300 std::swap( next [ i ], next [ j ] );
301 std::swap( prev [ i ], prev [ j ] );
304 vertex_mu2[ idx_v ] = 0.0;
307 RealVectors vu( nb );
308 for ( Index i = 0; i < nb; ++i )
309 vu[ i ] = myMesh.faceNormal( faces[ i ] );
310 vertex_mu2[ idx_v ] = Formula::mu2ConstantUAtVertex( a, vu );
317//-----------------------------------------------------------------------------
318template <typename TRealPoint, typename TRealVector>
319typename DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::TensorMeasure
320DGtal::CorrectedNormalCurrentComputer<TRealPoint, TRealVector>::
321computeMuXYConstantU() const
323 ASSERT( ! myMesh.faceNormals().empty() );
324 const RealTensor zeroT { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
325 TensorMeasure muXY( &myMesh, zeroT );
326 ASSERT( ! myMesh.faceNormals().empty() );
327 auto& edge_muXY = muXY.kMeasures( 1 );
328 edge_muXY.resize( myMesh.nbEdges() );
330 for ( Index idx_e = 0; idx_e < myMesh.nbEdges(); ++idx_e )
332 const auto& right_f = myMesh.edgeRightFaces( idx_e );
333 const auto& left_f = myMesh.edgeLeftFaces ( idx_e );
334 if ( right_f.size() == 1 && left_f.size() == 1 )
336 const auto ab = myMesh.edgeVertices( idx_e );
337 const RealPoint& xa = myMesh.position( ab.first );
338 const RealPoint& xb = myMesh.position( ab.second );
339 const RealVector& ur = myMesh.faceNormal( right_f.front() );
340 const RealVector& ul = myMesh.faceNormal( left_f.front() );
341 edge_muXY[ idx_e ] = Formula::muXYConstantUAtEdge( xa, xb, ur, ul );
344 edge_muXY[ idx_e ] = zeroT;
349///////////////////////////////////////////////////////////////////////////////
350///////////////////////////////////////////////////////////////////////////////