Salome HOME
0020885: EDF 607 SMESH: Measure tools
authorptv <ptv@opencascade.com>
Mon, 1 Nov 2010 10:09:14 +0000 (10:09 +0000)
committerptv <ptv@opencascade.com>
Mon, 1 Nov 2010 10:09:14 +0000 (10:09 +0000)
12 files changed:
idl/Makefile.am
idl/SMESH_Gen.idl
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_MeshUtils.cxx
src/SMESHGUI/SMESHGUI_MeshUtils.h
src/SMESH_I/Makefile.am
src/SMESH_I/SMESH_DumpPython.cxx
src/SMESH_I/SMESH_Gen_i.hxx
src/SMESH_I/SMESH_Measurements_i.cxx [new file with mode: 0644]
src/SMESH_I/SMESH_Measurements_i.hxx [new file with mode: 0644]
src/SMESH_I/SMESH_PythonDump.hxx
src/SMESH_SWIG/smeshDC.py

index 5a88808b30e51f8c05385801643e8174ae7f700e..491c38667fe62ed1838fff01371b6ddf84729c18 100644 (file)
@@ -32,7 +32,8 @@ BASEIDL_FILES = \
        SMESH_Filter.idl \
        SMESH_Group.idl \
        SMESH_Pattern.idl \
-       SMESH_MeshEditor.idl
+       SMESH_MeshEditor.idl \
+       SMESH_Measurements.idl
 
 # This variable defines the files to be installed
 dist_salomeidl_DATA = $(BASEIDL_FILES)
@@ -49,7 +50,8 @@ nodist_libSalomeIDLSMESH_la_SOURCES = \
        SMESH_FilterSK.cc \
        SMESH_GroupSK.cc \
        SMESH_PatternSK.cc \
-       SMESH_MeshEditorSK.cc
+       SMESH_MeshEditorSK.cc \
+       SMESH_MeasurementsSK.cc
 
 # header files must be exported: other modules have to use this library
 nodist_salomeinclude_HEADERS = $(BASEIDL_FILES:%.idl=%.hh)
index 14527a9b3b9244878734696a72c970429cf9416a..909193a3ee358ea9b06caf7e65f520ca3cbefa64 100644 (file)
@@ -42,6 +42,7 @@ module SMESH
 
   interface FilterManager;
   interface SMESH_Pattern;
+  interface Measurements;
 
   /*!
    * Tags definition
@@ -119,6 +120,8 @@ module SMESH
 
     SMESH_Pattern GetPattern();
 
+    Measurements  CreateMeasurements();
+
     /*!
       Set the current mode
      */
index 4d3383376164c5e9dc9b1c75e91d3e2d78150b2e..bcc33b7480ef402c62bb92b1605b8fef713c9bd9 100644 (file)
 #include <SALOMEconfig.h>
 #include CORBA_CLIENT_HEADER(SALOMEDS_Attributes)
 #include CORBA_CLIENT_HEADER(SMESH_MeshEditor)
+#include CORBA_CLIENT_HEADER(SMESH_Measurements)
 
 // Qt includes
 // #define       INCLUDE_MENUITEM_DEF // VSR commented ????????
@@ -1433,6 +1434,7 @@ LightApp_Module( "SMESH" )
 
   SMESH::GetFilterManager();
   SMESH::GetPattern();
+  SMESH::GetMeasurements();
 
   /* load resources for all available meshers */
   SMESH::InitAvailableHypotheses();
@@ -1447,8 +1449,10 @@ SMESHGUI::~SMESHGUI()
 {
 #ifdef WITHGENERICOBJ
   SMESH::GetFilterManager()->Destroy();
+  SMESH::GetMeasurements()->Destroy();
 #endif
   SMESH::GetFilterManager() = SMESH::FilterManager::_nil();
+  SMESH::GetMeasurements() = SMESH::Measurements::_nil();
 }
 
 //=============================================================================
