]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMUtils/GEOMUtils_ShapeStatistics.cxx
Salome HOME
22853: EDF 9924 GEOM: Dimension histogram
[modules/geom.git] / src / GEOMUtils / GEOMUtils_ShapeStatistics.cxx
1 // Copyright (C) 2015  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   for ( it = shapes.begin(); it != shapes.end(); ++it ) {
49     double aMeasure;
50     TopTools_IndexedMapOfShape aSubShapesMap;
51     TopExp::MapShapes(*it, aSubShapesMap); // map of all global indices
52     TopTools_IndexedMapOfShape aMx;
53     TopExp::MapShapes( *it, entity, aMx ); // map of current type sub-shape indices 
54     int aNbS = aMx.Extent();
55     int index = -1;
56     for ( int i = 1; i <= aNbS; ++i ) {
57       aMeasure = 0.0;
58       const TopoDS_Shape& aSubShape = aMx( i );
59       //Get the measure: length, area or volume
60       GProp_GProps LProps, SProps, VProps;
61       if ( entity == TopAbs_EDGE ) {
62         BRepGProp::LinearProperties( aSubShape, LProps );
63         aMeasure = LProps.Mass();
64       } else if ( entity == TopAbs_FACE ) {
65         BRepGProp::SurfaceProperties( aSubShape, SProps );
66         aMeasure = SProps.Mass();
67       } else if ( entity == TopAbs_SOLID ) {
68         BRepGProp::VolumeProperties( aSubShape, VProps );
69         aMeasure = VProps.Mass();
70       }
71       // Don't pass sub-shapes with out of range measure, if range is used
72       if ( hasRange ) {
73         if ( aMeasure < range.min || aMeasure > range.max )
74           continue;
75       } else {
76         // get range min and max
77         if ( aMeasure < range.min ) range.min = aMeasure;
78         if ( aMeasure > range.max ) range.max = aMeasure;
79       }
80       // get global index of sub-shape
81       index = aSubShapesMap.FindIndex( aSubShape );
82       // keep measures to distribute it
83       measures[index] = aMeasure;
84     }
85   }
86   return measures;
87 }
88
89 //=================================================================================
90 // function : ComputeDistribution()
91 // purpose  : gets distribution data for single shape
92 //=================================================================================
93 Distribution ComputeDistribution( TopoDS_Shape shape, 
94                                   TopAbs_ShapeEnum entity, 
95                                   int intervals, 
96                                   Range range)
97 {
98   std::list<TopoDS_Shape> aShapes;
99   aShapes.push_back( shape );
100   return ComputeDistribution( aShapes, entity, intervals, range );
101 }
102
103 //=================================================================================
104 // function : ComputeDistribution()
105 // purpose  : gets distribution data for list of shapes
106 //=================================================================================
107 Distribution ComputeDistribution( std::list<TopoDS_Shape> shapes, 
108                                   TopAbs_ShapeEnum entity, 
109                                   int nbIntervals, 
110                                   Range range)
111 {
112   // get list of measures and compute range (if it was not specified)
113   std::map<int,double> measures = ComputeMeasures( shapes, entity, range );
114
115   // compute a step
116   double aStep = (range.max - range.min) / nbIntervals;
117
118   // compute distribution in intervals
119   Distribution aDistr;
120   std::map<int,double>::iterator dit;
121   for ( int i = 0; i < nbIntervals; i++ ) {
122     Range localRange; // range of current interval
123     localRange.min = range.min + ( i * aStep );
124     localRange.max = range.min + ( (i+1) * aStep );
125     localRange.count = 0;
126
127     std::vector<int> indicesToErase;
128     for ( dit = measures.begin(); dit != measures.end(); dit++ ) {
129       if ( ( dit->second >= localRange.min && dit->second < localRange.max ) || 
130            ( i == nbIntervals-1 && dit->second == localRange.max ) ) {
131         localRange.count++;
132         localRange.indices.push_back( dit->first );
133         // measure is in interval, so remove it from map of search
134         indicesToErase.push_back( dit->first );
135       }
136     }
137     aDistr.push_back( localRange );
138     for( int j=0; j < indicesToErase.size(); j++ )
139       measures.erase( indicesToErase[j] );
140   }
141
142   return aDistr;
143 }
144
145 } //namespace GEOMUtils