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 SurfaceMeshHelper.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 SurfaceMeshHelper.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
33 //////////////////////////////////////////////////////////////////////////////
35 ///////////////////////////////////////////////////////////////////////////////
36 // IMPLEMENTATION of inline methods.
37 ///////////////////////////////////////////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////////////////
40 // ----------------------- Standard services ------------------------------
42 //-----------------------------------------------------------------------------
43 template <typename TRealPoint, typename TRealVector>
44 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::SurfaceMesh
45 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
46 makeSphere( const Scalar radius, const RealPoint& center,
47 Size m, Size n, const NormalsType normals )
49 m = std::max( m, (Size)1 ); // nb latitudes (except poles)
50 n = std::max( n, (Size)3 ); // nb longitudes
51 // vertices are numbered as follows
54 // m+1 -- 2*m: second row
56 // (n-1)*m+1 -- n*m: before last row
58 const Size nbv = 2 + n * m;
59 std::vector< RealPoint > p( nbv ); // positions
60 std::vector< std::vector< Size > > faces; // faces = ( incident vertices )
61 p[ 0 ] = center + radius * RealPoint( 0.0, 0.0, -1.0 );
62 p[ m*n+1 ] = center + radius * RealPoint( 0.0, 0.0, 1.0 );
63 const auto fv = [n] (Size i, Size j) -> Size { return i * n + j + (Size)1; };
64 for ( Size i = 0; i < m; ++i )
65 for ( Size j = 0; j < n; ++j )
67 const Scalar theta = ( 2.0 * M_PI * (double) j ) / (double) n;
68 const Scalar phi = ( M_PI * (double) (i+1) ) / (double) (m+1) - 0.5 * M_PI;
69 p[ fv( i, j ) ] = center + radius * RealPoint( cos( theta ) * cos( phi ),
70 sin( theta ) * cos( phi ),
73 for ( Size j = 0; j < n; ++j )
74 faces.push_back( std::vector< Size > { 0u, fv( 0, (j+1) % n ), fv( 0, j ) } );
75 for ( Size i = 0; i < m-1; ++i )
76 for ( Size j = 0; j < n; ++j )
78 faces.push_back( std::vector< Size >
79 { fv( i, j ), fv( i, (j+1) % n ),
80 fv( i+1, (j+1) % n ), fv( i+1, j ) } );
82 for ( Size j = 0; j < n; ++j )
83 faces.push_back( std::vector< Size > { fv( m-1, j ), fv( m-1, (j+1) % n ), m*n+(Size)1 } );
84 SurfaceMesh smesh( p.cbegin(), p.cend(), faces.cbegin(), faces.cend() );
85 if ( normals == NormalsType::VERTEX_NORMALS )
87 std::vector< RealVector > vnormals( nbv );
88 for ( Size k = 0; k < nbv; ++k )
89 vnormals[ k ] = ( p[ k ] - center ).getNormalized();
90 smesh.setVertexNormals( vnormals.cbegin(), vnormals.cend() );
92 else if ( normals == NormalsType::FACE_NORMALS )
94 std::vector< RealVector > fnormals( smesh.nbFaces() );
95 for ( Size k = 0; k < fnormals.size(); ++k )
96 fnormals[ k ] = ( smesh.faceCentroid( k ) - center ).getNormalized();
97 smesh.setFaceNormals( fnormals.cbegin(), fnormals.cend() );
102 //-----------------------------------------------------------------------------
103 template <typename TRealPoint, typename TRealVector>
104 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
105 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
106 sphereMeanCurvatures( const Scalar radius, Size m, Size n )
108 n = std::max( n, (Size)1 ); // nb latitudes (except poles)
109 m = std::max( m, (Size)3 ); // nb longitudes
110 // vertices are numbered as follows
113 // m+1 -- 2*m: second row
115 // (n-1)*m+1 -- n*m: before last row
117 const Size nbv = 2 + n * m;
118 return Scalars( nbv, 1.0 / radius );
121 //-----------------------------------------------------------------------------
122 template <typename TRealPoint, typename TRealVector>
123 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
124 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
125 sphereGaussianCurvatures( const Scalar radius, Size m, Size n )
127 n = std::max( n, (Size)1 ); // nb latitudes (except poles)
128 m = std::max( m, (Size)3 ); // nb longitudes
129 // vertices are numbered as follows
132 // m+1 -- 2*m: second row
134 // (n-1)*m+1 -- n*m: before last row
136 const Size nbv = 2 + n * m;
137 return Scalars( nbv, 1.0 / ( radius * radius ) );
140 //-----------------------------------------------------------------------------
141 template <typename TRealPoint, typename TRealVector>
142 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
143 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
144 sphereFirstPrincipalCurvatures( const Scalar radius, Size m, Size n )
146 n = std::max( n, (Size)1 ); // nb latitudes (except poles)
147 m = std::max( m, (Size)3 ); // nb longitudes
148 // vertices are numbered as follows
151 // m+1 -- 2*m: second row
153 // (n-1)*m+1 -- n*m: before last row
155 const Size nbv = 2 + n * m;
156 return Scalars( nbv, 1.0 / radius );
159 //-----------------------------------------------------------------------------
160 template <typename TRealPoint, typename TRealVector>
161 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
162 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
163 sphereSecondPrincipalCurvatures( const Scalar radius, Size m, Size n )
165 n = std::max( n, (Size)1 ); // nb latitudes (except poles)
166 m = std::max( m, (Size)3 ); // nb longitudes
167 // vertices are numbered as follows
170 // m+1 -- 2*m: second row
172 // (n-1)*m+1 -- n*m: before last row
174 const Size nbv = 2 + n * m;
175 return Scalars( nbv, 1.0 / radius );
178 //-----------------------------------------------------------------------------
179 template <typename TRealPoint, typename TRealVector>
180 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::RealVectors
181 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
182 sphereFirstPrincipalDirections( const Scalar , Size m, Size n )
184 // since the sphere is made of umbilic points, returned directions
185 // are arbitrary tangent vectors. Here we return latitude vectors.
186 n = std::max( n, (Size)1 ); // nb latitudes (except poles)
187 m = std::max( m, (Size)3 ); // nb longitudes
188 // vertices are numbered as follows
191 // m+1 -- 2*m: second row
193 // (n-1)*m+1 -- n*m: before last row
195 const Size nbv = 2 + n * m;
196 std::vector< RealVector > d1( nbv ); // directions
197 d1[ 0 ] = RealVector( 0.0, 1.0, 0.0 );
198 d1[ m*n+1 ] = RealVector( 0.0, 1.0, 0.0 );
199 const auto fv = [n] (Size i, Size j) -> Size { return i * n + j + (Size)1; };
200 for ( Size i = 0; i < m; ++i )
201 for ( Size j = 0; j < n; ++j )
203 const Scalar theta = ( 2.0 * M_PI * (double) j ) / (double) n;
204 d1[ fv( i, j ) ] = RealVector( -sin( theta ), cos( theta ), 0.0 );
209 //-----------------------------------------------------------------------------
210 template <typename TRealPoint, typename TRealVector>
211 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::RealVectors
212 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
213 sphereSecondPrincipalDirections( const Scalar , Size m, Size n )
215 // since the sphere is made of umbilic points, returned directions
216 // are arbitrary tangent vectors. Here we return latitude vectors.
217 n = std::max( n, (Size)1 ); // nb latitudes (except poles)
218 m = std::max( m, (Size)3 ); // nb longitudes
219 // vertices are numbered as follows
222 // m+1 -- 2*m: second row
224 // (n-1)*m+1 -- n*m: before last row
226 const Size nbv = 2 + n * m;
227 std::vector< RealVector > d2( nbv ); // directions
228 d2[ 0 ] = RealVector( 1.0, 0.0, 0.0 );
229 d2[ m*n+1 ] = RealVector( -1.0, 0.0, 0.0 );
230 const auto fv = [n] (Size i, Size j) -> Size { return i * n + j + (Size)1; };
231 for ( Size i = 0; i < m; ++i )
232 for ( Size j = 0; j < n; ++j )
234 const Scalar theta = ( 2.0 * M_PI * (double) j ) / (double) n;
235 const Scalar phi = ( M_PI * (double) (i+1) ) / (double) (m+1) - 0.5 * M_PI;
236 d2[ fv( i, j ) ] = RealVector( -cos( theta ) * sin( phi ),
237 -sin( theta ) * sin( phi ), cos( phi ) );
242 //-----------------------------------------------------------------------------
243 template <typename TRealPoint, typename TRealVector>
244 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::SurfaceMesh
245 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
246 makeLantern( const Scalar radius, const Scalar height, const RealPoint& center,
247 Size m, Size n, const NormalsType normals )
249 m = std::max( m, (Size)2 ); // nb latitudes
250 n = std::max( n, (Size)3 ); // nb longitudes
251 // vertices are numbered as follows
252 // 0 -- m-1: first row
253 // m -- 2m-1: second row (shifted)
255 // (n-1)*m -- nm-1: last row
256 const Size nbv = n * m;
257 std::vector< RealPoint > p( nbv ); // positions
258 std::vector< std::vector< Size > > faces; // faces = ( incident vertices )
259 const auto fv = [n] (Size i, Size j) -> Size { return i * n + j; };
260 for ( Size i = 0; i < m; ++i )
261 for ( Size j = 0; j < n; ++j )
263 const Scalar theta = ( i % 2 == 0 )
264 ? ( 2.0 * M_PI * (double) j ) / (double) n
265 : ( 2.0 * M_PI * ( 0.5 + (double) j ) ) / (double) n;
266 const Scalar h = height * ( (double) i / (double) (m-1) - 0.5 );
267 p[ fv( i, j ) ] = center + RealPoint( radius * cos( theta ),
268 radius * sin( theta ),
271 for ( Size i = 0; i < m-1; ++i )
272 for ( Size j = 0; j < n; ++j )
275 faces.push_back( std::vector< Size >
276 { fv( i, j ), fv( i, (j+1) % n ), fv( i+1, j ) } );
277 faces.push_back( std::vector< Size >
278 { fv( i, (j+1) % n ), fv( i+1, (j+1) % n ), fv( i+1, j )} );
282 faces.push_back( std::vector< Size >
283 { fv( i, j ), fv( i+1, (j+1)%n ), fv( i+1, j ) } );
284 faces.push_back( std::vector< Size >
285 { fv( i+1, (j+1)%n ), fv( i, j ), fv( i, (j+1) % n ) } );
287 SurfaceMesh smesh( p.cbegin(), p.cend(), faces.cbegin(), faces.cend() );
288 if ( normals == NormalsType::VERTEX_NORMALS )
290 std::vector< RealVector > vnormals( nbv );
291 for ( Size k = 0; k < nbv; ++k )
293 RealVector _n = p[ k ] - center;
295 vnormals[ k ] = _n.getNormalized();
297 smesh.setVertexNormals( vnormals.cbegin(), vnormals.cend() );
299 else if ( normals == NormalsType::FACE_NORMALS )
301 std::vector< RealVector > fnormals( smesh.nbFaces() );
302 for ( Size k = 0; k < fnormals.size(); ++k )
304 RealVector _n = smesh.faceCentroid( k ) - center;
306 fnormals[ k ] = _n.getNormalized();
308 smesh.setFaceNormals( fnormals.cbegin(), fnormals.cend() );
313 //-----------------------------------------------------------------------------
314 template <typename TRealPoint, typename TRealVector>
315 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
316 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
317 lanternMeanCurvatures( const Scalar radius, Size m, Size n )
319 n = std::max( n, (Size)2 ); // nb latitudes
320 m = std::max( m, (Size)3 ); // nb longitudes
321 const Size nbv = n * m;
322 return Scalars( nbv, 1.0 / ( 2.0 * radius ) );
325 //-----------------------------------------------------------------------------
326 template <typename TRealPoint, typename TRealVector>
327 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
328 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
329 lanternGaussianCurvatures( const Scalar radius, Size m, Size n )
331 (void)radius; //unused param.
332 n = std::max( n, (Size)2 ); // nb latitudes
333 m = std::max( m, (Size)3 ); // nb longitudes
334 const Size nbv = n * m;
335 return Scalars( nbv, 0.0 );
338 //-----------------------------------------------------------------------------
339 template <typename TRealPoint, typename TRealVector>
340 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
341 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
342 lanternFirstPrincipalCurvatures( const Scalar radius, Size m, Size n )
344 (void)radius; //unused param.
345 m = std::max( m, (Size)2 ); // nb latitudes
346 n = std::max( n, (Size)3 ); // nb longitudes
347 // vertices are numbered as follows
348 // 0 -- m-1: first row
349 // m -- 2m-1: second row (shifted)
351 // (n-1)*m -- nm-1: last row
352 const Size nbv = n * m;
353 return Scalars( nbv, 0.0 );
356 //-----------------------------------------------------------------------------
357 template <typename TRealPoint, typename TRealVector>
358 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
359 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
360 lanternSecondPrincipalCurvatures( const Scalar radius, Size m, Size n )
362 (void)radius; //unused param.
363 m = std::max( m, (Size)2 ); // nb latitudes
364 n = std::max( n, (Size)3 ); // nb longitudes
365 // vertices are numbered as follows
366 // 0 -- m-1: first row
367 // m -- 2m-1: second row (shifted)
369 // (n-1)*m -- nm-1: last row
370 const Size nbv = n * m;
371 return Scalars( nbv, 1.0 / radius );
374 //-----------------------------------------------------------------------------
375 template <typename TRealPoint, typename TRealVector>
376 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::RealVectors
377 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
378 lanternFirstPrincipalDirections( const Scalar radius, Size m, Size n )
380 (void)radius; //unused param.
381 m = std::max( m, (Size)2 ); // nb latitudes
382 n = std::max( n, (Size)3 ); // nb longitudes
383 // vertices are numbered as follows
384 // 0 -- m-1: first row
385 // m -- 2m-1: second row (shifted)
387 // (n-1)*m -- nm-1: last row
388 const Size nbv = n * m;
389 std::vector< RealVector > d1( nbv, RealVector( 0.0, 0.0, -1.0 ) ); // directions
393 //-----------------------------------------------------------------------------
394 template <typename TRealPoint, typename TRealVector>
395 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::RealVectors
396 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
397 lanternSecondPrincipalDirections( const Scalar radius, Size m, Size n )
399 (void)radius; //unused param.
400 m = std::max( m, (Size)2 ); // nb latitudes
401 n = std::max( n, (Size)3 ); // nb longitudes
402 // vertices are numbered as follows
403 // 0 -- m-1: first row
404 // m -- 2m-1: second row (shifted)
406 // (n-1)*m -- nm-1: last row
407 const Size nbv = n * m;
408 std::vector< RealVector > d2( nbv ); // directions
409 const auto fv = [n] (Size i, Size j) -> Size { return i * n + j; };
410 for ( Size i = 0; i < m; ++i )
411 for ( Size j = 0; j < n; ++j )
413 const Scalar theta = ( i % 2 == 0 )
414 ? ( 2.0 * M_PI * (double) j ) / (double) n
415 : ( 2.0 * M_PI * ( 0.5 + (double) j ) ) / (double) n;
416 d2[ fv( i, j ) ] = RealVector( -sin( theta ), cos( theta ), 0.0 );
421 //-----------------------------------------------------------------------------
422 template <typename TRealPoint, typename TRealVector>
423 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::SurfaceMesh
424 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
425 makeTorus( const Scalar big_radius, const Scalar small_radius, const RealPoint& center,
426 Size m, Size n, const int twist, const NormalsType normals )
428 m = std::max( m, (Size)3 ); // nb latitudes
429 n = std::max( n, (Size)3 ); // nb longitudes
430 // vertices are numbered as follows
431 // 0 -- m-1: first row
432 // m -- 2m-1: second row
434 // (n-1)*m -- nm-1: last row
435 const Size nbv = n * m;
436 std::vector< RealPoint > p( nbv ); // positions
437 std::vector< std::vector< Size > > faces; // faces = ( incident vertices )
438 const auto fv = [n] (Size i, Size j) -> Size { return i * n + j; };
439 for ( Size i = 0; i < m; ++i )
440 for ( Size j = 0; j < n; ++j )
442 const Scalar theta = ( 2.0 * M_PI * (double) i ) / (double) m;
443 const Scalar phi = ( 2.0 * M_PI * (double) j ) / (double) n
444 + twist * 2.0 * M_PI * (double) i / ( double ) m;
445 p[ fv( i, j ) ] = center
446 + RealPoint( ( big_radius + small_radius * cos( phi ) ) * cos( theta ),
447 ( big_radius + small_radius * cos( phi ) ) * sin( theta ),
448 small_radius * sin( phi ) );
450 for ( Size i = 0; i < m; ++i )
451 for ( Size j = 0; j < n; ++j )
453 faces.push_back( std::vector< Size >
454 { fv( i, j ), fv( (i+1)%m, j ), fv( i, (j+1) % n ) } );
455 faces.push_back( std::vector< Size >
456 { fv( i, (j+1) % n ), fv( (i+1)%m, j ), fv( (i+1)%m, (j+1) % n ) } );
458 SurfaceMesh smesh( p.cbegin(), p.cend(), faces.cbegin(), faces.cend() );
459 if ( normals == NormalsType::VERTEX_NORMALS )
461 std::vector< RealVector > vnormals( nbv );
462 for ( Size i = 0; i < m; ++i )
464 const Scalar theta = ( 2.0 * M_PI * (double) i ) / (double) m;
465 const RealPoint c = center + RealPoint( big_radius * cos( theta ),
466 big_radius * sin( theta ), 0.0 );
467 for ( Size j = 0; j < n; ++j )
468 vnormals[ fv( i, j ) ] = ( p[ fv( i, j ) ] - c ).getNormalized();
470 smesh.setVertexNormals( vnormals.cbegin(), vnormals.cend() );
472 else if ( normals == NormalsType::FACE_NORMALS )
474 std::vector< RealVector > fnormals( smesh.nbFaces() );
476 for ( Size i = 0; i < m; ++i )
478 const Scalar theta = ( 2.0 * M_PI * (double) i ) / (double) m;
479 const RealPoint c = center + RealPoint( big_radius * cos( theta ),
480 big_radius * sin( theta ), 0.0 );
481 for ( Size j = 0; j < n; ++j )
483 fnormals[ k ] = ( smesh.faceCentroid( k ) - c ).getNormalized();
484 fnormals[ k+1 ] = ( smesh.faceCentroid( k+1 ) - c ).getNormalized();
488 smesh.setFaceNormals( fnormals.cbegin(), fnormals.cend() );
493 //-----------------------------------------------------------------------------
494 template <typename TRealPoint, typename TRealVector>
495 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
496 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
497 torusMeanCurvatures( const Scalar big_radius, const Scalar small_radius,
498 Size m, Size n, const int twist )
500 m = std::max( m, (Size)3 ); // nb latitudes
501 n = std::max( n, (Size)3 ); // nb longitudes
502 const Size nbv = n * m;
503 Scalars hvalues( 2*nbv );
504 // H = - ( R + 2r cos phi ) / ( 2r(R + r cos phi) )
505 // G = cos phi / ( r(R + r cos phi) )
506 auto H = [&] ( int i, int j )
508 const Scalar phi = ( 2.0 * M_PI * (double) j ) / (double) n
509 + twist * 2.0 * M_PI * (double) i / ( double ) m;
510 return ( big_radius + 2.0 * small_radius * cos( phi ) )
511 / ( 2.0 * small_radius * ( big_radius + small_radius * cos( phi ) ) );
514 for ( Size i = 0; i < m; ++i )
515 for ( Size j = 0; j < n; ++j )
517 hvalues[ f++ ] = ( H( i, j ) + H( (i+1)%m, j ) + H( i, (j+1) % n ) ) / 3.0;
518 hvalues[ f++ ] = ( H( i, (j+1)%n ) + H( (i+1)%m, j ) + H( (i+1)%m, (j+1)%n ) ) / 3.0;
523 //-----------------------------------------------------------------------------
524 template <typename TRealPoint, typename TRealVector>
525 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
526 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
527 torusGaussianCurvatures( const Scalar big_radius, const Scalar small_radius,
528 Size m, Size n, const int twist )
530 m = std::max( m, (Size)3 ); // nb latitudes
531 n = std::max( n, (Size)3 ); // nb longitudes
532 const Size nbv = n * m;
533 Scalars gvalues( 2*nbv );
534 // H = - ( R + 2r cos phi ) / ( 2r(R + r cos phi) )
535 // G = cos phi / ( r(R + r cos phi) )
536 auto G = [&] ( int i, int j )
538 const Scalar phi = ( 2.0 * M_PI * (double) j ) / (double) n
539 + twist * 2.0 * M_PI * (double) i / ( double ) m;
541 / ( small_radius * ( big_radius + small_radius * cos( phi ) ) );
544 for ( Size i = 0; i < m; ++i )
545 for ( Size j = 0; j < n; ++j )
547 gvalues[ f++ ] = ( G( i, j ) + G( (i+1)%m, j ) + G( i, (j+1) % n ) ) / 3.0;
548 gvalues[ f++ ] = ( G( i, (j+1)%n ) + G( (i+1)%m, j ) + G( (i+1)%m, (j+1)%n ) ) / 3.0;
554 //-----------------------------------------------------------------------------
555 template <typename TRealPoint, typename TRealVector>
556 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
557 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
558 torusFirstPrincipalCurvatures( const Scalar big_radius, const Scalar small_radius,
559 Size m, Size n, const int twist )
561 const auto H = torusMeanCurvatures( big_radius, small_radius, m, n, twist );
562 const auto G = torusGaussianCurvatures( big_radius, small_radius, m, n, twist );
563 // k1 = H - sqrt( fabs( H * H - G ))
564 Scalars k1( H.size() );
565 const auto compute_k1 =
566 [&] ( Size i ) { return H[ i ] - sqrt( fabs( H[ i ] * H[ i ] - G[ i ] ) ); };
567 for ( Size i = 0; i < k1.size(); ++i ) k1[ i ] = compute_k1( i );
571 //-----------------------------------------------------------------------------
572 template <typename TRealPoint, typename TRealVector>
573 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::Scalars
574 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
575 torusSecondPrincipalCurvatures( const Scalar big_radius, const Scalar small_radius,
576 Size m, Size n, const int twist )
578 const auto H = torusMeanCurvatures( big_radius, small_radius, m, n, twist );
579 const auto G = torusGaussianCurvatures( big_radius, small_radius, m, n, twist );
580 // k2 = H + sqrt( fabs( H * H - G ))
581 Scalars k2( H.size() );
582 const auto compute_k2 =
583 [&] ( Size i ) { return H[ i ] + sqrt( fabs( H[ i ] * H[ i ] - G[ i ] ) ); };
584 for ( Size i = 0; i < k2.size(); ++i ) k2[ i ] = compute_k2( i );
588 //-----------------------------------------------------------------------------
589 template <typename TRealPoint, typename TRealVector>
590 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::RealVectors
591 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
592 torusFirstPrincipalDirections( const Scalar big_radius, const Scalar small_radius,
593 Size m, Size n, const int twist )
595 (void)big_radius;//not used
599 m = std::max( m, (Size)3 ); // nb latitudes
600 n = std::max( n, (Size)3 ); // nb longitudes
601 // vertices are numbered as follows
602 // 0 -- m-1: first row
603 // m -- 2m-1: second row
605 // (n-1)*m -- nm-1: last row
606 const Size nbv = n * m;
607 std::vector< RealVector > d1( nbv ); // directions
608 const auto fv = [n] (Size i, Size j) -> Size { return i * n + j; };
609 for ( Size i = 0; i < m; ++i )
610 for ( Size j = 0; j < n; ++j )
612 const Scalar theta = ( 2.0 * M_PI * (double) i ) / (double) m;
613 d1[ fv( i, j ) ] = RealVector( sin( theta ), cos( theta ), 0.0 );
618 //-----------------------------------------------------------------------------
619 template <typename TRealPoint, typename TRealVector>
620 typename DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::RealVectors
621 DGtal::SurfaceMeshHelper<TRealPoint, TRealVector>::
622 torusSecondPrincipalDirections( const Scalar big_radius, const Scalar small_radius,
623 Size m, Size n, const int twist )
625 (void)big_radius; //not used
626 (void)small_radius; //not used
628 m = std::max( m, (Size)3 ); // nb latitudes
629 n = std::max( n, (Size)3 ); // nb longitudes
630 // vertices are numbered as follows
631 // 0 -- m-1: first row
632 // m -- 2m-1: second row
634 // (n-1)*m -- nm-1: last row
635 const Size nbv = n * m;
636 std::vector< RealVector > d2( nbv ); // directions
637 const auto fv = [n] (Size i, Size j) -> Size { return i * n + j; };
638 for ( Size i = 0; i < m; ++i )
639 for ( Size j = 0; j < n; ++j )
641 const Scalar theta = ( 2.0 * M_PI * (double) i ) / (double) m;
642 const Scalar phi = ( 2.0 * M_PI * (double) j ) / (double) n
643 + twist * 2.0 * M_PI * (double) i / ( double ) m;
644 d2[ fv( i, j ) ] = RealVector( -( sin( phi ) ) * cos( theta ),
645 -( sin( phi ) ) * sin( theta ),
651 ///////////////////////////////////////////////////////////////////////////////
652 ///////////////////////////////////////////////////////////////////////////////