index 0763be3ed52c27879096d76939e1e2eddde899af..c6162bc6522244284b1c574916dc00d8a2d47beb 100644 (file)
@@ -27,6 +27,7 @@
 //
 #include "SMESHGUI_MeshUtils.h"
 
+#include "SMESHGUI.h"
 #include "SMESHGUI_Utils.h"
 
 // SALOME KERNEL includes
@@ -38,6 +39,7 @@
 // IDL includes
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Group)
+#include CORBA_SERVER_HEADER(SMESH_Measurements)
 
 namespace SMESH
 {
@@ -82,4 +84,14 @@ namespace SMESH
     }
     return baseName;
   }
+
+
+  SMESH::Measurements_var& GetMeasurements()
+  {
+    static SMESH::Measurements_var aMeasurements;
+    if (CORBA::is_nil(aMeasurements)) {
+      aMeasurements = SMESHGUI::GetSMESHGen()->CreateMeasurements();
+    }
+    return aMeasurements;
+  }
 } // end of namespace SMESH
index 5edffe9f31512874dc84aeadffd24db5909f5656..7cfcc532151b13ebcbe6c146f291cadec09f7b02 100644 (file)
@@ -39,6 +39,7 @@
 // IDL includes
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include CORBA_SERVER_HEADER(SMESH_Measurements)
 
 namespace SMESH
 {
@@ -47,6 +48,8 @@ namespace SMESH
  
   SMESHGUI_EXPORT
     QString        UniqueMeshName( const QString&, const QString& = QString() );
+
+  SMESHGUI_EXPORT  SMESH::Measurements_var& GetMeasurements();
 }
 
 #endif // SMESHGUI_MESHUTILS_H
index 9a2a3c6a4b9dfabb169ec30a6f1335a28afca9ec..53f2855287fc93c18661d779da406f69fe69eb58 100644 (file)
@@ -46,6 +46,7 @@ salomeinclude_HEADERS = \
        SMESH_Pattern_i.hxx \
        SMESH_2smeshpy.hxx \
        SMESH_NoteBook.hxx \
+       SMESH_Measurements_i.hxx \
        SMESH.hxx
 
 # Scripts to be installed.
@@ -76,7 +77,8 @@ dist_libSMESHEngine_la_SOURCES = \
        SMESH_Group_i.cxx \
        SMESH_Pattern_i.cxx \
        SMESH_2smeshpy.cxx \
-       SMESH_NoteBook.cxx 
+       SMESH_NoteBook.cxx \
+       SMESH_Measurements_i.cxx
 
 # Executables targets
 bin_PROGRAMS = SMESHEngine
index 44a848a35f4d32ce51e518748d452cb443ae6d83..c4473fe1ff89dcbd40afe123902c267df37d5c2c 100644 (file)
@@ -308,6 +308,15 @@ namespace SMESH
     return *this;
   }
 
