Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / src / mesh / cfMesh / utilities / triSurfaceTools / triSurfaceCurvatureEstimator / triSurfaceCurvatureEstimatorCalculate.C
blobcc368fc80e359929b86e513068178aada8e486c0
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | cfMesh: A library for mesh generation
4    \\    /   O peration     |
5     \\  /    A nd           | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6      \\/     M anipulation  | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9     This file is part of cfMesh.
11     cfMesh is free software; you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation; either version 3 of the License, or (at your
14     option) any later version.
16     cfMesh is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with cfMesh.  If not, see <http://www.gnu.org/licenses/>.
24 Description
26 \*---------------------------------------------------------------------------*/
28 #include "triSurfaceCurvatureEstimator.H"
29 #include "matrix3D.H"
30 #include "quadricFitting.H"
31 #include "helperFunctions.H"
32 #include "HashSet.H"
33 #include "boolList.H"
34 #include "Map.H"
35 #include "DynList.H"
37 #include "OFstream.H"
39 #include <map>
41 # ifdef USE_OMP
42 #include <omp.h>
43 # endif
45 //#define DEBUGCurvatureEstimator
47 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 namespace Foam
52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 void writeSurfaceToVTK
56     OFstream& file,
57     const triSurf& surf
60     //- write the header
61     file << "# vtk DataFile Version 3.0\n";
62     file << "vtk output\n";
63     file << "ASCII\n";
64     file << "DATASET POLYDATA\n";
66     //- write points
67     const pointField& points = surf.points();
68     file << "POINTS " << points.size() << " float\n";
69     forAll(points, pI)
70     {
71         const point& p = points[pI];
73         file << p.x() << ' ' << p.y() << ' ' << p.z() << ' ';
75         if( pI % 5 == 0 )
76             file << "\n";
77     }
79     //- write triangles
80     file << "\n";
81     file << "\nPOLYGONS " << surf.size() << " " << 4*surf.size() << endl;
82     forAll(surf, triI)
83     {
84         const labelledTri& tri = surf[triI];
85         file << 3 << " " << tri[0] << " " << tri[1] << " " << tri[2] << endl;
86     }
89 void writeSurfaceToVTK
91     OFstream& file,
92     const triSurf& surf,
93     const DynList<label>& triangles,
94     const labelHashSet& labels
97     //- write the header
98     file << "# vtk DataFile Version 3.0\n";
99     file << "vtk output\n";
100     file << "ASCII\n";
101     file << "DATASET POLYDATA\n";
103     //- write points
104     std::map<label, label> newPointLabel;
105     forAll(triangles, tI)
106     {
107         const labelledTri& tri = surf[triangles[tI]];
109         for(label pI=0;pI<3;++pI)
110         {
111             newPointLabel[tri[pI]];
112         }
113     }
115     forAllConstIter(labelHashSet, labels, it)
116         newPointLabel[it.key()];
118     const pointField& points = surf.points();
119     file << "POINTS " << label(newPointLabel.size()) << " float\n";
120     label counter(0);
121     for
122     (
123         std::map<label, label>::iterator it=newPointLabel.begin();
124         it!=newPointLabel.end();
125         ++it
126     )
127     {
128         it->second = counter++;
130         const point& p = points[it->first];
132         file << p.x() << ' ' << p.y() << ' ' << p.z() << ' ';
134         file << nl;
135     }
137     //- write triangles
138     file << "\n";
139     file << "\nPOLYGONS " << triangles.size()
140          << " " << 4*triangles.size() << endl;
141     forAll(triangles, tI)
142     {
143         const labelledTri& tri = surf[triangles[tI]];
145         file << 3
146              << " " << newPointLabel[tri[0]]
147              << " " << newPointLabel[tri[1]]
148              << " " << newPointLabel[tri[2]] << endl;
149     }
152 void writeSurfaceToVTK
154     const word& name,
155     const triSurf& surf,
156     const List<DynList<scalar, 1> >& data
159     OFstream file(name+".vtk");
161     writeSurfaceToVTK(file, surf);
163     //- write curvature fields
164     const pointField& points = surf.points();
165     file << "\n";
166     file << "\nPOINT_DATA " << points.size() << "\n";
168     file << "SCALARS Values double\n";
169     file << "LOOKUP_TABLE default\n";
170     forAll(points, pI)
171     {
172         file << data[pI][0] << " ";
174         if( pI && pI % 5 == 0 )
175             file << endl;
176     }
179 void writeSurfaceToVTK
181     const word& name,
182     const triSurf& surf,
183     const List<DynList<vector, 1> >& data
186     OFstream file(name+".vtk");
188     writeSurfaceToVTK(file, surf);
190     //- write curvature fields
191     const pointField& points = surf.points();
192     file << "\n";
193     file << "\nPOINT_DATA " << points.size() << "\n";
195     file << "VECTORS Values double\n";
196     file << "LOOKUP_TABLE default\n";
197     forAll(points, pI)
198     {
199         const vector& v = data[pI][0];
201         file << v[0] << " " << v[1] << " " << v[2] << " ";
203         if( pI && pI % 5 == 0 )
204             file << endl;
205     }
208 void triSurfaceCurvatureEstimator::calculateEdgeCurvature()
210     const pointField& points = surface_.points();
211     const edgeLongList& edges = surface_.edges();
212     const VRWGraph& pointEdges = surface_.pointEdges();
213     const VRWGraph& edgeFaces = surface_.edgeFacets();
215     edgePointCurvature_.setSize(points.size());
216     boolList featureEdge(edges.size());
218     # ifdef USE_OMP
219     # pragma omp parallel
220     # endif
221     {
222         # ifdef USE_OMP
223         # pragma omp for schedule(static, 1)
224         # endif
225         forAll(edgePointCurvature_, i)
226             edgePointCurvature_[i] = 0.0;
228         //- mark feature edges
229         # ifdef USE_OMP
230         # pragma omp for schedule(static, 1)
231         # endif
232         forAll(edgeFaces, eI)
233         {
234             if( edgeFaces.sizeOfRow(eI) != 2 )
235             {
236                 featureEdge[eI] = false;
237                 continue;
238             }
240             if(
241                  surface_[edgeFaces(eI, 0)].region() ==
242                  surface_[edgeFaces(eI, 1)].region()
243             )
244             {
245                 featureEdge[eI] = false;
246             }
247             else
248             {
249                 featureEdge[eI] = true;
250             }
251         }
253         # ifdef USE_OMP
254         # pragma omp barrier
255         # endif
257         //- loop through the points and calculate the curvature for points
258         //- attached to two feature edges
259         # ifdef USE_OMP
260         # pragma omp for schedule(dynamic, 20)
261         # endif
262         forAll(pointEdges, pI)
263         {
264             DynList<label> features;
265             forAllRow(pointEdges, pI, peI)
266             {
267                 const label edgeI = pointEdges(pI, peI);
268                 if( featureEdge[edgeI] )
269                     features.append(edgeI);
270             }
272             if( features.size() == 2 )
273             {
274                 //- calculate the curvature and store it in the map
275                 vector e1 = edges[features[0]].vec(points);
276                 const scalar d1 = mag(e1) + VSMALL;
277                 e1 /= d1;
278                 vector e2 = edges[features[1]].vec(points);
279                 const scalar d2 = mag(e2) + VSMALL;
280                 e2 /= d2;
282                 scalar cs = e1 & e2;
283                 cs = Foam::min(1.0, cs);
284                 cs = Foam::max(-1.0, cs);
286                 const scalar curv = Foam::acos(cs) / (0.5 * (d1+d2+VSMALL));
287                 edgePointCurvature_[pI] = Foam::mag(curv);
288             }
289         }
290     }
293 void triSurfaceCurvatureEstimator::calculateSurfaceCurvatures()
295     const VRWGraph& pointTriangles = surface_.pointFacets();
297     const pointField& points = surface_.points();
299     patchPositions_.setSize(surface_.size());
300     gaussianCurvature_.setSize(points.size());
301     meanCurvature_.setSize(points.size());
302     maxCurvature_.setSize(points.size());
303     minCurvature_.setSize(points.size());
304     maxCurvatureVector_.setSize(points.size());
305     minCurvatureVector_.setSize(points.size());
307     List<DynList<label, 4> > pointPatches(points.size());
309     # ifdef USE_OMP
310     # pragma omp parallel for schedule(dynamic, 40)
311     # endif
312     forAll(pointTriangles, pointI)
313     {
314         std::map<label, DynList<label> > regionTriangles;
315         Map<labelHashSet> otherLabels;
316         Map<vector> normals;
318         forAllRow(pointTriangles, pointI, ptI)
319         {
320             const label triI = pointTriangles(pointI, ptI);
321             const label regionI = surface_[triI].region();
323             if( !normals.found(regionI) )
324                 normals.insert(regionI, vector::zero);
325             if( regionTriangles.find(regionI) != regionTriangles.end() )
326                 regionTriangles.insert
327                 (
328                     std::make_pair
329                     (
330                         regionI,
331                         DynList<label>()
332                     )
333                 );
334             if( !otherLabels.found(regionI) )
335                 otherLabels.insert(regionI, labelHashSet());
337             regionTriangles[regionI].append(triI);
339             forAll(surface_[triI], tpI)
340             {
341                 const label pI = surface_[triI][tpI];
343                 if( pointI == pI )
344                     continue;
346                 otherLabels[regionI].insert(pI);
347                 normals[regionI] += surface_[triI].normal(points);
348             }
349         }
351         forAllConstIter(Map<labelHashSet>, otherLabels, it)
352         {
353             const labelHashSet& currLabels = it();
355             if( otherLabels[it.key()].size() > 5 )
356                 continue;
358             labelHashSet additionalPoints;
359             forAllConstIter(labelHashSet, currLabels, lit)
360             {
361                 const label neiPointI = lit.key();
362                 const constRow pTriangles = pointTriangles[neiPointI];
364                 forAll(pTriangles, ptI)
365                 {
366                     const labelledTri& nTri = surface_[pTriangles[ptI]];
368                     if( nTri.region() != it.key() )
369                         continue;
371                     forAll(nTri, pI)
372                         additionalPoints.insert(nTri[pI]);
373                 }
374             }
376             forAllConstIter(labelHashSet, additionalPoints, aIter)
377                 otherLabels[it.key()].insert(aIter.key());
378         }
380         forAllIter(Map<vector>, normals, nit)
381             nit() /= (Foam::mag(nit()) + VSMALL);
383         forAllConstIter(Map<labelHashSet>, otherLabels, it)
384         {
385             const labelHashSet& labels = it();
387             const label regionI = it.key();
389             //- store the patches
390             pointPatches[pointI].append(regionI);
392             //- find the position of point in the patch triangles
393             const DynList<label>& rTriangles = regionTriangles[regionI];
394             forAll(rTriangles, i)
395             {
396                 const label tI = rTriangles[i];
398                 label pos(-1);
399                 forAll(surface_[tI], j)
400                     if( surface_[tI][j] == pointI )
401                     {
402                         pos = j;
403                         break;
404                     }
406                 patchPositions_(tI, pos) = gaussianCurvature_[pointI].size();
407             }
409             //- store point coordinates
410             DynList<point> op;
412             forAllConstIter(labelHashSet, labels, lit)
413                 op.append(points[lit.key()]);
415             //- fit the quadric patch to the surface
416             quadricFitting qfit(points[pointI], normals[it.key()], op);
418             # ifdef DEBUGCurvatureEstimator
419             Info << "Point " << pointI << " in patch " << regionI
420                 << " normal " << normals[it.key()]
421                 << " evalution points " << labels
422                 << " has max curvature " << qfit.maxCurvature()
423                 << " and min curvature " << qfit.minCurvature() << endl;
424             OFstream file
425             (
426                 "point_" +
427                 help::scalarToText(pointI) +
428                 "_region_" +
429                 help::scalarToText(regionI) +
430                 "_triangles.vtk"
431             );
432             writeSurfaceToVTK(file, surface_, rTriangles, labels);
433             # endif
435             //- store curvatures
436             gaussianCurvature_[pointI].append(qfit.gaussianCurvature());
437             meanCurvature_[pointI].append(qfit.meanCurvature());
438             maxCurvature_[pointI].append(qfit.maxCurvature());
439             minCurvature_[pointI].append(qfit.minCurvature());
440             maxCurvatureVector_[pointI].append(qfit.maxCurvatureVector());
441             minCurvatureVector_[pointI].append(qfit.minCurvatureVector());
442         }
443     }
445     //- smooth curvatures using weighted Laplace
446     List<DynList<scalar, 1> > smoothMinCurv(points.size());
447     List<DynList<scalar, 1> > smoothMaxCurv(points.size());
449     # ifdef USE_OMP
450     # pragma omp parallel
451     # endif
452     {
453         for(label iteration=0;iteration<2;++iteration)
454         {
455             # ifdef USE_OMP
456             # pragma omp for schedule(static, 1)
457             # endif
458             forAll(pointTriangles, pointI)
459             {
460                 const constRow pTriangles = pointTriangles[pointI];
462                 //- find neighbouring points for each patch
463                 Map<DynList<label> > patchNeiPoints;
464                 forAll(pointPatches[pointI], ppI)
465                     patchNeiPoints.insert
466                     (
467                         pointPatches[pointI][ppI],
468                         DynList<label>()
469                     );
471                 forAll(pTriangles, ptI)
472                 {
473                     const labelledTri& tri = surface_[pTriangles[ptI]];
475                     if( !patchNeiPoints.found(tri.region()) )
476                         patchNeiPoints.insert(tri.region(), DynList<label>());
478                     forAll(tri, pI)
479                     {
480                         const label neiPointI = tri[pI];
482                         if( neiPointI == pointI )
483                             continue;
485                         patchNeiPoints[tri.region()].appendIfNotIn(neiPointI);
486                     }
487                 }
489                 smoothMinCurv[pointI].setSize(minCurvature_[pointI].size());
490                 smoothMaxCurv[pointI].setSize(maxCurvature_[pointI].size());
492                 //- update min curvature for all point patches
493                 forAll(minCurvature_[pointI], patchI)
494                 {
495                     const label cPatch = pointPatches[pointI][patchI];
497                     scalar minCurv(0.0);
498                     scalar maxCurv(0.0);
500                     const DynList<label>& neiPoints = patchNeiPoints[cPatch];
502                     if( neiPoints.size() == 0 )
503                     {
504                         smoothMinCurv[pointI][patchI] =
505                             minCurvature_[pointI][patchI];
507                         smoothMaxCurv[pointI][patchI] =
508                             maxCurvature_[pointI][patchI];
509                     }
511                     forAll(neiPoints, i)
512                     {
513                         const label neiPointI = neiPoints[i];
515                         const label pos =
516                             pointPatches[neiPointI].containsAtPosition(cPatch);
518                         minCurv += minCurvature_[neiPointI][pos];
519                         maxCurv += maxCurvature_[neiPointI][pos];
520                     }
522                     minCurv /= neiPoints.size();
523                     maxCurv /= neiPoints.size();
525                     //- store the value
526                     smoothMinCurv[pointI][patchI] =
527                         0.5 * (minCurv + minCurvature_[pointI][patchI]);
529                     smoothMaxCurv[pointI][patchI] =
530                         0.5 * (maxCurv + maxCurvature_[pointI][patchI]);
531                 }
532             }
534             # ifdef USE_OMP
535             # pragma omp barrier
537             # pragma omp for schedule(static, 1)
538             # endif
539             forAll(minCurvature_, pointI)
540             {
541                 forAll(minCurvature_[pointI], i)
542                 {
543                     minCurvature_[pointI][i] = smoothMinCurv[pointI][i];
544                     maxCurvature_[pointI][i] = smoothMaxCurv[pointI][i];
545                 }
546             }
547         }
549         # ifdef USE_OMP
550         # pragma omp barrier
551         # endif
553         //- update Gaussian and mean curvatures
554         # ifdef USE_OMP
555         # pragma omp for schedule(static, 1)
556         # endif
557         forAll(minCurvature_, pointI)
558         {
559             const DynList<scalar, 1>& minCurv = minCurvature_[pointI];
560             const DynList<scalar, 1>& maxCurv = maxCurvature_[pointI];
562             forAll(minCurv, i)
563             {
564                 gaussianCurvature_[pointI][i] = minCurv[i] * maxCurv[i];
565                 meanCurvature_[pointI][i] = 0.5 * (minCurv[i] + maxCurv[i]);
566             }
567         }
568     }
570     # ifdef DEBUGCurvatureEstimator
571     word name = "surfaceMeanCurv";
572     writeSurfaceToVTK(name, surface_, meanCurvature_);
573     writeSurfaceToVTK("surfaceGaussianCurv", surface_, gaussianCurvature_);
574     writeSurfaceToVTK("surfaceMaxCurv", surface_, maxCurvature_);
575     writeSurfaceToVTK("surfaceMinCurv", surface_, minCurvature_);
576     writeSurfaceToVTK("surfaceMaxCurvVec", surface_, maxCurvatureVector_);
577     writeSurfaceToVTK("surfaceMinCurvVec", surface_, minCurvatureVector_);
578     # endif
581 void triSurfaceCurvatureEstimator::calculateGaussianCurvature()
583     gaussianCurvature_.setSize(surface_.patches().size());
585     List<std::map<label, scalar> > magAreas(gaussianCurvature_.size());
587     forAll(surface_, triI)
588     {
589         const labelledTri& tri = surface_[triI];
590         const label region = tri.region();
592         forAll(tri, pI)
593         {
594             gaussianCurvature_[region][tri[pI]] = 2 * M_PI;
595             magAreas[region][tri[pI]] = 0.0;
596         }
597     }
599     const pointField& points = surface_.points();
600     const labelListList& pointTriangles = surface_.pointFaces();
602     forAll(surface_, triI)
603     {
604         const labelledTri& tri = surface_[triI];
605         const label region = tri.region();
607         const scalar A = mag(tri.normal(points)) + VSMALL;
609         const edgeList edges = tri.edges();
610         vectorField ev(3);
611         scalarField dv(3);
612         forAll(edges, eI)
613         {
614             ev[eI] = edges[eI].vec(points);
615             dv[eI] = mag(ev[eI]);
616             if( dv[eI] > VSMALL )
617                 ev[eI] /= dv[eI];
618         }
620         forAll(tri, pI)
621         {
622             scalar cs = ev[(pI+2)%3] & ev[pI];
623             cs = Foam::min(1.0, cs);
624             cs = Foam::max(1.0, cs);
626             gaussianCurvature_[region][tri[pI]] -= Foam::acos(-1.0 * cs);
627             magAreas[region][tri[pI]] += A;
628         }
629     }
631     //- calculate tge gaussian curvature for each vertex
632     forAll(gaussianCurvature_, patchI)
633     {
634         std::map<label, scalar>& gc = gaussianCurvature_[patchI];
635         std::map<label, scalar>& magSf = magAreas[patchI];
637         for
638         (
639             std::map<label, scalar>::iterator it = gc.begin();
640             it!=gc.end();
641             ++it
642         )
643             it->second = 3.0 * it->second / magSf[it->first];
644     }
646     //- smooth the curvature variation
647     const edgeList& edges = surface_.edges();
648     const labelListList& pointEdges = surface_.pointEdges();
649     forAll(meanCurvature_, patchI)
650     {
651         std::map<label, scalar>& gc = meanCurvature_[patchI];
653         std::map<label, scalar> newValues;
655         for(std::map<label, scalar>::iterator it=gc.begin();it!=gc.end();++it)
656         {
657             const labelList& pEdges = pointEdges[it->first];
659             scalar maxCurv(-VSMALL), minCurv(VSMALL);
660             label nNei(0);
662             forAll(pEdges, peI)
663             {
664                 const label ovI = edges[pEdges[peI]].otherVertex(it->first);
666                 if( gc.find(ovI) != gc.end() )
667                 {
668                     maxCurv = Foam::max(maxCurv, gc[ovI]);
669                     minCurv = Foam::min(minCurv, gc[ovI]);
670                     ++nNei;
671                 }
672             }
674             if( nNei != 0 )
675             {
676                 if( gc[it->first] > maxCurv )
677                 {
678                     newValues.insert
679                     (
680                         std::make_pair(it->first, 0.5*(maxCurv+gc[it->first]))
681                     );
682                 }
683                 else if( gc[it->first] >= minCurv )
684                 {
685                     newValues.insert(*it);
686                 }
687                 else
688                 {
689                     newValues.insert
690                     (
691                         std::make_pair(it->first, 0.5*(minCurv+gc[it->first]))
692                     );
693                 }
694             }
695         }
697         gc = newValues;
698     }
701 void triSurfaceCurvatureEstimator::calculateMeanCurvature()
703     const pointField& points = surface_.points();
705     meanCurvature_.setSize(surface_.patches().size());
707     List<Map<label> > nNeighbours(meanCurvature_.size());
709     const edgeList& edges = surface_.edges();
710     const labelListList& edgeFaces = surface_.edgeFaces();
712     //- calculate edge angles
713     forAll(edges, eI)
714     {
715         const labelList& eFaces = edgeFaces[eI];
717         if( eFaces.size() != 2 )
718             continue;
719         if( surface_[eFaces[0]].region() != surface_[eFaces[1]].region() )
720             continue;
722         const label region = surface_[eFaces[0]].region();
723         std::map<label, scalar>& mc = meanCurvature_[region];
724         Map<label>& nn = nNeighbours[region];
726         //- calculate normal vectors
727         vector n0 = surface_[eFaces[0]].normal(points);
728         const scalar A0 = mag(n0);
729         if( A0 > VSMALL )
730             n0 /= A0;
732         vector n1 = surface_[eFaces[1]].normal(points);
733         const scalar A1 = mag(n1);
734         if( A1 > VSMALL )
735             n1 /= A1;
737         //- calculate the cosine of the angle between the two vectors
738         scalar cs = n0 & n1;
739         cs = Foam::min(1.0, cs);
740         cs = Foam::max(-1.0, cs);
742         //- calculate and normalize the edge vector
743         vector ev = edges[eI].vec(points);
744         const scalar length = mag(ev);
745         if( length > VSMALL )
746             ev /= length;
748         //- calculate cross product of the normal vectors
749         const vector t = n0 ^ n1;
751         //- calculate the dot product between the edge vector and t
752         scalar sn = t & ev;
753         sn = Foam::min(1.0, sn);
754         sn = Foam::max(-1.0, sn);
756         //- calculate mean curvature over the edge
757         scalar Hf(0.0);
759         if( mag(sn) > VSMALL || mag(cs) > VSMALL )
760         {
761             //- calculate the angle
762             const scalar angle = Foam::atan2(sn, cs);
763             Hf += angle * length;
764         }
766         if( A0 > VSMALL || A1 > VSMALL )
767         {
768             Hf /= (A0 + A1 + VSMALL);
769             Hf *= 3.0;
770         }
772         //- store the data
773         const edge& e = edges[eI];
774         if( mc.find(e.start()) == mc.end() )
775         {
776             mc.insert(std::make_pair(e.start(), 0.0));
777             nn.insert(e.start(), 0);
778         }
779         mc[e.start()] += Hf;
780         nn[e.start()] += 1;
782         if( mc.find(e.end()) == mc.end() )
783         {
784             mc.insert(std::make_pair(e.end(), 0.0));
785             nn.insert(e.end(), 0);
786         }
787         mc[e.end()] += Hf;
788         nn[e.end()] += 1;
789     }
791     //- calculate the curvature for each vertex
792     forAll(meanCurvature_, patchI)
793     {
794         std::map<label, scalar>& mc = meanCurvature_[patchI];
795         Map<label>& nn = nNeighbours[patchI];
797         forAllIter(Map<label>, nn, it)
798         {
799             if( it() == 0 )
800             {
801                 mc[it.key()] = 0.0;
802                 continue;
803             }
805             mc[it.key()] = 0.5 * mc[it.key()] / it();
806         }
807     }
809     //- smooth the curvature variation
810     const labelListList& pointEdges = surface_.pointEdges();
811     forAll(meanCurvature_, patchI)
812     {
813         std::map<label, scalar>& mc = meanCurvature_[patchI];
815         std::map<label, scalar> newValues;
817         for(std::map<label, scalar>::iterator it=mc.begin();it!=mc.end();++it)
818         {
819             const labelList& pEdges = pointEdges[it->first];
821             scalar maxCurv(-VSMALL), minCurv(VSMALL);
822             label nNei(0);
824             forAll(pEdges, peI)
825             {
826                 const label ovI = edges[pEdges[peI]].otherVertex(it->first);
828                 if( mc.find(ovI) != mc.end() )
829                 {
830                     maxCurv = Foam::max(maxCurv, mc[ovI]);
831                     minCurv = Foam::min(minCurv, mc[ovI]);
832                     ++nNei;
833                 }
834             }
836             if( nNei != 0 )
837             {
838                 if( mc[it->first] > maxCurv )
839                 {
840                     newValues.insert
841                     (
842                         std::make_pair(it->first, 0.5*(maxCurv+mc[it->first]))
843                     );
844                 }
845                 else if( mc[it->first] >= minCurv )
846                 {
847                     newValues.insert(*it);
848                 }
849                 else
850                 {
851                     newValues.insert
852                     (
853                         std::make_pair(it->first, 0.5*(minCurv+mc[it->first]))
854                     );
855                 }
856             }
857         }
859         mc = newValues;
860     }
863 void triSurfaceCurvatureEstimator::calculateMinAndMaxCurvature()
865     maxCurvature_.setSize(meanCurvature_.size());
866     minCurvature_.setSize(meanCurvature_.size());
868     forAll(maxCurvature_, patchI)
869     {
870         std::map<label, scalar>& mc = meanCurvature_[patchI];
871         std::map<label, scalar>& gc = gaussianCurvature_[patchI];
872         for
873         (
874             std::map<label, scalar>::const_iterator it=mc.begin();
875             it!=mc.end();
876             ++it
877         )
878         {
879             const label pI = it->first;
880             scalar disc = sqr(mc[pI]) - gc[pI];
881             if( disc <  0 )
882                 disc = sqr(mc[pI]) + gc[pI];
884             const scalar sqrtdisc = sqrt(disc);
885             maxCurvature_[patchI][pI] = mc[pI] + sqrtdisc;
886             minCurvature_[patchI][pI] = mc[pI] - sqrtdisc;
887         }
888     }
892 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
894 } // End namespace Foam
896 // ************************************************************************* //