From 6b4b2b09efa11c7596b665771c90490c13fb4a9a Mon Sep 17 00:00:00 2001 From: skv Date: Fri, 18 Dec 2015 17:30:19 +0300 Subject: [PATCH] Statistics of the operation --- doc/salome/examples/canrecplugindemo.py | 7 ++ .../CANRECPLUGIN/images/canrec_plugin_dlg.png | Bin 11273 -> 23411 bytes .../images/canrec_plugin_dlg_stat.png | Bin 0 -> 12924 bytes .../input/canrecplugin_usage_page.doc | 17 +++- idl/CANRECPlugin.idl | 30 ++++++- .../CANRECPluginEngine_IOperations_i.cc | 66 +++++++++++++-- .../CANRECPluginEngine_IOperations_i.hh | 5 +- .../CANRECPluginImpl_Driver.cxx | 79 +++++++++++++++++- .../CANRECPluginImpl_Driver.hxx | 3 + .../CANRECPluginImpl_ICanRec.hxx | 5 ++ .../CANRECPluginImpl_IOperations.cxx | 61 +++++++++++++- .../CANRECPluginImpl_IOperations.hxx | 15 +++- ...ANRECPluginGUI_CanonicalRecognitionDlg.cxx | 69 +++++++++++++-- .../CANRECPluginGUI_CanonicalRecognitionDlg.h | 1 + .../resources/CANRECPlugin_msg_en.ts | 36 ++++++++ src/CANRECPLUGIN_PY/CANRECPluginBuilder.py | 31 ++++++- 16 files changed, 392 insertions(+), 33 deletions(-) create mode 100644 doc/salome/gui/CANRECPLUGIN/images/canrec_plugin_dlg_stat.png diff --git a/doc/salome/examples/canrecplugindemo.py b/doc/salome/examples/canrecplugindemo.py index c88ff1e..82b5541 100644 --- a/doc/salome/examples/canrecplugindemo.py +++ b/doc/salome/examples/canrecplugindemo.py @@ -13,6 +13,13 @@ shape_igs = geompy.ImportIGES(path) # Build Canonical Recognition shape_cr = geompy.MakeCanonicalRecognition(shape_igs, True, True, 0.01) +# Get the number of canonical faces +init_nb_f = geompy.GetNbCanonicalFaces(shape_igs) +res_nb_f = geompy.GetNbCanonicalFaces(shape_cr) + +print "Number of canonical faces in the initial shape: %s" % init_nb_f +print "Number of canonical faces in the result shape: %s" % res_nb_f + # Publish in the study geompy.addToStudy( shape_igs, 'Import from IGS' ) geompy.addToStudy( shape_cr, 'Canonical Recognition' ) diff --git a/doc/salome/gui/CANRECPLUGIN/images/canrec_plugin_dlg.png b/doc/salome/gui/CANRECPLUGIN/images/canrec_plugin_dlg.png index 1c724a937f2de304e5876f157f8c08416a5d6394..d7729996a0353900917e593b2e92294868333539 100644 GIT binary patch literal 23411 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 literal 11273 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 Recognition in the Main Menu select New E This Operation constructs a canonical recognition (convert, if possible, a NURBS geometry B-Spline / Bezier curve or surface to its analytical form) of an \b Object. To constructs the canonical recognition you need to define the shape. +\n Once you chose an object you can see the number of canonical faces in this object on the label below. \n Merge Surfaces checkbox allows to merge surfaces in the result shape. \n Merge Curves checkbox allows to merge curvies in the result shape. \n The \b Result of the operation will be any \b GEOM_Object. -\n TUI Command: geompy.MakeCanonicalRecognition(Shape, MergeSurf, MergeCurves), +\n TUI Commands: +
    +
  • geompy.MakeCanonicalRecognition(Shape, MergeSurf, MergeCurves, theTolerance=0.01), where Shape is a shape to be converted into canonical recognition, -MergeSurf and MergeCurv flags to merge surfaces / curves in the result shape. - +MergeSurf and MergeCurv flags to merge surfaces / curves in the result shape, +theTolerance is the tolerance of the operation. Default value is 0.01.
  • +
  • geompy.GetNbCanonicalFaces(Shape), where Shape is a shape to be tested. +Returns the number of canonical faces in this shape.
  • +