+  TPythonDump& 
+  TPythonDump::
+  operator<<(SMESH::Measurements_i* theArg)
+  {
+    myStream<<"aMeasurements";
+    return *this;
+  }
+
+
   TPythonDump& TPythonDump:: operator<<(SMESH_Gen_i* theArg)
   {
     myStream << SMESHGenName(); return *this;
@@ -685,6 +694,7 @@ TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
   TCollection_AsciiString aScript;
   aScript = "def RebuildData(theStudy):\n\t";
   aScript += helper + "aFilterManager = " + aSMESHGen + ".CreateFilterManager()\n\t";
+  aScript += helper + "aMeasurements = " + aSMESHGen + ".CreateMeasurements()\n\t";
   if ( isPublished )
     aScript += aSMESHGen + ".SetCurrentStudy(theStudy)";
   else
index 89cf79ca77690e5fc39133f8387eebee1f3a491e..b2c90805c642e4b8d65fdaa6413da1fb1e06ad2e 100644 (file)
@@ -223,7 +223,7 @@ public:
   SMESH::SMESH_Mesh_ptr CreateEmptyMesh()
     throw ( SALOME::SALOME_Exception );
 
-  //  Create mesh(es) and import data from UNV file
+  //  Create mesh(es) and import data from UNV fileter
   SMESH::SMESH_Mesh_ptr CreateMeshesFromUNV( const char* theFileName )
     throw ( SALOME::SALOME_Exception );
 
@@ -357,6 +357,9 @@ public:
   // Return a pattern mesher
   SMESH::SMESH_Pattern_ptr GetPattern();
 
+  // Create measurement instance
+  SMESH::Measurements_ptr  CreateMeasurements();
+
   // Clears study-connected data when it is closed
   void Close( SALOMEDS::SComponent_ptr theComponent );
   
diff --git a/src/SMESH_I/SMESH_Measurements_i.cxx b/src/SMESH_I/SMESH_Measurements_i.cxx
new file mode 100644 (file)
index 0000000..fa52f66
--- /dev/null
@@ -0,0 +1,243 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  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.
+//
+//  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
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
+//  File   : SMESH_Filter_i.cxx
+//  Author : Alexey Petrov, OCC
+//  Module : SMESH
+//
+#include "SMESH_Measurements_i.hxx"
+
+#include "SMESH_Gen_i.hxx"
+#include "SMESH_PythonDump.hxx"
+
+#include "SMDS_Mesh.hxx"
+#include "SMDS_MeshNode.hxx"
+#include "SMDS_MeshElement.hxx"
+#include "SMDS_ElemIterator.hxx"
+
+#include "SMESHDS_Mesh.hxx"
+
+
+using namespace SMESH;
+
+/**
+ * this local function to avoid uninitialized fields
+ */
+static void initMeasure( SMESH::Measure& theMeasure)
+{
+
+  theMeasure.minX = theMeasure.minY = theMeasure.minZ = 0.;
+  theMeasure.maxX = theMeasure.maxY = theMeasure.maxZ = 0.;
+  theMeasure.node1 = theMeasure.node2 = -1;
+  theMeasure.elem1 = theMeasure.elem2 = -1;
+  theMeasure.value = 0.;
+}
+
+//=============================================================================
+/*!
+ *  SMESH_Gen_i::CreateMeasurements
+ *
+ *  Create measurement instance
+ */
+//=============================================================================
+
+SMESH::Measurements_ptr SMESH_Gen_i::CreateMeasurements()
+{
+  SMESH::Measurements_i* aMeasure = new SMESH::Measurements_i();
+  SMESH::Measurements_var anObj = aMeasure->_this();
+  return anObj._retn();
+}
+
+  
+/*
+  Class       : Measurements
+  Description : make measure of mesh qunatities
+*/
+
+//=======================================================================
+// name    : Measurements_i
+// Purpose : Constructor
+//=======================================================================
+Measurements_i::Measurements_i()
+: SALOME::GenericObj_i( SMESH_Gen_i::GetPOA() )
+{
+  //Base class Salome_GenericObject do it inmplicitly by overriding PortableServer::POA_ptr _default_POA() method
+  //PortableServer::ObjectId_var anObjectId =
+  //  SMESH_Gen_i::GetPOA()->activate_object( this );
+}
+
+//=======================================================================
+// name    : ~Measurements_i
+// Purpose : Destructor
+//=======================================================================
+Measurements_i::~Measurements_i()
+{
+  //TPythonDump()<<this<<".Destroy()";
+}
+
+static double getNodeNodeDistance (const SMDS_MeshNode* theNode1,
+                                   const SMDS_MeshNode* theNode2)
+{
+  double dist = 0., dd = 0.;
+  if (!theNode1 || !theNode2)
+    return dist;
+  dd = theNode1->X(); dd -= theNode2->X(); dd *= dd; dist += dd;
+  dd = theNode1->Y(); dd -= theNode2->Y(); dd *= dd; dist += dd;
+  dd = theNode1->Z(); dd -= theNode2->Z(); dd *= dd; dist += dd;
+  if (dist < 0)
+    return 0;
+  return sqrt(dist);
+}
+
+static SMESHDS_Mesh* getMesh(SMESH::SMESH_IDSource_ptr theSource)
+{
+  if (!CORBA::is_nil( theSource ))
+  {
+    SMESH_Mesh_i* anImplPtr = DownCast<SMESH_Mesh_i*>(theSource->GetMesh());
+    if (anImplPtr)
+      return anImplPtr->GetImpl().GetMeshDS();
+  }
+  return 0;
+}
+
+static bool isNodeType (SMESH::array_of_ElementType_var theTypes)
+{
+  return theTypes->length() > 0 && theTypes[0] == SMESH::NODE;
+}
+
+//=======================================================================
+// name    : MinDistance
+// Purpose : minimal distance between two given entities
+//=======================================================================
+SMESH::Measure Measurements_i::MinDistance
+ (SMESH::SMESH_IDSource_ptr theSource1,
+  SMESH::SMESH_IDSource_ptr theSource2)
+{
+  SMESH::Measure aMeasure;
+  initMeasure(aMeasure);
+
+  if (CORBA::is_nil( theSource1 ) || CORBA::is_nil( theSource2 ))
+    return aMeasure;
+
+  // calculate minimal distance between two mesh entities
+  SMESH::array_of_ElementType_var types1 = theSource1->GetTypes();
+  SMESH::array_of_ElementType_var types2 = theSource2->GetTypes();
+  // here we assume that type of all IDs defined by first type in array
+  const bool isNode1 = isNodeType(types1);
+  const bool isNode2 = isNodeType(types2);
+
+  SMESH::long_array_var aElementsId1 = theSource1->GetIDs();
+  SMESH::long_array_var aElementsId2 = theSource2->GetIDs();
+
+  // compute distance between two entities
+  /** NOTE: currently only node-node case implemented
+   * all other cases could be implemented later
+   * this IF should be replaced by comples swtich
+   * on mesh entities types
+   */
+  if (isNode1 && isNode2)
+  {
+    // node - node
+    const SMESHDS_Mesh* aMesh1 = getMesh( theSource1 );
+    const SMESHDS_Mesh* aMesh2 = getMesh( theSource2 );
+    const SMDS_MeshNode* theNode1 = aMesh1 ? aMesh1->FindNode( aElementsId1[0] ) : 0;
+    const SMDS_MeshNode* theNode2 = aMesh2 ? aMesh2->FindNode( aElementsId2[0] ) : 0;
+    aMeasure.value = getNodeNodeDistance( theNode1, theNode2 );
+    if (theNode1 && theNode2)
+    {
+      aMeasure.node1 = theNode1->GetID();
+      aMeasure.node2 = theNode2->GetID();
+    }
+  }
+  else
+  {
+    // NOT_IMPLEMENTED
+  }
+
+  return aMeasure;
+}
+
+//=======================================================================
+// name    : enlargeBoundingBox
+// Purpose : 
+//=======================================================================
+static void enlargeBoundingBox(const SMDS_MeshNode* theNode,
+                               SMESH::Measure&      theMeasure)
+{
+  if (!theNode)
+    return;
+  theMeasure.minX = min( theMeasure.minX, theNode->X() );
+  theMeasure.maxX = max( theMeasure.maxX, theNode->X() );
+  theMeasure.minY = min( theMeasure.minY, theNode->Y() );
+  theMeasure.maxY = max( theMeasure.maxY, theNode->Y() );
+  theMeasure.minZ = min( theMeasure.minZ, theNode->Z() );
+  theMeasure.maxZ = max( theMeasure.maxZ, theNode->Z() );
+}
+
+//=======================================================================
+// name    : enlargeBoundingBox
+// Purpose : 
+//=======================================================================
+static void enlargeBoundingBox(const SMESH::SMESH_IDSource_ptr theObject,
+                               SMESH::Measure&                 theMeasure)
+{
+  if ( CORBA::is_nil( theObject ) )
+    return;
+  const SMESHDS_Mesh* aMesh = getMesh( theObject );
+  if ( !aMesh )
+    return;
+  SMESH::array_of_ElementType_var types = theObject->GetTypes();
+  SMESH::long_array_var     aElementsId = theObject->GetIDs();
+  // here we assume that type of all IDs defined by first type in array
+  const bool isNode = isNodeType( types );
+  for(int i = 0, n = aElementsId->length(); i < n; i++)
+  {
+    if (isNode)
+      enlargeBoundingBox( aMesh->FindNode( aElementsId[i] ), theMeasure);
+    else
+    {
+      const SMDS_MeshElement * elem = aMesh->FindElement( aElementsId[i] );
+      if (!elem)
+        continue;
+      SMDS_ElemIteratorPtr aNodeIter = elem->nodesIterator();
+      while( aNodeIter->more() )
+        enlargeBoundingBox( dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() ), theMeasure);
+    }
+  }
+}
+                               
+//=======================================================================
+// name    : BoundingBox
+// Purpose : compute common bounding box of entities
+//=======================================================================
+SMESH::Measure Measurements_i::BoundingBox (const SMESH::ListOfIDSources& theSources)
+{
+  SMESH::Measure aMeasure;
+  initMeasure(aMeasure);
+
+  // calculate bounding box on sources
+  for ( int i = 0, n = theSources.length(); i < n ; ++i )
+    enlargeBoundingBox( theSources[i], aMeasure );
+
+  return aMeasure;
+}
diff --git a/src/SMESH_I/SMESH_Measurements_i.hxx b/src/SMESH_I/SMESH_Measurements_i.hxx
new file mode 100644 (file)
index 0000000..899d5bc
--- /dev/null
@@ -0,0 +1,66 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  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.
+//
+//  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
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
+//  File   : SMESH_Measurements_i.hxx
+//  Author : Pavel Telkov, OCC
+//  Module : SMESH
+//
+#ifndef _SMESH_MEASUREMENTS_I_HXX_
+#define _SMESH_MEASUREMENTS_I_HXX_
+
+#include "SMESH.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_Measurements)
+
+#include "SALOME_GenericObj_i.hh"
+
+class SMESHDS_Mesh;
+
+namespace SMESH
+{
+
+  /*
+    Measurements
+  */
+  class SMESH_I_EXPORT Measurements_i: public virtual POA_SMESH::Measurements,
+                                       public virtual SALOME::GenericObj_i
+  {
+  public:
+    Measurements_i();
+    ~Measurements_i();
+
+    /*!
+     * minimal distance between two given entities
+     */
+    SMESH::Measure MinDistance(SMESH::SMESH_IDSource_ptr theSource1,
+                               SMESH::SMESH_IDSource_ptr theSource2);
+
+    /*!
+     * common bounding box of entities
+     */
+    SMESH::Measure BoundingBox(const SMESH::ListOfIDSources& theSources);
+  };
+}
+
+#endif
index 031b3c4156b789ff0e5ddf2fc8c17076b5722e8c..f1ee2658182007e1182ec2f02be0d5711d7f659b 100644 (file)
@@ -73,6 +73,7 @@ namespace SMESH
   class FilterManager_i;
   class Filter_i;
   class Functor_i;
