From 2c3b6932117ebd79122309d089815ab9a206d50c Mon Sep 17 00:00:00 2001 From: akl Date: Thu, 23 Apr 2015 12:42:06 +0400 Subject: [PATCH] 22853: EDF 9924 GEOM: Dimension histogram --- src/CMakeLists.txt | 4 +- src/EntityGUI/CMakeLists.txt | 2 + src/EntityGUI/EntityGUI_SubShapeDlg.cxx | 21 + src/EntityGUI/EntityGUI_SubShapeDlg.h | 2 + src/GEOMGUI/GEOM_msg_en.ts | 83 ++- src/GEOMGUI/GEOM_msg_fr.ts | 85 ++- src/GEOMGUI/GEOM_msg_ja.ts | 89 +++- src/GEOMGUI/GeometryGUI.cxx | 3 + src/GEOMGUI/GeometryGUI_Operations.h | 1 + src/GEOMUtils/CMakeLists.txt | 2 + src/GEOMUtils/GEOMUtils_ShapeStatistics.cxx | 154 ++++++ src/GEOMUtils/GEOMUtils_ShapeStatistics.hxx | 67 +++ src/GroupGUI/CMakeLists.txt | 2 + src/GroupGUI/GroupGUI_GroupDlg.cxx | 27 + src/GroupGUI/GroupGUI_GroupDlg.h | 2 + src/MeasureGUI/CMakeLists.txt | 2 + src/MeasureGUI/MeasureGUI.cxx | 4 + .../MeasureGUI_ShapeStatisticsDlg.cxx | 486 ++++++++++++++++++ .../MeasureGUI_ShapeStatisticsDlg.h | 86 ++++ 19 files changed, 1110 insertions(+), 12 deletions(-) create mode 100644 src/GEOMUtils/GEOMUtils_ShapeStatistics.cxx create mode 100644 src/GEOMUtils/GEOMUtils_ShapeStatistics.hxx create mode 100644 src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.cxx create mode 100644 src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d271e268e..6f830743b 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,8 +43,8 @@ IF(SALOME_BUILD_GUI) SET(SUBDIRS_GUI OBJECT DlgRef GEOMFiltersSelection Material GEOMGUI GEOMBase DependencyTree GEOMToolsGUI DisplayGUI BasicGUI PrimitiveGUI GenerationGUI - CurveCreator EntityGUI BuildGUI BooleanGUI TransformationGUI OperationGUI - RepairGUI MeasureGUI GroupGUI BlocksGUI AdvancedGUI + CurveCreator MeasureGUI EntityGUI BuildGUI BooleanGUI TransformationGUI OperationGUI + RepairGUI GroupGUI BlocksGUI AdvancedGUI GEOM_SWIG_WITHIHM ) ENDIF() diff --git a/src/EntityGUI/CMakeLists.txt b/src/EntityGUI/CMakeLists.txt index ecfc09a2d..0bb93f921 100755 --- a/src/EntityGUI/CMakeLists.txt +++ b/src/EntityGUI/CMakeLists.txt @@ -39,6 +39,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/GEOMImpl ${PROJECT_SOURCE_DIR}/src/GEOMGUI ${PROJECT_SOURCE_DIR}/src/GEOMBase + ${PROJECT_SOURCE_DIR}/src/MeasureGUI ${PROJECT_SOURCE_DIR}/src/SKETCHER ${PROJECT_SOURCE_DIR}/src/CurveCreator ${PROJECT_SOURCE_DIR}/src/ShapeRecognition @@ -67,6 +68,7 @@ SET(_link_LIBRARIES DlgRef GEOMSketcher CurveCreator + MeasureGUI ) # optional sources diff --git a/src/EntityGUI/EntityGUI_SubShapeDlg.cxx b/src/EntityGUI/EntityGUI_SubShapeDlg.cxx index 9db5fbab0..598d05de6 100644 --- a/src/EntityGUI/EntityGUI_SubShapeDlg.cxx +++ b/src/EntityGUI/EntityGUI_SubShapeDlg.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -165,6 +166,7 @@ EntityGUI_SubShapeDlg::EntityGUI_SubShapeDlg(GeometryGUI* theGeometryGUI, QWidge myLessFilterSpin = new SalomeApp_DoubleSpinBox(myFilterGrp); myGreaterFilterSpin = new SalomeApp_DoubleSpinBox(myFilterGrp); myApplyFilterButton = new QPushButton(tr("GEOM_BUT_APPLY"), myFilterGrp); + myPlotDistributionButton = new QPushButton(tr("GEOM_PLOT_DISTRIBUTION"), myFilterGrp); QGridLayout* filterLayout = new QGridLayout(myFilterGrp); filterLayout->addWidget(myLessFilterCheck, 0, 0); @@ -174,6 +176,7 @@ EntityGUI_SubShapeDlg::EntityGUI_SubShapeDlg(GeometryGUI* theGeometryGUI, QWidge filterLayout->addWidget(myGreaterFilterCombo, 1, 1); filterLayout->addWidget(myGreaterFilterSpin, 1, 2); filterLayout->addWidget(myApplyFilterButton, 0, 3); + filterLayout->addWidget(myPlotDistributionButton, 1, 3); QVBoxLayout* layout = new QVBoxLayout(centralWidget()); layout->setMargin(0); layout->setSpacing(6); @@ -250,6 +253,7 @@ void EntityGUI_SubShapeDlg::Init() connect(GroupPoints->PushButton4, SIGNAL(clicked()), this, SLOT(showOnlySelected())); connect(myApplyFilterButton, SIGNAL(clicked()), this, SLOT(ClickOnOkFilter())); + connect(myPlotDistributionButton, SIGNAL(clicked()), this, SLOT(ClickOnPlot())); connect(myLessFilterCheck, SIGNAL(stateChanged(int)), this, SLOT(MeasureToggled())); connect(myGreaterFilterCheck, SIGNAL(stateChanged(int)), this, SLOT(MeasureToggled())); @@ -491,6 +495,11 @@ void EntityGUI_SubShapeDlg::SubShapeToggled() GroupPoints->CheckButton1->isChecked() && shapeType() < GEOM::VERTEX); + myPlotDistributionButton->setEnabled( myFilterGrp->isEnabled() && + ( shapeType() == TopAbs_EDGE || + shapeType() == TopAbs_FACE || + shapeType() == TopAbs_SOLID ) ); + activateSelection(); } @@ -936,6 +945,18 @@ void EntityGUI_SubShapeDlg::ClickOnOkFilter() updateButtonState(); } +//================================================================================= +// function : ClickOnPlot() +// purpose : opens "Shape Statistics" dialog box in order to plot sub-shapes distribution. +//================================================================================= +void EntityGUI_SubShapeDlg::ClickOnPlot() +{ + QDialog* dlg = new MeasureGUI_ShapeStatisticsDlg( this, myShape, (TopAbs_ShapeEnum)shapeType() ); + if ( dlg ) { + dlg->show(); + } +} + //================================================================================= // function : MeasureToggled() // purpose : diff --git a/src/EntityGUI/EntityGUI_SubShapeDlg.h b/src/EntityGUI/EntityGUI_SubShapeDlg.h index e3618ac41..c2f14e66e 100644 --- a/src/EntityGUI/EntityGUI_SubShapeDlg.h +++ b/src/EntityGUI/EntityGUI_SubShapeDlg.h @@ -73,6 +73,7 @@ private slots: void showOnlySelected(); void ClickOnOkFilter(); + void ClickOnPlot(); void MeasureToggled(); private: @@ -102,6 +103,7 @@ private: SalomeApp_DoubleSpinBox* myLessFilterSpin; SalomeApp_DoubleSpinBox* myGreaterFilterSpin; QPushButton* myApplyFilterButton; + QPushButton* myPlotDistributionButton; QGroupBox* myFilterGrp; }; diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index c1e7addb1..64727e1af 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -431,6 +431,10 @@ Please, select face, shell or solid and try again GEOM_FAST_CHECK_INTERSECTIONS Fast intersection + + GEOM_SHAPE_STATISTICS + Shape Statistics + GEOM_CIRCLE Circle @@ -2556,6 +2560,10 @@ Please, select face, shell or solid and try again MEN_FAST_CHECK_INTERSECTIONS Fast intersection + + MEN_SHAPE_STATISTICS + Shape Statistics + MEN_CHECK_FREE_BNDS Check Free Boundaries @@ -2838,7 +2846,7 @@ Please, select face, shell or solid and try again MEN_MEASURES - Measures + Inspection MEN_MIN_DIST @@ -3591,6 +3599,10 @@ Please, select face, shell or solid and try again STB_FAST_CHECK_INTERSECTIONS Fast intersection + + + STB_SHAPE_STATISTICS + Shape Statistics STB_CHECK_FREE_BNDS @@ -4224,6 +4236,10 @@ Please, select face, shell or solid and try again TOP_FAST_CHECK_INTERSECTIONS Fast intersection + + TOP_SHAPE_STATISTICS + Shape Statistics + TOP_CHECK_FREE_BNDS Check free boundaries @@ -5384,6 +5400,10 @@ shells and solids on the other hand. GEOM_HEALING_STATS_COL_2 Modification + + GEOM_PLOT_DISTRIBUTION + Plot + GeometryGUI @@ -5433,7 +5453,7 @@ shells and solids on the other hand. TOOL_MEASURES - Measures + Inspection TOOL_IMPORTEXPORT @@ -7335,6 +7355,65 @@ Do you want to create new material? Objects And Results + + MeasureGUI_ShapeStatisticsDlg + + GEOM_SHAPE_STATISTICS_TYPE + Type + + + GEOM_SHAPE_STATISTICS_LENGTH + Edges length + + + GEOM_SHAPE_STATISTICS_AREA + Faces area + + + GEOM_SHAPE_STATISTICS_VOLUME + Solids volume + + + GEOM_SHAPE_STATISTICS_NB_INTERVALS + Number of intervals + + + GEOM_SHAPE_STATISTICS_SCALAR_RANGE + Scalar range + + + GEOM_SHAPE_STATISTICS_COMPUTE + Compute + + + GEOM_SHAPE_STATISTICS_MIN + Min + + + GEOM_SHAPE_STATISTICS_MAX + Max + + + GEOM_SHAPE_STATISTICS_CREATE_GROUPS + Create Groups + + + GEOM_SHAPE_STATISTICS_DISTRIBUTION_NB_ENT + Number of entities + + + GEOM_SHAPE_STATISTICS_MIN_ERROR + Set minimal range value or switch-off Scalar range + + + GEOM_SHAPE_STATISTICS_MAX_ERROR + Set maximal range value or switch-off Scalar range + + + GEOM_SHAPE_STATISTICS_MIN_MAX_ERROR + Minimal range value can not be more than maximal + + TransformationGUI_ExtensionDlg diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 69786b158..a895bf960 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -431,6 +431,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_FAST_CHECK_INTERSECTIONS Intersection rapide + + GEOM_SHAPE_STATISTICS + Shape Statistics + GEOM_CIRCLE Cercle @@ -2512,6 +2516,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_FAST_CHECK_INTERSECTIONS Intersection rapide + + MEN_SHAPE_STATISTICS + Shape Statistics + MEN_CHECK_FREE_BNDS Contrôler les contours libres @@ -2794,7 +2802,7 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_MEASURES - Mesures + Inspection MEN_MIN_DIST @@ -3539,7 +3547,11 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_FAST_CHECK_INTERSECTIONS Intersection rapide - + + + STB_SHAPE_STATISTICS + Shape Statistics + STB_CHECK_FREE_BNDS Vérifier les contours libres @@ -4164,6 +4176,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_FAST_CHECK_INTERSECTIONS Intersection rapide + + TOP_SHAPE_STATISTICS + Shape Statistics + TOP_CHECK_FREE_BNDS Valider les contours libres @@ -5316,6 +5332,10 @@ le paramètre '%1' aux préférences du module Géométrie.GEOM_HEALING_STATS_COL_2 Modification + + GEOM_PLOT_DISTRIBUTION + Plot + GeometryGUI @@ -5365,7 +5385,7 @@ le paramètre '%1' aux préférences du module Géométrie. TOOL_MEASURES - Informations + Inspection TOOL_IMPORTEXPORT @@ -7268,6 +7288,65 @@ Voulez-vous en créer un nouveau ? Objets et résultats + + MeasureGUI_ShapeStatisticsDlg + + GEOM_SHAPE_STATISTICS_TYPE + Type + + + GEOM_SHAPE_STATISTICS_LENGTH + Edges length + + + GEOM_SHAPE_STATISTICS_AREA + Faces area + + + GEOM_SHAPE_STATISTICS_VOLUME + Solids volume + + + GEOM_SHAPE_STATISTICS_NB_INTERVALS + Number of intervals + + + GEOM_SHAPE_STATISTICS_SCALAR_RANGE + Scalar range + + + GEOM_SHAPE_STATISTICS_COMPUTE + Compute + + + GEOM_SHAPE_STATISTICS_MIN + Min + + + GEOM_SHAPE_STATISTICS_MAX + Max + + + GEOM_SHAPE_STATISTICS_CREATE_GROUPS + Create Groups + + + GEOM_SHAPE_STATISTICS_DISTRIBUTION_NB_ENT + Number of entities + + + GEOM_SHAPE_STATISTICS_MIN_ERROR + Set minimal range value or switch-off Scalar range + + + GEOM_SHAPE_STATISTICS_MAX_ERROR + Set maximal range value or switch-off Scalar range + + + GEOM_SHAPE_STATISTICS_MIN_MAX_ERROR + Minimal range value can not be more than maximal + + TransformationGUI_ExtensionDlg diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts index 6b5668ec8..c3e895e1e 100644 --- a/src/GEOMGUI/GEOM_msg_ja.ts +++ b/src/GEOMGUI/GEOM_msg_ja.ts @@ -415,6 +415,10 @@ GEOM_FAST_CHECK_INTERSECTIONS Fast intersection + + GEOM_SHAPE_STATISTICS + Shape Statistics + GEOM_CHECK_SELF_INTERSECTIONS_FAILED 自己交差の検出に失敗しました @@ -2467,6 +2471,10 @@ MEN_FAST_CHECK_INTERSECTIONS Fast intersection + + MEN_SHAPE_STATISTICS + Shape Statistics + MEN_CHECK_FREE_BNDS 自由境界の確認 @@ -2749,7 +2757,7 @@ MEN_MEASURES - 計測 + Inspection MEN_MIN_DIST @@ -3482,7 +3490,11 @@ STB_FAST_CHECK_INTERSECTIONS Fast intersection - + + + STB_SHAPE_STATISTICS + Shape Statistics + STB_CHECK_FREE_BNDS 自由境界をチェック @@ -4100,8 +4112,12 @@ 自己交差の確認 - TOP_FAST_CHECK_INTERSECTIONS - Fast intersection + TOP_FAST_CHECK_INTERSECTIONS + Fast intersection + + + TOP_SHAPE_STATISTICS + Shape Statistics TOP_CHECK_FREE_BNDS @@ -5211,6 +5227,10 @@ GEOM_NO_SHAPES_SELECTED There are no shapes that meet filtering parameters + + GEOM_PLOT_DISTRIBUTION + Plot + GeometryGUI @@ -5260,7 +5280,7 @@ TOOL_MEASURES - Measures + Inspection TOOL_IMPORTEXPORT @@ -7153,6 +7173,65 @@ Objects And Results + + MeasureGUI_ShapeStatisticsDlg + + GEOM_SHAPE_STATISTICS_TYPE + Type + + + GEOM_SHAPE_STATISTICS_LENGTH + Edges length + + + GEOM_SHAPE_STATISTICS_AREA + Faces area + + + GEOM_SHAPE_STATISTICS_VOLUME + Solids volume + + + GEOM_SHAPE_STATISTICS_NB_INTERVALS + Number of intervals + + + GEOM_SHAPE_STATISTICS_SCALAR_RANGE + Scalar range + + + GEOM_SHAPE_STATISTICS_COMPUTE + Compute + + + GEOM_SHAPE_STATISTICS_MIN + Min + + + GEOM_SHAPE_STATISTICS_MAX + Max + + + GEOM_SHAPE_STATISTICS_CREATE_GROUPS + Create Groups + + + GEOM_SHAPE_STATISTICS_DISTRIBUTION_NB_ENT + Number of entities + + + GEOM_SHAPE_STATISTICS_MIN_ERROR + Set minimal range value or switch-off Scalar range + + + GEOM_SHAPE_STATISTICS_MAX_ERROR + Set maximal range value or switch-off Scalar range + + + GEOM_SHAPE_STATISTICS_MIN_MAX_ERROR + Minimal range value can not be more than maximal + + TransformationGUI_ExtensionDlg diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index 790e65a7d..25832ed53 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -644,6 +644,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) case GEOMOp::OpCheckSelfInters: // MENU MEASURE - CHECK SELF INTERSECTIONS case GEOMOp::OpFastCheckInters: // MENU MEASURE - FAST CHECK INTERSECTIONS case GEOMOp::OpManageDimensions: // MENU MEASURE - MANAGE DIMENSIONS + case GEOMOp::OpShapeStatistics: // MENU MEASURE - SHAPE STATISTICS case GEOMOp::OpShowAllDimensions: // POPUP MENU - SHOW ALL DIMENSIONS case GEOMOp::OpHideAllDimensions: // POPUP MENU - HIDE ALL DIMENSIONS libName = "MeasureGUI"; @@ -1025,6 +1026,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpGetNonBlocks, "GET_NON_BLOCKS" ); createGeomAction( GEOMOp::OpCheckSelfInters, "CHECK_SELF_INTERSECTIONS" ); createGeomAction( GEOMOp::OpFastCheckInters, "FAST_CHECK_INTERSECTIONS" ); + createGeomAction( GEOMOp::OpShapeStatistics, "SHAPE_STATISTICS" ); #ifdef _DEBUG_ // PAL16821 createGeomAction( GEOMOp::OpCheckGeom, "CHECK_GEOMETRY" ); @@ -1288,6 +1290,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( GEOMOp::OpCheckSelfInters, measurId, -1 ); createMenu( GEOMOp::OpFastCheckInters, measurId, -1 ); createMenu( GEOMOp::OpInspectObj, measurId, -1 ); + createMenu( GEOMOp::OpShapeStatistics, measurId, -1 ); int toolsId = createMenu( tr( "MEN_TOOLS" ), -1, -1, 50 ); #if defined(_DEBUG_) || defined(_DEBUG) // PAL16821 diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index 915f5d1f1..865ac91d9 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -200,6 +200,7 @@ namespace GEOMOp { OpHideAllDimensions = 5016, // POPUP MENU - HIDE ALL DIMENSIONS OpFastCheckInters = 5017, // MENU MEASURES - FAST CHECK INTERSECTIONS OpInspectObj = 5018, // MENU MEASURES - INSPECT OBJECT + OpShapeStatistics = 5019, // MENU MEASURES - SHAPE STATISTICS // GroupGUI --------------------//-------------------------------- OpGroupCreate = 6000, // MENU GROUP - CREATE OpGroupEdit = 6001, // MENU GROUP - EDIT diff --git a/src/GEOMUtils/CMakeLists.txt b/src/GEOMUtils/CMakeLists.txt index 039990ab7..a2bbfd9d0 100755 --- a/src/GEOMUtils/CMakeLists.txt +++ b/src/GEOMUtils/CMakeLists.txt @@ -53,6 +53,7 @@ SET(GEOMUtils_HEADERS GEOMUtils.hxx GEOMUtils_Hatcher.hxx GEOMUtils_HTrsfCurve2d.hxx + GEOMUtils_ShapeStatistics.hxx GEOMUtils_Trsf2d.hxx GEOMUtils_TrsfCurve2d.hxx GEOMUtils_XmlHandler.hxx @@ -63,6 +64,7 @@ SET(GEOMUtils_SOURCES GEOMUtils.cxx GEOMUtils_Hatcher.cxx GEOMUtils_HTrsfCurve2d.cxx + GEOMUtils_ShapeStatistics.cxx GEOMUtils_Trsf2d.cxx GEOMUtils_TrsfCurve2d.cxx GEOMUtils_XmlHandler.cxx diff --git a/src/GEOMUtils/GEOMUtils_ShapeStatistics.cxx b/src/GEOMUtils/GEOMUtils_ShapeStatistics.cxx new file mode 100644 index 000000000..3343e2c2c --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_ShapeStatistics.cxx @@ -0,0 +1,154 @@ +// Copyright (C) 2015 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : GEOMUtils_ShapeStatisticsDlg.cxx +// Author : Alexander KOVALEV, OPEN CASCADE S.A.S. + +#include "GEOMUtils_ShapeStatistics.hxx" + +#include +#include +#include +#include +#include + +namespace GEOMUtils +{ +//================================================================================= +// function : ComputeMeasures() +// purpose : gets measures of the given type for list of shapes in the range +//================================================================================= + std::map ComputeMeasures( std::list shapes, + TopAbs_ShapeEnum entity, + Range &range) +{ + bool hasRange = (range.min != -1.0); // -1.0 means that range must not be used + if ( !hasRange ) + range.min = 1e+32, range.max = 0.0; + // list of measures of entities + std::map measures; + + std::list::const_iterator it; + for ( it = shapes.begin(); it != shapes.end(); ++it ) { + double aMeasure; + TopTools_IndexedMapOfShape aMx; + TopExp::MapShapes( *it, entity, aMx ); + int aNbS = aMx.Extent(); + int index = -1; + for ( int i = 1; i <= aNbS; ++i ) { + aMeasure = 0.0; + const TopoDS_Shape& aSubShape = aMx( i ); + index = aMx.FindIndex( aSubShape ); + //Get the measure: length, area or volume + GProp_GProps LProps, SProps, VProps; + if ( entity == TopAbs_EDGE ) { + BRepGProp::LinearProperties( aSubShape, LProps ); + aMeasure = LProps.Mass(); + } else if ( entity == TopAbs_FACE ) { + BRepGProp::SurfaceProperties( aSubShape, SProps ); + aMeasure = SProps.Mass(); + } else if ( entity == TopAbs_SOLID ) { + BRepGProp::VolumeProperties( aSubShape, VProps ); + aMeasure = VProps.Mass(); + } + // Don't pass sub-shapes with out of range measure, if range is used + if ( hasRange ) { + if ( aMeasure < range.min || aMeasure > range.max ) + continue; + } else { + // get range min and max + if ( aMeasure < range.min ) range.min = aMeasure; + if ( aMeasure > range.max ) range.max = aMeasure; + } + // keep measures to distribute it + measures[index] = aMeasure; + } + } + return measures; +} + +//================================================================================= +// function : ComputeDistribution() +// purpose : gets distribution data for single shape +//================================================================================= +Distribution ComputeDistribution( TopoDS_Shape shape, + TopAbs_ShapeEnum entity, + int intervals, + Range range) +{ + std::list aShapes; + aShapes.push_back( shape ); + return ComputeDistribution( aShapes, entity, intervals, range ); +} + +//================================================================================= +// function : ComputeDistribution() +// purpose : gets distribution data for list of shapes +//================================================================================= +Distribution ComputeDistribution( std::list shapes, + TopAbs_ShapeEnum entity, + int nbIntervals, + Range range) +{ + // get list of measures and compute range (if it was not specified) + std::map measures = ComputeMeasures( shapes, entity, range ); + + // compute a step + double aStep = (range.max - range.min) / nbIntervals; + + // compute distribution in intervals + Distribution aDistr; + std::map::iterator dit; + for ( int i = 0; i < nbIntervals; i++ ) { + Range localRange; // range of current interval + localRange.min = range.min + ( i * aStep ); + localRange.max = range.min + ( (i+1) * aStep ); + localRange.count = 0; + + std::vector indicesToErase; + for ( dit = measures.begin(); dit != measures.end(); dit++ ) { + if ( ( dit->second >= localRange.min && dit->second < localRange.max ) || + ( i == nbIntervals-1 && dit->second == localRange.max ) ) { + localRange.count++; + localRange.indices.push_back( dit->first ); + // measure is in interval, so remove it from map of search + indicesToErase.push_back( dit->first ); + } + } + aDistr.push_back( localRange ); + for( int j=0; j < indicesToErase.size(); j++ ) + measures.erase( indicesToErase[j] ); + } + + return aDistr; +} + +//================================================================================= +// function : FilterSubShapes() +// purpose : gets list of sub-shapes IDs according to the specified range data (needed for groups creation function) +//================================================================================= +std::list FilterSubShapes( TopoDS_Shape shape, + TopAbs_ShapeEnum entity, + Range range) +{ + std::list idList; + return idList; +} + +} //namespace GEOMUtils diff --git a/src/GEOMUtils/GEOMUtils_ShapeStatistics.hxx b/src/GEOMUtils/GEOMUtils_ShapeStatistics.hxx new file mode 100644 index 000000000..73c29ed61 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_ShapeStatistics.hxx @@ -0,0 +1,67 @@ +// Copyright (C) 2015 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : GEOMUtils_ShapeStatisticsDlg.hxx +// Author : Alexander KOVALEV, OPEN CASCADE S.A.S. + +#ifndef _GEOMUtils_ShapeStatistics_HXX_ +#define _GEOMUtils_ShapeStatistics_HXX_ + +#include +#include +#include + +#include + +namespace GEOMUtils +{ + // struct to store range data + typedef struct { double min; double max; long count; std::list indices; } Range; + // distribution is a set of ranges + typedef std::vector Distribution; + + // function to get measures of entities and compute range for list of shapes + Standard_EXPORT std::map ComputeMeasures( + std::list shapes, + TopAbs_ShapeEnum entity, + Range &range ); + + // function to get distribution data for single shape + Standard_EXPORT Distribution ComputeDistribution( + TopoDS_Shape shape, + TopAbs_ShapeEnum entity, + int intervals, + Range range ); + + // function to get distribution data for list of shapes + Standard_EXPORT Distribution ComputeDistribution( + std::list shapes, + TopAbs_ShapeEnum entity, + int intervals, + Range range ); + + // function to get list of sub-shapes IDs according to the specified range data (needed for groups creation function). + Standard_EXPORT std::list FilterSubShapes( + TopoDS_Shape shape, + TopAbs_ShapeEnum entity, + Range range ); + +} + +#endif // _GEOMUtils_ShapeStatistics_HXX_ diff --git a/src/GroupGUI/CMakeLists.txt b/src/GroupGUI/CMakeLists.txt index acf593702..73e18271b 100755 --- a/src/GroupGUI/CMakeLists.txt +++ b/src/GroupGUI/CMakeLists.txt @@ -39,6 +39,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/GEOMImpl ${PROJECT_SOURCE_DIR}/src/GEOMGUI ${PROJECT_SOURCE_DIR}/src/GEOMBase + ${PROJECT_SOURCE_DIR}/src/MeasureGUI ${PROJECT_SOURCE_DIR}/src/DlgRef ${PROJECT_BINARY_DIR}/src/DlgRef ${CMAKE_CURRENT_SOURCE_DIR} @@ -56,6 +57,7 @@ ADD_DEFINITIONS( SET(_link_LIBRARIES GEOMBase GEOMUtils + MeasureGUI ) # --- resources --- diff --git a/src/GroupGUI/GroupGUI_GroupDlg.cxx b/src/GroupGUI/GroupGUI_GroupDlg.cxx index 82a51075e..a13977ef6 100644 --- a/src/GroupGUI/GroupGUI_GroupDlg.cxx +++ b/src/GroupGUI/GroupGUI_GroupDlg.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -200,6 +201,7 @@ GroupGUI_GroupDlg::GroupGUI_GroupDlg (Mode mode, GeometryGUI* theGeometryGUI, QW myLessFilterSpin = new SalomeApp_DoubleSpinBox(myFilterGrp); myGreaterFilterSpin = new SalomeApp_DoubleSpinBox(myFilterGrp); myApplyFilterButton = new QPushButton(tr("GEOM_BUT_APPLY"), myFilterGrp); + myPlotDistributionButton = new QPushButton(tr("GEOM_PLOT_DISTRIBUTION"), myFilterGrp); QGridLayout* filterLayout = new QGridLayout(myFilterGrp); filterLayout->addWidget(myLessFilterCheck, 0, 0); @@ -209,6 +211,7 @@ GroupGUI_GroupDlg::GroupGUI_GroupDlg (Mode mode, GeometryGUI* theGeometryGUI, QW filterLayout->addWidget(myGreaterFilterCombo, 1, 1); filterLayout->addWidget(myGreaterFilterSpin, 1, 2); filterLayout->addWidget(myApplyFilterButton, 0, 3); + filterLayout->addWidget(myPlotDistributionButton, 1, 3); QVBoxLayout* layout = new QVBoxLayout(centralWidget()); layout->setMargin(0); layout->setSpacing(6); @@ -326,6 +329,7 @@ void GroupGUI_GroupDlg::Init() connect(myIdList, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged())); connect(myApplyFilterButton, SIGNAL(clicked()), this, SLOT(ClickOnOkFilter())); + connect(myPlotDistributionButton, SIGNAL(clicked()), this, SLOT(ClickOnPlot())); connect(myLessFilterCheck, SIGNAL(stateChanged(int)), this, SLOT(MeasureToggled())); connect(myGreaterFilterCheck, SIGNAL(stateChanged(int)), this, SLOT(MeasureToggled())); @@ -1135,6 +1139,16 @@ void GroupGUI_GroupDlg::updateState (bool isAdd) subSelectionWay() == ALL_SUBSHAPES && myIsShapeType && getShapeType() != TopAbs_VERTEX); + // manage of 'Plot' button access + GEOM::GEOM_IShapesOperations_var aShOp = getGeomEngine()->GetIShapesOperations( getStudyId() ); + GEOM::ListOfLong_var aSubShapes = aShOp->SubShapeAllIDs( myMainObj, getShapeType(), false ); + bool hasCurrentEntities = aSubShapes->length() > 0; + myPlotDistributionButton->setEnabled( myFilterGrp->isEnabled() && + myIsShapeType && + ( getShapeType() == TopAbs_EDGE || + getShapeType() == TopAbs_FACE || + getShapeType() == TopAbs_SOLID ) && + hasCurrentEntities ); if (subSelectionWay() == ALL_SUBSHAPES) setInPlaceObj(GEOM::GEOM_Object::_nil()); } @@ -1423,6 +1437,19 @@ void GroupGUI_GroupDlg::ClickOnOkFilter() updateState(true); } +//================================================================================= +// function : ClickOnPlot() +// purpose : opens "Shape Statistics" dialog box in order to plot sub-shapes distribution. +//================================================================================= +void GroupGUI_GroupDlg::ClickOnPlot() +{ + TopoDS_Shape aMainShape = GEOM_Client::get_client().GetShape(GeometryGUI::GetGeomGen(), myMainObj); + QDialog* dlg = new MeasureGUI_ShapeStatisticsDlg( this, aMainShape, getShapeType() ); + if ( dlg ) { + dlg->show(); + } +} + void GroupGUI_GroupDlg::MeasureToggled() { myLessFilterSpin->setEnabled(myLessFilterCheck->isChecked()); diff --git a/src/GroupGUI/GroupGUI_GroupDlg.h b/src/GroupGUI/GroupGUI_GroupDlg.h index ad8f4e159..231ea033a 100644 --- a/src/GroupGUI/GroupGUI_GroupDlg.h +++ b/src/GroupGUI/GroupGUI_GroupDlg.h @@ -83,6 +83,7 @@ private slots: void showOnlySelected(); void selectionChanged(); void ClickOnOkFilter(); + void ClickOnPlot(); void MeasureToggled(); private: @@ -133,6 +134,7 @@ private: SalomeApp_DoubleSpinBox* myLessFilterSpin; SalomeApp_DoubleSpinBox* myGreaterFilterSpin; QPushButton* myApplyFilterButton; + QPushButton* myPlotDistributionButton; QGroupBox* myFilterGrp; }; diff --git a/src/MeasureGUI/CMakeLists.txt b/src/MeasureGUI/CMakeLists.txt index c7ab327c1..31e2375ac 100755 --- a/src/MeasureGUI/CMakeLists.txt +++ b/src/MeasureGUI/CMakeLists.txt @@ -129,6 +129,7 @@ SET(_moc_HEADERS MeasureGUI_ManageDimensionsDlg.h MeasureGUI_CreateDimensionDlg.h MeasureGUI_DimensionInteractor.h + MeasureGUI_ShapeStatisticsDlg.h ) # header files / uic wrappings @@ -163,6 +164,7 @@ SET(MeasureGUI_SOURCES MeasureGUI_DimensionCreateTool.cxx MeasureGUI_DimensionInteractor.cxx MeasureGUI_DimensionFilter.cxx + MeasureGUI_ShapeStatisticsDlg.cxx ${_moc_SOURCES} ${_uic_files} ) diff --git a/src/MeasureGUI/MeasureGUI.cxx b/src/MeasureGUI/MeasureGUI.cxx index 37c8ed4b2..1ab692d32 100644 --- a/src/MeasureGUI/MeasureGUI.cxx +++ b/src/MeasureGUI/MeasureGUI.cxx @@ -53,6 +53,7 @@ #include "MeasureGUI_FastCheckIntersectionsDlg.h" // Method FAST CHECK INTERSCTIONS #include "MeasureGUI_PointDlg.h" // Method POINTCOORDINATES #include "MeasureGUI_ManageDimensionsDlg.h" // Method MANAGEDIMENSIONS +#include "MeasureGUI_ShapeStatisticsDlg.h" // Method SHAPE STATISTICS #include @@ -129,6 +130,9 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::OpFastCheckInters: dlg = new MeasureGUI_FastCheckIntersectionsDlg( getGeometryGUI(), parent ); break; // FAST CHECK INTERSCTIONS + case GEOMOp::OpShapeStatistics: + dlg = new MeasureGUI_ShapeStatisticsDlg( parent ); + break; // FAST CHECK INTERSCTIONS case GEOMOp::OpPointCoordinates: dlg = new MeasureGUI_PointDlg( getGeometryGUI(), parent ); break; // POINT COORDINATES diff --git a/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.cxx b/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.cxx new file mode 100644 index 000000000..febb7fab8 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.cxx @@ -0,0 +1,486 @@ +// Copyright (C) 2015 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : MeasureGUI_ShapeStatisticsDlg.cxx +// Author : Alexander KOVALEV, OPEN CASCADE S.A.S. + +// internal includes +#include "MeasureGUI_ShapeStatisticsDlg.h" + +// GEOM includes +#include +#include +#include +#include + +// GUI includes +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +// Qt includes +#include +#include +#include +#include + +// Qtx includes +#include + +// OCC includes +#include + +//=========================================================================== +// class : MeasureGUI_ShapeStatisticsDlg() +//=========================================================================== +MeasureGUI_ShapeStatisticsDlg::MeasureGUI_ShapeStatisticsDlg( QWidget* parent, TopoDS_Shape aShape, TopAbs_ShapeEnum aSubShapeType ) + : GEOMBase_Helper( SUIT_Session::session()->activeApplication()->desktop() ), + QDialog( parent ), + myHistogram ( 0 ) +{ + myShapes.push_back( aShape ); + myMainObj = GEOM::GEOM_Object::_nil(); + + QIcon iconSelect( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) ); + + setWindowTitle( tr( "GEOM_SHAPE_STATISTICS" ) ); + setAttribute( Qt::WA_DeleteOnClose ); + + myApp = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() ); + //myViewWindow = myApp->desktop()->activeWindow(); + + QVBoxLayout* topLayout = new QVBoxLayout( this ); + + QGridLayout* settingsLayout = new QGridLayout(); + + /********************** Selected Objects **********************/ + + QLabel* objsLabel = new QLabel( tr( "GEOM_SELECTED_OBJECTS" ), this ); + QPushButton* selBtn = new QPushButton( this ); + selBtn->setIcon( iconSelect ); + myEditMainShape = new QLineEdit( this ); + myEditMainShape->setReadOnly(true); + + settingsLayout->addWidget( objsLabel, 0, 0 ); + settingsLayout->addWidget( selBtn, 0, 1 ); + settingsLayout->addWidget( myEditMainShape, 0, 2 ); + + if ( !aShape.IsNull() ) { + objsLabel->hide(); + selBtn->hide(); + myEditMainShape->hide(); + } + + /********************** Type **********************/ + + QLabel* typeLabel = new QLabel( tr( "GEOM_SHAPE_STATISTICS_TYPE" ), this ); + myCBTypes = new QtxComboBox( this ); + myCBTypes->setCleared( true ); + if ( aSubShapeType != TopAbs_SHAPE ) { + fillTypes( aSubShapeType == TopAbs_EDGE, + aSubShapeType == TopAbs_FACE, + aSubShapeType == TopAbs_SOLID ); + myCBTypes->setEnabled( false ); + } + + settingsLayout->addWidget( typeLabel, 1, 0 ); + settingsLayout->addWidget( myCBTypes, 1, 2 ); + + /********************** Number of intervals **********************/ + + QLabel* nbIntervalsLabel = new QLabel( tr( "GEOM_SHAPE_STATISTICS_NB_INTERVALS" ), this ); + myNbIntervals = new QtxIntSpinBox( 1, 1000, 1, this ); + myNbIntervals->setValue( 10 ); + + settingsLayout->addWidget( nbIntervalsLabel, 2, 0 ); + settingsLayout->addWidget( myNbIntervals, 2, 2 ); + + /********************** Scalar Range **********************/ + + myScalarRangeBox = new QGroupBox( tr( "GEOM_SHAPE_STATISTICS_SCALAR_RANGE" ), this ); + myScalarRangeBox->setCheckable( true ); + myScalarRangeBox->setChecked( false ); + QLabel* minLabel = new QLabel( tr( "GEOM_SHAPE_STATISTICS_MIN" ), this ); + myMin = new QLineEdit( this ); + QtxDoubleValidator* aValid = new QtxDoubleValidator( this ); + aValid->setBottom( 0.0 ); + myMin->setValidator( aValid ); + QLabel* maxLabel = new QLabel( tr( "GEOM_SHAPE_STATISTICS_MAX" ), this ); + myMax = new QLineEdit( this ); + myMax->setValidator( aValid ); + + QPushButton* buttonCompute = new QPushButton( tr( "GEOM_SHAPE_STATISTICS_COMPUTE" ), this ); + connect( buttonCompute, SIGNAL( clicked() ), this, SLOT( clickOnCompute() ) ); + + QGridLayout* scalarRangeLayout = new QGridLayout(); + scalarRangeLayout->setMargin( 11 ); settingsLayout->setSpacing( 6 ); + + scalarRangeLayout->addWidget( minLabel, 0, 0 ); + scalarRangeLayout->addWidget( myMin, 0, 1 ); + scalarRangeLayout->addWidget( maxLabel, 1, 0 ); + scalarRangeLayout->addWidget( myMax, 1, 1 ); + scalarRangeLayout->addWidget( buttonCompute, 0, 2, 2, 1 ); + + myScalarRangeBox->setLayout( scalarRangeLayout ); + + /********************** Buttons **********************/ + + myButtonPlot = new QPushButton( tr( "GEOM_PLOT_DISTRIBUTION" ), this ); + myButtonCreateGr = new QPushButton( tr( "GEOM_SHAPE_STATISTICS_CREATE_GROUPS" ), this ); + QPushButton* buttonClose = new QPushButton( tr( "GEOM_BUT_CLOSE" ), this ); + QPushButton* buttonHelp = new QPushButton( tr( "GEOM_BUT_HELP" ), this ); + + QHBoxLayout* buttonsLayout = new QHBoxLayout(); + buttonsLayout->addWidget( myButtonPlot ); + buttonsLayout->addWidget( myButtonCreateGr ); + buttonsLayout->addWidget( buttonClose ); + buttonsLayout->addWidget( buttonHelp ); + + if ( !aShape.IsNull() ) { + myButtonCreateGr->hide(); + } + /********************** Layouting **********************/ + + topLayout->addLayout( settingsLayout ); + topLayout->addWidget( myScalarRangeBox ); + topLayout->addLayout( buttonsLayout ); + + // Signals and slots connections + + connect( selBtn, SIGNAL( clicked() ), this, SLOT( onEditMainShape() ) ); + + connect( myButtonPlot, SIGNAL( clicked() ), this, SLOT( clickOnPlot() ) ); + connect( myButtonCreateGr, SIGNAL( clicked() ), this, SLOT( clickOnCreateGroups() ) ); + + connect( buttonClose, SIGNAL( clicked() ), this, SLOT( reject() ) ); + connect( buttonHelp, SIGNAL( clicked() ), this, SLOT( clickOnHelp() ) ); + + connect(myApp->selectionMgr(), + SIGNAL(currentSelectionChanged()), this, SLOT(onEditMainShape())); + + if ( aShape.IsNull() ) + onEditMainShape(); +} + +//=========================================================================== +// function : ~MeasureGUI_ShapeStatisticsDlg() +// purpose : Destroys the object and frees any allocated resources +//=========================================================================== +MeasureGUI_ShapeStatisticsDlg::~MeasureGUI_ShapeStatisticsDlg() +{ +} + +//================================================================================= +// function : onEditMainShape() +// purpose : called when selection button was clicked +//================================================================================= +void MeasureGUI_ShapeStatisticsDlg::onEditMainShape() +{ + // restore initial parameters for dialog box + myEditMainShape->setText(""); + myEditMainShape->setFocus(); + + //get shapes from selection + QList selShapes = getSelected( TopAbs_SHAPE, -1 ); + + myButtonPlot->setEnabled( !selShapes.isEmpty() ); + myButtonCreateGr->setEnabled( selShapes.count() == 1 ); + + if ( !selShapes.isEmpty() ) { + if ( selShapes.count() == 1 ) + myMainObj = selShapes[0].get(); + QString aName = selShapes.count() > 1 ? QString( "%1_objects").arg( selShapes.count() ) : GEOMBase::GetName( myMainObj ); + myEditMainShape->setText( aName ); + } + + updateTypes( selShapes ); +} + +//================================================================================= +// function : currentType() +// purpose : returns currently selected type of shapes in 'Type' combobox +//================================================================================= +void MeasureGUI_ShapeStatisticsDlg::fillTypes( bool hasEdges, bool hasFaces, bool hasSolids ) +{ + if ( hasEdges ) + myCBTypes->addItem( tr("GEOM_SHAPE_STATISTICS_LENGTH"), 0 ); + if ( hasFaces ) + myCBTypes->addItem( tr("GEOM_SHAPE_STATISTICS_AREA"), 1 ); + if ( hasSolids ) + myCBTypes->addItem( tr("GEOM_SHAPE_STATISTICS_VOLUME"), 2 ); + + myCBTypes->setEnabled( myCBTypes->count() > 0 ); +} + +//================================================================================= +// function : updateTypes() +// purpose : update 'Type' combobox with available types +//================================================================================= +void MeasureGUI_ShapeStatisticsDlg::updateTypes( QList theShapes) +{ + myCBTypes->clear(); + myCBTypes->setEnabled( false ); + + int hasEdges = -1, hasFaces = -1, hasSolids = -1; + + myShapes.clear(); + // get types of the shapes and its sub-shapes + foreach( GEOM::GeomObjPtr aShapePtr, theShapes ) { + if ( !aShapePtr ) { + hasEdges, hasFaces, hasSolids = 0; + return; + } + TopoDS_Shape aShape; + if ( !GEOMBase::GetShape( aShapePtr.get(), aShape ) || aShape.IsNull() ) { + hasEdges, hasFaces, hasSolids = 0; + return; + } + + myShapes.push_back( aShape ); + + GEOM::ListOfLong_var aSubShapes; + GEOM::GEOM_IShapesOperations_var aShOp = getGeomEngine()->GetIShapesOperations( getStudyId() ); + if ( hasEdges != 0 ) { + aSubShapes = aShOp->SubShapeAllIDs( aShapePtr.get(), TopAbs_EDGE, false ); + hasEdges = aSubShapes->length() > 0; + } + if ( hasFaces != 0 ) { + aSubShapes = aShOp->SubShapeAllIDs( aShapePtr.get(), TopAbs_FACE, false ); + hasFaces = aSubShapes->length() > 0; + } + if ( hasSolids != 0 ) { + aSubShapes = aShOp->SubShapeAllIDs( aShapePtr.get(), TopAbs_SOLID, false ); + hasSolids = aSubShapes->length() > 0; + } + } + fillTypes( hasEdges, hasFaces, hasSolids ); +} + +//================================================================================= +// function : currentType() +// purpose : returns currently selected type of shapes in 'Type' combobox +//================================================================================= +TopAbs_ShapeEnum MeasureGUI_ShapeStatisticsDlg::currentType() +{ + switch ( myCBTypes->itemData( myCBTypes->currentIndex() ).toInt() ) { + case 0: + return TopAbs_EDGE; + case 1: + return TopAbs_FACE; + case 2: + return TopAbs_SOLID; + } +} + +//================================================================================= +// function : clickOnPlot() +// purpose : called when Plot button was clicked +//================================================================================= +bool MeasureGUI_ShapeStatisticsDlg::checkInput() +{ + if ( myMin->text().isEmpty() ) { + showError( tr("GEOM_SHAPE_STATISTICS_MIN_ERROR") ); + return false; + } + if ( myMax->text().isEmpty() ) { + showError( tr("GEOM_SHAPE_STATISTICS_MAX_ERROR" ) ); + return false; + } + if (myMin->text().toDouble() > myMax->text().toDouble()) { + showError( tr("GEOM_SHAPE_STATISTICS_MIN_MAX_ERROR" ) ); + return false; + } + return true; +} +//================================================================================= +// function : clickOnPlot() +// purpose : called when Plot button was clicked +//================================================================================= +void MeasureGUI_ShapeStatisticsDlg::clickOnPlot() +{ + GEOMUtils::Range aRange; + if ( myScalarRangeBox->isChecked() ) { + if ( !checkInput() ) + return; + aRange.min = myMin->text().toDouble(); + aRange.max = myMax->text().toDouble(); + } else { + aRange.min = -1.0; // flag that range is empty + } + + GEOMUtils::Distribution aShapesDistr = + GEOMUtils::ComputeDistribution( myShapes, currentType(), myNbIntervals->value(), aRange ); + + QList xVals, yVals; + double width = -1, min = -1; + double xmin = 1e+32, xmax = 0.0, ymax = 0.0; + int i=0; + GEOMUtils::Distribution::const_iterator it; + for (it = aShapesDistr.begin(); it != aShapesDistr.end(); it++) { + GEOMUtils::Range ran = *it; + if ( width < 0 ) width = ran.max - ran.min; // bar width + if ( min < 0 ) min = ran.min; // global min + xVals << width / 2. + i*width + min; // get a middle of bar + yVals << ran.count; + // get global boundary max values + if ( ran.min < xmin ) xmin = ran.min; + if ( ran.max > xmax ) xmax = ran.max; + if ( ran.count > ymax ) ymax = ran.count; + i++; + } + + // plot the computed distribution + SUIT_ViewManager* aViewManager = myApp->getViewManager( Plot2d_Viewer::Type(), true ); // create if necessary + if( !aViewManager ) + return; + Plot2d_Viewer* aView = dynamic_cast(aViewManager->getViewModel()); + if ( !aView ) + return; + Plot2d_ViewWindow* aViewWnd = dynamic_cast(aViewManager->getActiveView()); + if( !aViewWnd ) + return; + aViewWnd->setFocus(); + Plot2d_ViewFrame* aPlot = aViewWnd->getViewFrame(); + if ( !aPlot ) + return; + + aPlot->EraseAll(); + + // create or reuse histogram + if( !myHistogram ) + myHistogram = new Plot2d_Histogram(); + else + myHistogram->clearAllPoints(); + // set histogram parameters + myHistogram->setData( xVals, yVals ); + if ( width != 0.0 ) + myHistogram->setWidth( width ); + myHistogram->setAutoAssign(true); + myHistogram->setName( myEditMainShape->text() ); + myHistogram->setHorTitle( myCBTypes->currentText() ); + myHistogram->setVerTitle( tr("GEOM_SHAPE_STATISTICS_DISTRIBUTION_NB_ENT") ); + myHistogram->setColor( QColor(0, 85, 0) ); + // display histogram + aPlot->displayObject( myHistogram, true ); + if ( width == 0.0 ) // only one X value + aPlot->fitAll(); + else + aPlot->fitData( 0, xmin, xmax, 0.0, ymax ); +} + +//================================================================================= +// function : clickOnCompute() +// purpose : called when Compute button was clicked +//================================================================================= +void MeasureGUI_ShapeStatisticsDlg::clickOnCompute() +{ + GEOMUtils::Range aRange; + aRange.min = -1.0; // flag that range is empty + std::map measures = GEOMUtils::ComputeMeasures( myShapes, currentType(), aRange ); + if ( measures.size() != 0 ) { + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + int aPrecision = resMgr->integerValue( "Geometry", "length_precision", 6 ); + myMin->setText( DlgRef::PrintDoubleValue( aRange.min, aPrecision ) ); + myMax->setText( DlgRef::PrintDoubleValue( aRange.max, aPrecision ) ); + } +} + +//================================================================================= +// function : clickOnCreateGroups() +// purpose : called when Create Groups button was clicked +//================================================================================= +void MeasureGUI_ShapeStatisticsDlg::clickOnCreateGroups() +{ + GEOM::GEOM_IGroupOperations_var anOper = GEOM::GEOM_IGroupOperations::_narrow(getOperation()); + + GEOMUtils::Range aRange; + if ( myScalarRangeBox->isChecked() ) { + if ( !checkInput() ) + return; + aRange.min = myMin->text().toDouble(); + aRange.max = myMax->text().toDouble(); + } else { + aRange.min = -1.0; // flag that range is empty + } + + GEOMUtils::Distribution aShapesDistr = + GEOMUtils::ComputeDistribution( myShapes, currentType(), myNbIntervals->value(), aRange ); + + GEOMUtils::Distribution::const_iterator it; + for (it = aShapesDistr.begin(); it != aShapesDistr.end(); it++) { + std::list idList = (*it).indices; + int nn = idList.size(); + if ( nn > 0 ) { + GEOM::ListOfLong_var aNewList = new GEOM::ListOfLong; + aNewList->length(nn); + int ii = 0; + std::list::const_iterator id_it; + for ( id_it = idList.begin(); id_it != idList.end(); id_it++ ) { + aNewList[ii] = *id_it; + ii++; + } + + if (CORBA::is_nil(myMainObj)) + return; + + GEOM::GEOM_Object_var aGroup; + aGroup = anOper->CreateGroup( myMainObj, currentType() ); + + if (CORBA::is_nil(aGroup) || !anOper->IsDone()) + return; + + GEOM::ListOfLong_var aCurrList = anOper->GetObjects(aGroup); + if (!anOper->IsDone()) + return; + + if (aCurrList->length() > 0) + { + anOper->DifferenceIDs(aGroup, aCurrList); + if (!anOper->IsDone()) + return; + } + + anOper->UnionIDs(aGroup, aNewList); + if (!anOper->IsDone()) + return; + } + } +} + +//================================================================================= +// function : clickOnHelp() +// purpose : called when Help button was clicked +//================================================================================= +void MeasureGUI_ShapeStatisticsDlg::clickOnHelp() +{ + GeometryGUI* aGeomGUI = dynamic_cast( myApp->module( "Geometry" ) ); + myApp->onHelpContextModule( aGeomGUI ? myApp->moduleName( aGeomGUI->moduleName() ) : QString(""), "create_sketcher_page.html" ); +} diff --git a/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.h b/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.h new file mode 100644 index 000000000..64c39f3bf --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.h @@ -0,0 +1,86 @@ +// Copyright (C) 2015 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_ShapeStatisticsDlg.h +// Author : Alexander KOVALEV, Open CASCADE (alexander.kovalev@opencascade.com) +// +#ifndef MEASUREGUI_SHAPESTATISTICSDLG_H +#define MEASUREGUI_SHAPESTATISTICSDLG_H + +// GEOM includes +#include +#include "GEOM_GenericObjPtr.h" + +// Qt includes +#include +#include +#include +#include + +// Qtx includes +#include +#include + +class Plot2d_Histogram; + +//========================================================================== +// class : MeasureGUI_ShapeStatisticsDlg +// purpose : +//========================================================================== + +class MeasureGUI_ShapeStatisticsDlg : public QDialog, public GEOMBase_Helper +{ + Q_OBJECT + +public: + MeasureGUI_ShapeStatisticsDlg( QWidget*, TopoDS_Shape aShape = TopoDS_Shape(), TopAbs_ShapeEnum aSubShapeType = TopAbs_SHAPE ); + ~MeasureGUI_ShapeStatisticsDlg(); + +private slots: + void onEditMainShape(); + void clickOnCompute(); + void clickOnPlot(); + void clickOnCreateGroups(); + void clickOnHelp(); + +private: + void fillTypes( bool, bool, bool ); + void updateTypes( QList theShapes ); + TopAbs_ShapeEnum currentType(); + bool checkInput(); + +private: + SalomeApp_Application* myApp; + QPointer myViewWindow; + QLineEdit* myEditMainShape; + QtxComboBox* myCBTypes; + std::list myShapes; + GEOM::GEOM_Object_var myMainObj; + QtxIntSpinBox* myNbIntervals; + QGroupBox* myScalarRangeBox; + QLineEdit* myMin; + QLineEdit* myMax; + QPushButton* myButtonPlot; + QPushButton* myButtonCreateGr; + Plot2d_Histogram* myHistogram; + +}; + +#endif // MEASUREGUI_SHAPESTATISTICSDLG_H -- 2.39.2