\n Arguments: Name + one object. \image html canrec_plugin_dlg.png +Once the user presses the \b Apply or Apply and Close buttons, +he will be given with the operation statistics information: + +\image html canrec_plugin_dlg_stat.png + \n \b Example: Our TUI Script provide you with useful example of the use of \ref canrec_example "Canonical Recognition". diff --git a/idl/CANRECPlugin.idl b/idl/CANRECPlugin.idl index 9bdad0a..3d57c46 100644 --- a/idl/CANRECPlugin.idl +++ b/idl/CANRECPlugin.idl @@ -24,6 +24,8 @@ module CANRECPlugin { + typedef sequence ListOfLong; + /*! * \brief Interface to Canonical Recognition modeling functions. */ @@ -36,13 +38,33 @@ module CANRECPlugin * \param theMergeSurf the flag to switch on/off merging surfaces in the result shape. * \param theMergeCurves the flag to switch on/off merging curves in the result shape. * \param theTolerance the tolerance of the canonical recognition operation. + * \param theStat the statistics of the operation. Output parameter. + * Each integer value in the sequence has its own meaning + * depending on its index: + * 0 - total number of faces in the initial shape; + * 1 - number of canonical faces in the initial shape; + * 2 - number of faces converted to the canonical form; + * 3 - number of merged surfaces; + * 4 - number of merged curves. + * Nagative value means that this value is not computed. * * \return New GEOM_Object, containing the canonical recognition of the input object. */ - GEOM::GEOM_Object MakeCanonicalRecognition ( in GEOM::GEOM_Object theObject, - in boolean theMergeSurf, - in boolean theMergeCurves, - in double theTolerance ); + GEOM::GEOM_Object MakeCanonicalRecognition + (in GEOM::GEOM_Object theObject, + in boolean theMergeSurf, + in boolean theMergeCurves, + in double theTolerance, + out ListOfLong theStat); + + /*! + * \brief Get the number of canonical faces in the shape. + * + * \param theObject the input object (solid, compound, compsolid). + * + * \return the number of canonical faces in the object. + */ + long GetNbCanonicalFaces(in GEOM::GEOM_Object theObject); }; }; diff --git a/src/CANRECPLUGINEngine/CANRECPluginEngine_IOperations_i.cc b/src/CANRECPLUGINEngine/CANRECPluginEngine_IOperations_i.cc index e6b3b6e..677edb7 100644 --- a/src/CANRECPLUGINEngine/CANRECPluginEngine_IOperations_i.cc +++ b/src/CANRECPLUGINEngine/CANRECPluginEngine_IOperations_i.cc @@ -49,27 +49,79 @@ GEOM::GEOM_Object_ptr CANRECPluginEngine_IOperations_i::MakeCanonicalRecognition( GEOM::GEOM_Object_ptr theObject, CORBA::Boolean theMergeSurf, CORBA::Boolean theMergeCurves, - CORBA::Double theTolerance ) + CORBA::Double theTolerance, + CANRECPlugin::ListOfLong_out theStat ) { + theStat = new CANRECPlugin::ListOfLong(); + // Set a not done flag GetOperations()->SetNotDone(); // Get the reference points Handle(GEOM_Object) anInitObject = GetObjectImpl( theObject ); - if ( anInitObject.IsNull() ) return GEOM::GEOM_Object::_nil(); + if ( anInitObject.IsNull() ) { + return GEOM::GEOM_Object::_nil(); + } // Make Canonical Recognition - Handle(GEOM_Object) anObject = GetOperations()->MakeCanonicalRecognition( anInitObject, - theMergeSurf, - theMergeCurves, - theTolerance ); - if ( !GetOperations()->IsDone() || anObject.IsNull() ) + Handle(TColStd_HSequenceOfInteger) aStat = new TColStd_HSequenceOfInteger; + Handle(GEOM_Object) anObject = + GetOperations()->MakeCanonicalRecognition(anInitObject, + theMergeSurf, + theMergeCurves, + theTolerance, + aStat); + + if (!GetOperations()->IsDone() || anObject.IsNull()) { return GEOM::GEOM_Object::_nil(); + } + + // Copy statistics. + int nbInts = aStat->Length(); + int i; + + theStat->length(nbInts); + + for (i = 0; i < nbInts; i++) { + theStat[i] = aStat->Value(i + 1); + } return GetObject( anObject ); } +//============================================================================= +/*! + * \brief Get the number of canonical faces in the shape. + * + * \param theObject the input object (solid, compound, compsolid). + * + * \return the number of canonical faces in the object. + */ +//============================================================================= +CORBA::Long CANRECPluginEngine_IOperations_i::GetNbCanonicalFaces + (GEOM::GEOM_Object_ptr theObject) +{ + // Set a not done flag + GetOperations()->SetNotDone(); + + // Get the reference points + Handle(GEOM_Object) anInitObject = GetObjectImpl(theObject); + + if (anInitObject.IsNull()) { + return -1; + } + + // Get the number of canonical faces. + CORBA::Long aResult = GetOperations()->GetNbCanonicalFaces(anInitObject); + + if (!GetOperations()->IsDone()) { + return -1; + } + + return aResult; +} + ::CANRECPluginImpl_IOperations* CANRECPluginEngine_IOperations_i::GetOperations() { return (::CANRECPluginImpl_IOperations*)GetImpl(); diff --git a/src/CANRECPLUGINEngine/CANRECPluginEngine_IOperations_i.hh b/src/CANRECPLUGINEngine/CANRECPluginEngine_IOperations_i.hh index 419c2c0..14502bb 100644 --- a/src/CANRECPLUGINEngine/CANRECPluginEngine_IOperations_i.hh +++ b/src/CANRECPLUGINEngine/CANRECPluginEngine_IOperations_i.hh @@ -43,7 +43,10 @@ class CANRECPLUGINENGINE_EXPORT CANRECPluginEngine_IOperations_i : GEOM::GEOM_Object_ptr MakeCanonicalRecognition ( GEOM::GEOM_Object_ptr theObject, CORBA::Boolean theMergeSurf, CORBA::Boolean theMergeCurves, - CORBA::Double theTolerance ); + CORBA::Double theTolerance, + CANRECPlugin::ListOfLong_out theStat ); + + CORBA::Long GetNbCanonicalFaces(GEOM::GEOM_Object_ptr theObject); CANRECPluginImpl_IOperations* GetOperations(); }; diff --git a/src/CANRECPLUGINEngine/CANRECPluginImpl_Driver.cxx b/src/CANRECPLUGINEngine/CANRECPluginImpl_Driver.cxx index 107776d..15f07e7 100644 --- a/src/CANRECPLUGINEngine/CANRECPluginImpl_Driver.cxx +++ b/src/CANRECPLUGINEngine/CANRECPluginImpl_Driver.cxx @@ -22,10 +22,19 @@ #include +#include #include +#include +#include #include +#include +#include +#include +#include + #include #include +#include #include #include @@ -35,12 +44,56 @@ #include #endif // CANREC_HASLICENSE +/** + * This function returns the number of shapes of a certain type. + * + * \param theShape the shape. + * \param theType the required type. + * \return the number of shapes of a certain type. + */ +static Standard_Integer GetNbShapes(const TopoDS_Shape &theShape, + const TopAbs_ShapeEnum theType) +{ + TopTools_IndexedMapOfShape aMapShapes; + + TopExp::MapShapes(theShape, theType, aMapShapes); + + const Standard_Integer aResult = aMapShapes.Extent(); + + return aResult; +} + const Standard_GUID& CANRECPluginImpl_Driver::GetID() { static Standard_GUID aGUID("7e1492bb-b4cd-4a40-ad8f-102902b0047e"); return aGUID; } +Standard_Integer CANRECPluginImpl_Driver::GetNbCanonicalFaces + (const TopoDS_Shape &theShape) +{ + TopExp_Explorer anExp(theShape, TopAbs_FACE); + TopLoc_Location aLoc; + Standard_Integer aNbSurf = 0; + TopTools_MapOfShape aMapFence; + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &aShFace = anExp.Current(); + + if (aMapFence.Add(aShFace)) { + TopoDS_Face aFace = TopoDS::Face(aShFace); + Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace, aLoc); + + if(aSurface->IsKind(STANDARD_TYPE(Geom_Plane)) || + ShapeConvert_Surface::IsCanonical(aSurface)) { + aNbSurf++; + } + } + } + + return aNbSurf; +} + CANRECPluginImpl_Driver::CANRECPluginImpl_Driver() { } @@ -86,6 +139,9 @@ Standard_Integer CANRECPluginImpl_Driver::Execute( TFunction_Logbook& log ) cons aRecognizer.SurfaceMode() = isNeedMergeSurf; aRecognizer.CurveMode() = isNeedMergeCurves; + const Standard_Integer anInitNbFaces = GetNbShapes(aShape, TopAbs_FACE); + const Standard_Integer anInitNbCanonical = GetNbCanonicalFaces(aShape); + // 1. Recognizing aRecognizer.SetShape( aShape ); aRecognizer.UnifyMode() = false; @@ -97,22 +153,41 @@ Standard_Integer CANRECPluginImpl_Driver::Execute( TFunction_Logbook& log ) cons aSewing.Add( aResultingShape ); aSewing.Perform(); aResultingShape = aSewing.SewedShape(); - + + const Standard_Integer aNbConverted = + GetNbCanonicalFaces(aResultingShape) - anInitNbCanonical; + Standard_Integer aNbMergedFaces = -1; + Standard_Integer aNbMergedEdges = -1; + // 3.1. Union Surfaces if ( isNeedMergeSurf ) { ShapeConvert_UnionFaces aFaceUnifier; aFaceUnifier.GetTolerance() = aTolerance; aResultingShape = aFaceUnifier.Perform( aResultingShape ); + aNbMergedFaces = anInitNbFaces - GetNbShapes(aResultingShape, TopAbs_FACE); } // 3.2. Union Curves if ( isNeedMergeCurves ) { ShapeConvert_UnionEdges anEdgeUnifier; - aResultingShape = anEdgeUnifier.Perform( aResultingShape, aTolerance ); + aNbMergedEdges = GetNbShapes(aResultingShape, TopAbs_EDGE); + aResultingShape = anEdgeUnifier.Perform( aResultingShape, aTolerance ); + aNbMergedEdges -= GetNbShapes(aResultingShape, TopAbs_EDGE); } if ( aResultingShape.IsNull() ) return 0; + // Create statistics + Handle(TColStd_HArray1OfInteger) aStat = new TColStd_HArray1OfInteger(1, 5); + + aStat->SetValue(1, anInitNbFaces); + aStat->SetValue(2, anInitNbCanonical); + aStat->SetValue(3, aNbConverted); + aStat->SetValue(4, aNbMergedFaces); + aStat->SetValue(5, aNbMergedEdges); + + aData.SetStatistics(aStat); + aFunction->SetValue( aResultingShape ); log.SetTouched( Label() ); diff --git a/src/CANRECPLUGINEngine/CANRECPluginImpl_Driver.hxx b/src/CANRECPLUGINEngine/CANRECPluginImpl_Driver.hxx index 68266ba..1b18418 100644 --- a/src/CANRECPLUGINEngine/CANRECPluginImpl_Driver.hxx +++ b/src/CANRECPLUGINEngine/CANRECPluginImpl_Driver.hxx @@ -22,6 +22,8 @@ #include +class TopoDS_Shape; + DEFINE_STANDARD_HANDLE( CANRECPluginImpl_Driver, GEOM_BaseDriver ); class CANRECPluginImpl_Driver : public GEOM_BaseDriver @@ -31,6 +33,7 @@ public: ~CANRECPluginImpl_Driver(); static const Standard_GUID& GetID(); + static Standard_Integer GetNbCanonicalFaces(const TopoDS_Shape &theShape); virtual Standard_Integer Execute( TFunction_Logbook& ) const; Standard_Boolean MustExecute( const TFunction_Logbook& ) const; virtual void Validate( TFunction_Logbook& ) const; diff --git a/src/CANRECPLUGINEngine/CANRECPluginImpl_ICanRec.hxx b/src/CANRECPLUGINEngine/CANRECPluginImpl_ICanRec.hxx index 111aa48..41a578e 100644 --- a/src/CANRECPLUGINEngine/CANRECPluginImpl_ICanRec.hxx +++ b/src/CANRECPLUGINEngine/CANRECPluginImpl_ICanRec.hxx @@ -21,11 +21,13 @@ #define __CANRECPLUGINIMPL_ICANREC_HXX #include +#include #define CanonicalRecognition_ARG_NeedMergeSurf 1 #define CanonicalRecognition_ARG_NeedMergeCurves 2 #define CanonicalRecognition_ARG_Tolerance 3 #define CanonicalRecognition_ARG_Object 4 +#define CanonicalRecognition_ARG_Stat 5 class CANRECPluginImpl_ICanRec { @@ -44,6 +46,9 @@ public: void SetObject(Handle(GEOM_Function) anInitialObject) { _func->SetReference(CanonicalRecognition_ARG_Object, anInitialObject); } Handle(GEOM_Function) GetObject() { return _func->GetReference(CanonicalRecognition_ARG_Object); } + void SetStatistics(const Handle(TColStd_HArray1OfInteger) &theStat) { _func->SetIntegerArray(CanonicalRecognition_ARG_Stat, theStat); } + Handle(TColStd_HArray1OfInteger) GetStatistics() { return _func->GetIntegerArray(CanonicalRecognition_ARG_Stat); } + private: Handle(GEOM_Function) _func; }; diff --git a/src/CANRECPLUGINEngine/CANRECPluginImpl_IOperations.cxx b/src/CANRECPLUGINEngine/CANRECPluginImpl_IOperations.cxx index 9fdb532..81b20d8 100644 --- a/src/CANRECPLUGINEngine/CANRECPluginImpl_IOperations.cxx +++ b/src/CANRECPLUGINEngine/CANRECPluginImpl_IOperations.cxx @@ -46,17 +46,27 @@ CANRECPluginImpl_IOperations::~CANRECPluginImpl_IOperations() * \param theMergeCurves set merging curves * \param theTolerance set tolerance * \param theObject is initial object + * \param theStat is the statistics. A set of integers. For details please + * see CANRECPlugin.idl * \return New GEOM_Object, containing the created shape. */ //============================================================================= Handle(GEOM_Object) -CANRECPluginImpl_IOperations::MakeCanonicalRecognition ( Handle(GEOM_Object) theObject, - bool theMergeSurf, - bool theMergeCurves, - double theTolerance ) +CANRECPluginImpl_IOperations::MakeCanonicalRecognition + (Handle(GEOM_Object) theObject, + bool theMergeSurf, + bool theMergeCurves, + double theTolerance, + Handle_TColStd_HSequenceOfInteger &theStat) { SetErrorCode( KO ); + if (theStat.IsNull()) { + theStat = new TColStd_HSequenceOfInteger; + } else { + theStat->Clear(); + } + if ( theObject.IsNull() ) return NULL; // Add a new object @@ -92,6 +102,17 @@ CANRECPluginImpl_IOperations::MakeCanonicalRecognition ( Handle(GEOM_Object) the SetErrorCode( aFail->GetMessageString() ); return NULL; } + + Handle(TColStd_HArray1OfInteger) anArray = aData.GetStatistics(); + + if (anArray.IsNull() == Standard_False) { + Standard_Integer i = anArray->Lower(); + const Standard_Integer iUp = anArray->Upper(); + + for (; i <= iUp; ++i) { + theStat->Append(anArray->Value(i)); + } + } // Make a Python command GEOM::TPythonDump(aFunction) << aShape << " = " << "geompy.MakeCanonicalRecognition(" << @@ -101,3 +122,35 @@ CANRECPluginImpl_IOperations::MakeCanonicalRecognition ( Handle(GEOM_Object) the return aShape; } + +//============================================================================= +/*! + * \brief Get the number of canonical faces in the shape. + * + * \param theObject the input object (solid, compound, compsolid). + * + * \return the number of canonical faces in the object. + */ +//============================================================================= +Standard_Integer CANRECPluginImpl_IOperations::GetNbCanonicalFaces + (const Handle(GEOM_Object) &theObject) +{ + SetErrorCode(KO); + + TopoDS_Shape aShape = theObject->GetValue(); + + if (aShape.IsNull()) { + return -1; + } + + const Standard_Integer aResult = + CANRECPluginImpl_Driver::GetNbCanonicalFaces(aShape); + + if (aResult >= 0) { + SetErrorCode(OK); + + return aResult; + } + + return -1; +} diff --git a/src/CANRECPLUGINEngine/CANRECPluginImpl_IOperations.hxx b/src/CANRECPLUGINEngine/CANRECPluginImpl_IOperations.hxx index 2d7ba11..3be84a9 100644 --- a/src/CANRECPLUGINEngine/CANRECPluginImpl_IOperations.hxx +++ b/src/CANRECPLUGINEngine/CANRECPluginImpl_IOperations.hxx @@ -23,6 +23,8 @@ #include #include +#include + class GEOM_Engine; class CANRECPluginImpl_IOperations: public GEOM_IOperations @@ -31,10 +33,15 @@ public: Standard_EXPORT CANRECPluginImpl_IOperations( GEOM_Engine* theEngine, int theDocID ); Standard_EXPORT ~CANRECPluginImpl_IOperations(); - Standard_EXPORT Handle(GEOM_Object) MakeCanonicalRecognition ( Handle(GEOM_Object) theObject, - bool theMergeSurf, - bool theMergeCurves, - double theTolerance ); + Standard_EXPORT Handle(GEOM_Object) MakeCanonicalRecognition + (Handle(GEOM_Object) theObject, + bool theMergeSurf, + bool theMergeCurves, + double theTolerance, + Handle_TColStd_HSequenceOfInteger &theStat); + + Standard_EXPORT Standard_Integer GetNbCanonicalFaces + (const Handle(GEOM_Object) &theObject); }; #endif // __CANRECPLUGINIMPL_IOPERATIONS_HXX diff --git a/src/CANRECPLUGINGUI/CANRECPluginGUI_CanonicalRecognitionDlg.cxx b/src/CANRECPLUGINGUI/CANRECPluginGUI_CanonicalRecognitionDlg.cxx index 8de9222..8c899a5 100644 --- a/src/CANRECPLUGINGUI/CANRECPluginGUI_CanonicalRecognitionDlg.cxx +++ b/src/CANRECPLUGINGUI/CANRECPluginGUI_CanonicalRecognitionDlg.cxx @@ -59,7 +59,8 @@ // Constructor //================================================================================= CANRECPluginGUI_CanonicalRecognitionDlg::CANRECPluginGUI_CanonicalRecognitionDlg( GeometryGUI* theGeometryGUI, QWidget* parent ) -: GEOMBase_Skeleton(theGeometryGUI, parent, false) +: GEOMBase_Skeleton(theGeometryGUI, parent, false), + myNbFacesLbl(0) { QString aPluginName = "CANRECPlugin"; QPixmap imageOp (SUIT_Session::session()->resourceMgr()->loadPixmap( aPluginName, tr( "ICO_CANONICALRECOGNITION" ) ) ); @@ -94,6 +95,9 @@ CANRECPluginGUI_CanonicalRecognitionDlg::CANRECPluginGUI_CanonicalRecognitionDlg PButton1->setIcon( image1 ); PButton1->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + // Label with number of faces. + myNbFacesLbl = new QLabel(argGroup); + // 2. Object QLabel* textLabel1 = new QLabel( argGroup ); textLabel1->setText( tr( "CANRECPLUGIN_ARG_OBJ" ) ); @@ -118,12 +122,13 @@ CANRECPluginGUI_CanonicalRecognitionDlg::CANRECPluginGUI_CanonicalRecognitionDlg lay->addWidget( textLabel1, 0, 0 ); lay->addWidget( PButton1, 0, 1 ); lay->addWidget( LineEdit1, 0, 2 ); + lay->addWidget(myNbFacesLbl, 1, 0, 1, 3); - lay->addWidget( textLabel2, 1, 0, 1, 2 ); - lay->addWidget( SpinBoxTol, 1, 2 ); + lay->addWidget( textLabel2, 2, 0, 1, 2 ); + lay->addWidget( SpinBoxTol, 2, 2 ); - lay->addWidget( CheckButton1, 2, 0, 1, 3 ); - lay->addWidget( CheckButton2, 3, 0, 1, 3 ); + lay->addWidget( CheckButton1, 3, 0, 1, 3 ); + lay->addWidget( CheckButton2, 4, 0, 1, 3 ); myHelpFileName = "canrecplugin_usage_page.html"; myHelpContext = aPluginName.toUpper(); @@ -253,7 +258,9 @@ bool CANRECPluginGUI_CanonicalRecognitionDlg::execute( ObjectList& objects ) CORBA::Double aTolerance = SpinBoxTol->value(); // call engine function - anObj = anOper->MakeCanonicalRecognition( myObject.get(), aMergeSurf, aMergeCurves, aTolerance ); + CANRECPlugin::ListOfLong_var aStat; + + anObj = anOper->MakeCanonicalRecognition( myObject.get(), aMergeSurf, aMergeCurves, aTolerance, aStat ); res = !anObj->_is_nil(); if ( res && !IsPreview() ) { @@ -265,6 +272,31 @@ bool CANRECPluginGUI_CanonicalRecognitionDlg::execute( ObjectList& objects ) if ( aParameters.count() > 0 ) anObj->SetParameters( aParameters.join(":").toLatin1().constData() ); + + + // Display message box with statistics. + // Compose statistics string. + QString aStatString = tr("CANRECPLUGIN_INFO_TEXT_CAPTION"); + + aStatString += "\n\n\t"; + aStatString += tr("CANRECPLUGIN_INFO_TEXT_NB_FACES_INIT").arg(aStat[0]); + aStatString += "\n\t"; + aStatString += tr("CANRECPLUGIN_INFO_TEXT_NB_CAN_FACES_INIT").arg(aStat[1]); + aStatString += "\n\t"; + aStatString += tr("CANRECPLUGIN_INFO_TEXT_NB_FACES").arg(aStat[2]); + + if (CheckButton1->isChecked()) { + aStatString += "\n\t"; + aStatString += tr("CANRECPLUGIN_INFO_TEXT_MERGED_SURF").arg(aStat[3]); + } + + if (CheckButton2->isChecked()) { + aStatString += "\n\t"; + aStatString += tr("CANRECPLUGIN_INFO_TEXT_MERGED_CURV").arg(aStat[4]); + } + + SUIT_MessageBox::information + (this, tr("CANRECPLUGIN_INFO_TITLE"), aStatString); } if ( res ) @@ -286,9 +318,32 @@ void CANRECPluginGUI_CanonicalRecognitionDlg::SelectionIntoArgument() { myObject = selected.first(); LineEdit1->setText( myObject->GetName() ); + + // Get statistics of initial shape. + CANRECPlugin::ICanRecOperations_var anOper = + CANRECPlugin::ICanRecOperations::_narrow( getOperation() ); + const int aNbCanFaces = + anOper->GetNbCanonicalFaces(myObject.get()); + TopoDS_Shape aShape; + + if (GEOMBase::GetShape(myObject.get(), aShape) && !aShape.IsNull()) { + // Get the tolal number of faces. + TopTools_IndexedMapOfShape aMapShapes; + + TopExp::MapShapes(aShape, TopAbs_FACE, aMapShapes); + + const Standard_Integer aNbFaces = aMapShapes.Extent(); + + myNbFacesLbl->setText(tr("CANRECPLUGIN_ARG_NB_CAN_FACES"). + arg(aNbCanFaces).arg(aNbFaces)); + } else { + myNbFacesLbl->setText(tr("CANRECPLUGIN_ARG_NB_CAN_FACES_NO_OBJECT")); + } } - else + else { LineEdit1->setText( "" ); + myNbFacesLbl->setText(tr("CANRECPLUGIN_ARG_NB_CAN_FACES_NO_OBJECT")); + } } //================================================================================= diff --git a/src/CANRECPLUGINGUI/CANRECPluginGUI_CanonicalRecognitionDlg.h b/src/CANRECPLUGINGUI/CANRECPluginGUI_CanonicalRecognitionDlg.h index 15ae7a5..1899653 100644 --- a/src/CANRECPLUGINGUI/CANRECPluginGUI_CanonicalRecognitionDlg.h +++ b/src/CANRECPLUGINGUI/CANRECPluginGUI_CanonicalRecognitionDlg.h @@ -63,6 +63,7 @@ private: SalomeApp_DoubleSpinBox* SpinBoxTol; QCheckBox* CheckButton1; QCheckBox* CheckButton2; + QLabel *myNbFacesLbl; GEOM::GeomObjPtr myObject; }; diff --git a/src/CANRECPLUGINGUI/resources/CANRECPlugin_msg_en.ts b/src/CANRECPLUGINGUI/resources/CANRECPlugin_msg_en.ts index fba0e94..e69d60d 100644 --- a/src/CANRECPLUGINGUI/resources/CANRECPlugin_msg_en.ts +++ b/src/CANRECPLUGINGUI/resources/CANRECPlugin_msg_en.ts @@ -62,5 +62,41 @@ CANRECPLUGIN_ARG_TOLERANCE Tolerance + + CANRECPLUGIN_ARG_NB_CAN_FACES_NO_OBJECT + Number of canonical faces: + + + CANRECPLUGIN_ARG_NB_CAN_FACES + Number of canonical faces: %1 of %2 + + + CANRECPLUGIN_INFO_TITLE + Operation Statistics + + + CANRECPLUGIN_INFO_TEXT_CAPTION + Operation Statistics: + + + CANRECPLUGIN_INFO_TEXT_NB_FACES_INIT + Total number of faces in the initial shape: %1 + + + CANRECPLUGIN_INFO_TEXT_NB_CAN_FACES_INIT + Number of canonical faces in the initial shape: %1 + + + CANRECPLUGIN_INFO_TEXT_NB_FACES + Number of faces converted to the canonical form: %1 + + + CANRECPLUGIN_INFO_TEXT_MERGED_SURF + Number of merged surfaces: %1 + + + CANRECPLUGIN_INFO_TEXT_MERGED_CURV + Number of merged curves: %1 + diff --git a/src/CANRECPLUGIN_PY/CANRECPluginBuilder.py b/src/CANRECPLUGIN_PY/CANRECPluginBuilder.py index e4c9c01..8dfda9a 100644 --- a/src/CANRECPLUGIN_PY/CANRECPluginBuilder.py +++ b/src/CANRECPLUGIN_PY/CANRECPluginBuilder.py @@ -69,8 +69,37 @@ def MakeCanonicalRecognition(self, theObj, theMergeSurf, theMergeCurves, from salome.geom.geomBuilder import ParseParameters, RaiseIfFailed anOp = GetCANRECOperations(self) theMergeSurf, theMergeCurves, theTolerance, Parameters = ParseParameters(theMergeSurf, theMergeCurves, theTolerance) - anObj = anOp.MakeCanonicalRecognition(theObj, theMergeSurf, theMergeCurves, theTolerance) + (anObj, aStat) = anOp.MakeCanonicalRecognition(theObj, theMergeSurf, theMergeCurves, theTolerance) RaiseIfFailed("MakeCanonicalRecognition", anOp) self._autoPublish(anObj, theName, "canonical") anOp.UnRegister() + print "Total number of faces in the initial shape: %s" % aStat[0] + print "Number of canonical faces in the initial shape: %s" % aStat[1] + print "Number of faces converted to the canonical form: %s" % aStat[2] + if aStat[3] >= 0: + print "Number of merged surfaces: %s" % aStat[3] + if aStat[4] >= 0: + print "Number of merged curves: %s" % aStat[4] + return anObj + +## Get the number of canonical faces in the shape. +# @param theObj the input object (solid, compound, compsolid). +# +# @return the number of canonical faces in the object. +def GetNbCanonicalFaces(self, theObj): + """ + Get the number of canonical faces in the shape. + + Parameters: + theObj the input object (solid, compound, compsolid). + + Returns: + the number of canonical faces in the object. + """ + from salome.geom.geomBuilder import RaiseIfFailed + anOp = GetCANRECOperations(self) + aNbCanFaces = anOp.GetNbCanonicalFaces(theObj) + RaiseIfFailed("GetNbCanonicalFaces", anOp) + anOp.UnRegister() + return aNbCanFaces -- 2.39.2