+  class Measurements_i;
 
 // ===========================================================================================
 /*!
@@ -142,6 +143,9 @@ namespace SMESH
     TPythonDump& 
     operator<<(SMESH::Functor_i* theArg);
 
+    TPythonDump& 
+    operator<<(SMESH::Measurements_i* theArg);
+
     TPythonDump& 
     operator<<(SMESH_Gen_i* theArg);
 
index 10b0bf16348fe30158adf1d7c4691f56ec328aab..6958a9e22581fcc6b37c3fc6421f9dc7f76fed45 100644 (file)
@@ -842,6 +842,7 @@ class smeshDC(SMESH._objref_SMESH_Gen):
         aCriteria = []
         aCriteria.append(aCriterion)
         aFilter.SetCriteria(aCriteria)
+        aFilterMgr.Destroy()
         return aFilter
 
     ## Creates a numerical functor by its type
@@ -1628,6 +1629,7 @@ class Mesh:
         aCriteria.append(Criterion)
         aFilter.SetCriteria(aCriteria)
         group = self.MakeGroupByFilter(groupName, aFilter)
+        aFilterMgr.Destroy()
         return group
 
     ## Creates a mesh group by the given criteria (list of criteria)
@@ -1640,6 +1642,7 @@ class Mesh:
         aFilter = aFilterMgr.CreateFilter()
         aFilter.SetCriteria(theCriteria)
         group = self.MakeGroupByFilter(groupName, aFilter)
+        aFilterMgr.Destroy()
         return group
 
     ## Creates a mesh group by the given filter
@@ -1669,6 +1672,7 @@ class Mesh:
         aPredicate = aFilterMgr.CreateFreeEdges()
         aPredicate.SetMesh(self.mesh)
         aBorders = aPredicate.GetBorders()
+        aFilterMgr.Destroy()
         return aBorders
 
     ## Removes a group
@@ -2188,6 +2192,62 @@ class Mesh:
         return self.mesh.BaryCenter(id)
 
 
+    # Get mesh measurements information:
+    # ------------------------------------
+
+    def MinDistance(self, id1, id2, isElem1=False, isElem2=False):
+        aMeasure = self.GetMinDistance(id1, id2, isElem1, isElem2)
+        return aMeasure.value
+    
+    #  @param node1, node2 is nodes to measure distance
+    #  @return Measure structure
+    def GetMinDistance(self, id1, id2, isElem1=False, isElem2=False):
+        if isinstance( id1, int):
+            if (isElem1):
+                id1 = self.editor.MakeIDSource([id1], SMESH.FACE)
+            else:
+                id1 = self.editor.MakeIDSource([id1], SMESH.NODE)
+        if isinstance( id2, int):
+            if (isElem2):
+                id2 = self.editor.MakeIDSource([id2], SMESH.FACE)
+            else:
+                id2 = self.editor.MakeIDSource([id2], SMESH.NODE)
+        
+        aMeasurements = self.smeshpyD.CreateMeasurements()
+        aMeasure = aMeasurements.MinDistance(id1, id2)
+        aMeasurements.Destroy()
+        return aMeasure
+    
+    #  @param IDsOfElements is a list of ids of elements or nodes
+    #  @return Measure structure
+    def GetBoundingBox(self, IDs = None, isElem=True):
+        if isinstance( IDs, Mesh ):
+            IDs = [ IDs.mesh ]
+        elif (IDs == None):
+            IDs = [ self.mesh ]
+        elif isinstance( IDs, int):
+            if (isElem):
+                IDs = [ self.editor.MakeIDSource(IDs, SMESH.FACE) ]
+            else:
+                IDs = [ self.editor.MakeIDSource(IDs, SMESH.NODE) ]
+        elif isinstance( IDs, list ) and isinstance( IDs[0], int):
+            if (isElem):
+                IDs = [ self.editor.MakeIDSource(IDs, SMESH.FACE) ]
+            else:
+                IDs = [ self.editor.MakeIDSource(IDs, SMESH.NODE) ]
+        elif hasattr(IDs, "_narrow"):
+            anIDs = IDs._narrow(SMESH.SMESH_IDSource)
+            if (anIDs):
+                IDs = [ anIDs ]
+                
+        aMeasure = None
+        if isinstance(IDs, list):
+            aMeasurements = self.smeshpyD.CreateMeasurements()
+            aMeasure = aMeasurements.BoundingBox(IDs)
+            aMeasurements.Destroy()
+            
+        return aMeasure
+    
     # Mesh edition (SMESH_MeshEditor functionality):
     # ---------------------------------------------