From: akl Date: Thu, 23 Apr 2015 08:42:06 +0000 (+0400) Subject: 22853: EDF 9924 GEOM: Dimension histogram X-Git-Tag: V7_7_0a1~31 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=59b5446863dc5eea40bbc83261d976760cdc395d;p=modules%2Fgeom.git 22853: EDF 9924 GEOM: Dimension histogram --- diff --git a/doc/salome/gui/GEOM/images/editgroup.png b/doc/salome/gui/GEOM/images/editgroup.png index c7f55074e..4501fa61f 100755 Binary files a/doc/salome/gui/GEOM/images/editgroup.png and b/doc/salome/gui/GEOM/images/editgroup.png differ diff --git a/doc/salome/gui/GEOM/images/geomcreategroup.png b/doc/salome/gui/GEOM/images/geomcreategroup.png index 0f67a625c..c982f0bc9 100755 Binary files a/doc/salome/gui/GEOM/images/geomcreategroup.png and b/doc/salome/gui/GEOM/images/geomcreategroup.png differ diff --git a/doc/salome/gui/GEOM/images/shape_statistics.png b/doc/salome/gui/GEOM/images/shape_statistics.png new file mode 100644 index 000000000..2aaaa9ad3 Binary files /dev/null and b/doc/salome/gui/GEOM/images/shape_statistics.png differ diff --git a/doc/salome/gui/GEOM/images/shape_statistics_simple.png b/doc/salome/gui/GEOM/images/shape_statistics_simple.png new file mode 100644 index 000000000..bc2c0767b Binary files /dev/null and b/doc/salome/gui/GEOM/images/shape_statistics_simple.png differ diff --git a/doc/salome/gui/GEOM/input/shape_statistics_operation.doc b/doc/salome/gui/GEOM/input/shape_statistics_operation.doc new file mode 100644 index 000000000..207db3b75 --- /dev/null +++ b/doc/salome/gui/GEOM/input/shape_statistics_operation.doc @@ -0,0 +1,28 @@ +/*! + +\page shape_statistics_operation_page Shape Statistics + +This operation allows plotting a distribution histogram for the numerical parameters and creating the corresponding geometrical groups of the given shape. + +To call Shape Statistics dialog box, in the Main Menu select Inspection - > Shape Statistics. + +\image html shape_statistics.png + +In this dialog: +- "Selected objects" standard selection box allows selecting one or more geometrical objects. + +- "Type" combo-box with the following items: "Edges length", "Faces area", "Solids volume". +\note "Type" combo-box includes only parameters applied to the currently selected shape (e.g. "Solids volume" will not be available for face or shell being selected); multiple selection is processed correspondingly (i.e. only types applicable for all selected shapes will be available). + +- "Number of intervals" spin box is used to specify number of distribution histogram ranges. + +- "Scalar range" checkable group box that, when switched ON, allows specifying custom values range used for plotting and creating groups. +\note By default, "Scalar range" controls is empty; pressing "Compute" button allows automatic computing initial range of the chosen parameter. This is needed as computation of the parameters range can be time-consuming for large or complex models. In case of multiple selection, scalar range is computed as common from all selected shapes. + +- "Plot" button opens or uses an opened Plot2d viewer and plots the distribution histogram for the selected shape(s). + +- "Create groups" button allows creating a groups according to the currently specified parameters. The groups names will include numerical values of the range, e.g. "Edges_length_0-20", "Edges_length_20-40", etc. Empty groups are not created. + +- Close dialog box, by pressing Close button. + +*/ diff --git a/doc/salome/gui/GEOM/input/using_measurement_tools.doc b/doc/salome/gui/GEOM/input/using_measurement_tools.doc index 77a5ee4b3..515a94ce4 100644 --- a/doc/salome/gui/GEOM/input/using_measurement_tools.doc +++ b/doc/salome/gui/GEOM/input/using_measurement_tools.doc @@ -19,6 +19,7 @@
  • \subpage managing_dimensions_page "Dimensions"
  • \subpage whatis_page "WhatIs"
  • \subpage inspect_object_operation_page "Inspect Object"
  • +
  • \subpage shape_statistics_operation_page "Shape Statistics"
  • \n To check their integrity: diff --git a/doc/salome/gui/GEOM/input/working_with_groups.doc b/doc/salome/gui/GEOM/input/working_with_groups.doc index 36a0d49a3..df36fd6a2 100644 --- a/doc/salome/gui/GEOM/input/working_with_groups.doc +++ b/doc/salome/gui/GEOM/input/working_with_groups.doc @@ -24,7 +24,7 @@ This functionality is available in OCC viewer only. To create a group of sub-shapes of a geometrical object in the main menu select New entity > Group > Create -\n The following menu will appear: +\n The following dialog box will appear: \image html geomcreategroup.png @@ -101,6 +101,11 @@ In order to filter out some entities: The entities which satisfy entered filtering parameters will be automatically highlighted in the 3D viewer. +\b Plot button into "Filter" group box provides an access +to the \ref shape_statistics_operation_page "Shape Statistics" functionality with simplified look-n-feel: + +\image html shape_statistics_simple.png + \n TUI Command: geompy.CreateGroup(MainShape, ShapeType), where MainShape is a shape for which the group is created, ShapeType is a type of shapes in the created group. 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/GEOMBase/GEOMBase.cxx b/src/GEOMBase/GEOMBase.cxx index e10909ddc..0cfe8f6ae 100644 --- a/src/GEOMBase/GEOMBase.cxx +++ b/src/GEOMBase/GEOMBase.cxx @@ -859,7 +859,7 @@ QString GEOMBase::GetEntry( GEOM::GEOM_Object_ptr object ) // Function : PublishSubObject // Purpose : Publish sub-shape under the main object //================================================================ -void GEOMBase::PublishSubObject( GEOM::GEOM_Object_ptr object ) +void GEOMBase::PublishSubObject( GEOM::GEOM_Object_ptr object, const QString& name ) { SalomeApp_Study* study = dynamic_cast( SUIT_Session::session()->activeApplication()->activeStudy() ); if ( study && !CORBA::is_nil( object ) ) { @@ -868,9 +868,9 @@ void GEOMBase::PublishSubObject( GEOM::GEOM_Object_ptr object ) GEOM::GEOM_Object_var father = object->GetMainShape(); QString fatherEntry = GetEntry( father ); if ( entry.isEmpty() && !CORBA::is_nil( father ) && !fatherEntry.isEmpty() ) { - QString name = GetName( object ); + QString aName = !name.isEmpty() ? name : GetName( object ); GeometryGUI::GetGeomGen()->AddInStudy( GeometryGUI::ClientStudyToStudy( studyDS ), - object, name.toLatin1().data(), father.in() ); + object, aName.toLatin1().data(), father.in() ); } } } diff --git a/src/GEOMBase/GEOMBase.h b/src/GEOMBase/GEOMBase.h index 242e5fdcd..69e21e778 100644 --- a/src/GEOMBase/GEOMBase.h +++ b/src/GEOMBase/GEOMBase.h @@ -133,7 +133,7 @@ public : static QString GetEntry( GEOM::GEOM_Object_ptr object ); /* Publish sub-shape under the main object */ - static void PublishSubObject( GEOM::GEOM_Object_ptr object ); + static void PublishSubObject( GEOM::GEOM_Object_ptr object, const QString& name = QString() ); static void Synchronize( QList& left, QList& right ); }; diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index c1e7addb1..c67b290fe 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,69 @@ 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 + + + GEOM_MSG_GROUPS_CREATED + %1 groups created + + TransformationGUI_ExtensionDlg diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 69786b158..0ab7e34fc 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,69 @@ 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 + + + GEOM_MSG_GROUPS_CREATED + %1 groups created + + TransformationGUI_ExtensionDlg diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts index 6b5668ec8..75807fcc7 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,69 @@ 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 + + + GEOM_MSG_GROUPS_CREATED + %1 groups created + + 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..81ae5aeba --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_ShapeStatistics.cxx @@ -0,0 +1,145 @@ +// 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 aSubShapesMap; + TopExp::MapShapes(*it, aSubShapesMap); // map of all global indices + TopTools_IndexedMapOfShape aMx; + TopExp::MapShapes( *it, entity, aMx ); // map of current type sub-shape indices + int aNbS = aMx.Extent(); + int index = -1; + for ( int i = 1; i <= aNbS; ++i ) { + aMeasure = 0.0; + const TopoDS_Shape& aSubShape = aMx( i ); + //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; + } + // get global index of sub-shape + index = aSubShapesMap.FindIndex( aSubShape ); + // 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; +} + +} //namespace GEOMUtils diff --git a/src/GEOMUtils/GEOMUtils_ShapeStatistics.hxx b/src/GEOMUtils/GEOMUtils_ShapeStatistics.hxx new file mode 100644 index 000000000..703050e51 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_ShapeStatistics.hxx @@ -0,0 +1,61 @@ +// 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 ); + +} + +#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..9387cf4a8 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.cxx @@ -0,0 +1,533 @@ +// 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 +#include + +// Qt includes +#include +#include +#include +#include + +// Qtx includes +#include + +// OCC includes +#include + +#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 ); + + 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() ); + + 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 ); + myButtonPlot->setDefault( true ); + 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 : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr MeasureGUI_ShapeStatisticsDlg::createOperation() +{ + return getGeomEngine()->GetIGroupOperations(getStudyId()); +} + +#define RETURN_WITH_MSG(a, b) \ + if (!(a)) { \ + theMessage += (b); \ + return false; \ + } + +//================================================================ +// Function : getFather +// Purpose : Get father object for object to be added in study +// (called with addInStudy method) +//================================================================ +GEOM::GEOM_Object_ptr MeasureGUI_ShapeStatisticsDlg::getFather(GEOM::GEOM_Object_ptr theObj) +{ + GEOM::GEOM_Object_var aFatherObj; + if (theObj->GetType() == GEOM_GROUP) { + GEOM::GEOM_IGroupOperations_var anOper = GEOM::GEOM_IGroupOperations::_narrow(getOperation()); + aFatherObj = anOper->GetMainShape(theObj); + } + return aFatherObj._retn(); +} + +//================================================================================= +// function : getSourceObjects +// purpose : virtual method to get source objects +//================================================================================= +QList MeasureGUI_ShapeStatisticsDlg::getSourceObjects() +{ + QList res; + res << myMainObj; + return res; +} + +//================================================================================= +// 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]; + QString aName = selShapes.count() > 1 ? QString( "%1_objects").arg( selShapes.count() ) : GEOMBase::GetName( myMainObj.get() ); + 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"), (int)TopAbs_EDGE ); + if ( hasFaces ) + myCBTypes->addItem( tr("GEOM_SHAPE_STATISTICS_AREA"), (int)TopAbs_FACE ); + if ( hasSolids ) + myCBTypes->addItem( tr("GEOM_SHAPE_STATISTICS_VOLUME"), (int)TopAbs_SOLID ); + + 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 ) + return; + + TopoDS_Shape aShape; + if ( !GEOMBase::GetShape( aShapePtr.get(), aShape ) || aShape.IsNull() ) + return; + + myShapes.push_back( aShape ); + + GEOM::ListOfLong_var aSubShapes; + GEOM::GEOM_IShapesOperations_var aShOp = getGeomEngine()->GetIShapesOperations( getStudyId() ); + if ( hasEdges != 0 ) + hasEdges = aShOp->NumberOfSubShapes( aShapePtr.get(), TopAbs_EDGE ) > 0; + if ( hasFaces != 0 ) + hasEdges = aShOp->NumberOfSubShapes( aShapePtr.get(), TopAbs_FACE ) > 0; + if ( hasSolids != 0 ) + hasEdges = aShOp->NumberOfSubShapes( aShapePtr.get(), TopAbs_SOLID ) > 0; + } + fillTypes( hasEdges, hasFaces, hasSolids ); +} + +//================================================================================= +// function : currentType() +// purpose : returns currently selected type of shapes in 'Type' combobox +//================================================================================= +TopAbs_ShapeEnum MeasureGUI_ShapeStatisticsDlg::currentType() +{ + return (TopAbs_ShapeEnum)( myCBTypes->itemData( myCBTypes->currentIndex() ).toInt() ); +} + +//================================================================================= +// function : clickOnPlot() +// purpose : called when Plot button was clicked +//================================================================================= +bool MeasureGUI_ShapeStatisticsDlg::isValid(QString& theMessage) +{ + if ( myScalarRangeBox->isChecked() ) { + RETURN_WITH_MSG( !myMin->text().isEmpty(), tr("GEOM_SHAPE_STATISTICS_MIN_ERROR") ) + RETURN_WITH_MSG( !myMax->text().isEmpty(), tr("GEOM_SHAPE_STATISTICS_MAX_ERROR") ) + RETURN_WITH_MSG( myMin->text().toDouble() <= myMax->text().toDouble(), tr("GEOM_SHAPE_STATISTICS_MIN_MAX_ERROR") ) + } + return true; +} +//================================================================================= +// function : clickOnPlot() +// purpose : called when Plot button was clicked +//================================================================================= +void MeasureGUI_ShapeStatisticsDlg::clickOnPlot() +{ + GEOMUtils::Range aRange; + if ( myScalarRangeBox->isChecked() ) { + QString msg; + if ( !isValid( msg ) ) { + showError( msg ); + return; + } + aRange.min = myMin->text().toDouble(); + aRange.max = myMax->text().toDouble(); + } else { + aRange.min = -1.0; // flag that range is empty + aRange.max = -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_ViewWindow* aViewWnd = dynamic_cast(aViewManager->getActiveView()); + if( !aViewWnd ) + return; + 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 + aRange.max = -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() +{ + onAccept(false, false, false); +} + +//================================================================================= +// function : execute(ObjectList& objects) +// purpose : +//================================================================================= +bool MeasureGUI_ShapeStatisticsDlg::execute(ObjectList& objects) +{ + if ( myMainObj.isNull() ) + return false; + + GEOM::GroupOpPtr anOper = GEOM::GEOM_IGroupOperations::_narrow(getOperation()); + + GEOMUtils::Range aRange; + if ( myScalarRangeBox->isChecked() ) { + QString msg; + if ( !isValid( msg ) ) { + showError( msg ); + return false; + } + aRange.min = myMin->text().toDouble(); + aRange.max = myMax->text().toDouble(); + } else { + aRange.min = -1.0; // flag that range is empty + aRange.max = -1.0; // flag that range is empty + } + + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + int aPrecision = resMgr->integerValue( "Geometry", "length_precision", 6 ); + QString aTypePrefix = myCBTypes->currentText().replace(' ', '_'); + QString objIOR, aMin, aMax, aGroupName; + SalomeApp_Study* study = getStudy(); + + GEOMUtils::Distribution aShapesDistr = + GEOMUtils::ComputeDistribution( myShapes, currentType(), myNbIntervals->value(), aRange ); + + int nbGroups = 0; + + 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; + } + + // Create an empty group + GEOM::GEOM_Object_var aGroup; + aGroup = anOper->CreateGroup( myMainObj.get(), currentType() ); + + if (CORBA::is_nil(aGroup) || !anOper->IsDone()) + return false; + + // Add sub-shapes into group + anOper->UnionIDs(aGroup, aNewList); + if (!anOper->IsDone()) + return false; + + // publish group + aMin = DlgRef::PrintDoubleValue( (*it).min, aPrecision ); + aMax = DlgRef::PrintDoubleValue( (*it).max, aPrecision ); + aGroupName = aTypePrefix + "_" + aMin + "_" + aMax; + GEOMBase::PublishSubObject( aGroup, aGroupName ); + + // this is needed just to avoid error message + objects.push_back(aGroup._retn()); + + nbGroups++; + } + } + + SUIT_MessageBox::information( this, tr( "INF_INFO" ), tr( "GEOM_MSG_GROUPS_CREATED" ).arg( nbGroups ) ); + + return true; +} + +//================================================================================= +// 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(""), "shape_statistics_operation_page.html" ); +} diff --git a/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.h b/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.h new file mode 100644 index 000000000..80131321b --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.h @@ -0,0 +1,92 @@ +// 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(); + +protected: + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + virtual bool isValid (QString&); + virtual bool execute (ObjectList&); + virtual GEOM::GEOM_Object_ptr getFather (GEOM::GEOM_Object_ptr); + virtual QList getSourceObjects(); + +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(); + +private: + SalomeApp_Application* myApp; + QLineEdit* myEditMainShape; + QtxComboBox* myCBTypes; + std::list myShapes; + GEOM::GeomObjPtr myMainObj; + QtxIntSpinBox* myNbIntervals; + QGroupBox* myScalarRangeBox; + QLineEdit* myMin; + QLineEdit* myMax; + QPushButton* myButtonPlot; + QPushButton* myButtonCreateGr; + Plot2d_Histogram* myHistogram; + +}; + +#endif // MEASUREGUI_SHAPESTATISTICSDLG_H