Salome HOME
215d69bf198b9f34960203723da2a367c4ed6749
[modules/geom.git] / src / GEOMUtils / GEOMUtils_ShapeStatistics.cxx
1 // Copyright (C) 2015-2022  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File   : GEOMUtils_ShapeStatisticsDlg.cxx
21 // Author : Alexander KOVALEV, OPEN CASCADE S.A.S.
22
23 #include "GEOMUtils_ShapeStatistics.hxx"
24
25 #include <BRepGProp.hxx>
26 #include <GProp_GProps.hxx>
27 #include <TopExp.hxx>
28 #include <TopExp_Explorer.hxx>
29 #include <TopTools_IndexedMapOfShape.hxx>
30
31 namespace GEOMUtils
32 {
33 //=================================================================================
34 // function : ComputeMeasures()
35 // purpose  : gets measures of the given type for list of shapes in the range
36 //=================================================================================
37   std::map<int,double> ComputeMeasures( std::list<TopoDS_Shape> shapes, 
38                               TopAbs_ShapeEnum entity, 
39                               Range &range)
40 {
41   bool hasRange = (range.min != -1.0); // -1.0 means that range must not be used
42   if ( !hasRange )
43     range.min = 1e+32, range.max = 0.0;
44   // list of measures of entities
45   std::map<int, double> measures;
46     
47   std::list<TopoDS_Shape>::const_iterator it;
48   int shift = 0;
49   for ( it = shapes.begin(); it != shapes.end(); ++it ) {
50     double aMeasure;
51     TopTools_IndexedMapOfShape aSubShapesMap;
52     TopExp::MapShapes(*it, aSubShapesMap); // map of all global indices
53     TopTools_IndexedMapOfShape aMx;
54     TopExp::MapShapes( *it, entity, aMx ); // map of current type sub-shape indices 
55     int aNbS = aMx.Extent();
56     int index = -1;
57     for ( int i = 1; i <= aNbS; ++i ) {
58       aMeasure = 0.0;
59       const TopoDS_Shape& aSubShape = aMx( i );
60       //Get the measure: length, area or volume
61       GProp_GProps LProps, SProps, VProps;
62       if ( entity == TopAbs_EDGE ) {
63         BRepGProp::LinearProperties( aSubShape, LProps );
64         aMeasure = LProps.Mass();
65       } else if ( entity == TopAbs_FACE ) {
66         BRepGProp::SurfaceProperties( aSubShape, SProps );
67         aMeasure = SProps.Mass();
68       } else if ( entity == TopAbs_SOLID ) {
69         BRepGProp::VolumeProperties( aSubShape, VProps );
70         aMeasure = VProps.Mass();
71       }
72       // Don't pass sub-shapes with out of range measure, if range is used
73       if ( hasRange ) {
74         if ( aMeasure < range.min || aMeasure > range.max )
75           continue;
76       } else {
77         // get range min and max
78         if ( aMeasure < range.min ) range.min = aMeasure;
79         if ( aMeasure > range.max ) range.max = aMeasure;
80       }
81       // get global index of sub-shape
82       index = aSubShapesMap.FindIndex( aSubShape );
83       // keep measures to distribute it
84       measures[shift+index] = aMeasure;
85     }
86     shift += aSubShapesMap.Extent();
87   }
88   return measures;
89 }
90
91 //=================================================================================
92 // function : ComputeDistribution()
93 // purpose  : gets distribution data for single shape
94 //=================================================================================
95 Distribution ComputeDistribution( TopoDS_Shape shape, 
96                                   TopAbs_ShapeEnum entity, 
97                                   int intervals, 
98                                   Range range)
99 {
100   std::list<TopoDS_Shape> aShapes;
101   aShapes.push_back( shape );
102   return ComputeDistribution( aShapes, entity, intervals, range );
103 }
104
105 //=================================================================================
106 // function : ComputeDistribution()
107 // purpose  : gets distribution data for list of shapes
108 //=================================================================================
109 Distribution ComputeDistribution( std::list<TopoDS_Shape> shapes, 
110                                   TopAbs_ShapeEnum entity, 
111                                   int nbIntervals, 
112                                   Range range)
113 {
114   // get list of measures and compute range (if it was not specified)
115   std::map<int,double> measures = ComputeMeasures( shapes, entity, range );
116
117   // compute a step
118   double aStep = (range.max - range.min) / nbIntervals;
119
120   // compute distribution in intervals
121   Distribution aDistr;
122   std::map<int,double>::iterator dit;
123   for ( int i = 0; i < nbIntervals; i++ ) {
124     Range localRange; // range of current interval
125     localRange.min = range.min + ( i * aStep );
126     localRange.max = range.min + ( (i+1) * aStep );
127     localRange.count = 0;
128
129     std::vector<int> indicesToErase;
130     for ( dit = measures.begin(); dit != measures.end(); dit++ ) {
131       if ( ( dit->second >= localRange.min && dit->second < localRange.max ) || 
132            ( i == nbIntervals-1 && dit->second == localRange.max ) ) {
133         localRange.count++;
134         localRange.indices.push_back( dit->first );
135         // measure is in interval, so remove it from map of search
136         indicesToErase.push_back( dit->first );
137       }
138     }
139     aDistr.push_back( localRange );
140     for( size_t j=0; j < indicesToErase.size(); j++ )
141       measures.erase( indicesToErase[j] );
142   }
143
144   return aDistr;
145 }
146
147 } //namespace GEOMUtils