From e69dd23c497fe21a8c399f4836601c5e106469f8 Mon Sep 17 00:00:00 2001 From: ptv Date: Mon, 1 Nov 2010 10:09:14 +0000 Subject: [PATCH] 0020885: EDF 607 SMESH: Measure tools --- idl/Makefile.am | 6 +- idl/SMESH_Gen.idl | 3 + src/SMESHGUI/SMESHGUI.cxx | 4 + src/SMESHGUI/SMESHGUI_MeshUtils.cxx | 12 ++ src/SMESHGUI/SMESHGUI_MeshUtils.h | 3 + src/SMESH_I/Makefile.am | 4 +- src/SMESH_I/SMESH_DumpPython.cxx | 10 ++ src/SMESH_I/SMESH_Gen_i.hxx | 5 +- src/SMESH_I/SMESH_Measurements_i.cxx | 243 +++++++++++++++++++++++++++ src/SMESH_I/SMESH_Measurements_i.hxx | 66 ++++++++ src/SMESH_I/SMESH_PythonDump.hxx | 4 + src/SMESH_SWIG/smeshDC.py | 60 +++++++ 12 files changed, 416 insertions(+), 4 deletions(-) create mode 100644 src/SMESH_I/SMESH_Measurements_i.cxx create mode 100644 src/SMESH_I/SMESH_Measurements_i.hxx diff --git a/idl/Makefile.am b/idl/Makefile.am index 5a88808b3..491c38667 100644 --- a/idl/Makefile.am +++ b/idl/Makefile.am @@ -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) diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index 14527a9b3..909193a3e 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -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 */ diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 4d3383376..bcc33b748 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -122,6 +122,7 @@ #include #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(); } //============================================================================= diff --git a/src/SMESHGUI/SMESHGUI_MeshUtils.cxx b/src/SMESHGUI/SMESHGUI_MeshUtils.cxx index 0763be3ed..c6162bc65 100644 --- a/src/SMESHGUI/SMESHGUI_MeshUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshUtils.cxx @@ -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 #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 diff --git a/src/SMESHGUI/SMESHGUI_MeshUtils.h b/src/SMESHGUI/SMESHGUI_MeshUtils.h index 5edffe9f3..7cfcc5321 100644 --- a/src/SMESHGUI/SMESHGUI_MeshUtils.h +++ b/src/SMESHGUI/SMESHGUI_MeshUtils.h @@ -39,6 +39,7 @@ // IDL includes #include #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 diff --git a/src/SMESH_I/Makefile.am b/src/SMESH_I/Makefile.am index 9a2a3c6a4..53f285528 100644 --- a/src/SMESH_I/Makefile.am +++ b/src/SMESH_I/Makefile.am @@ -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 diff --git a/src/SMESH_I/SMESH_DumpPython.cxx b/src/SMESH_I/SMESH_DumpPython.cxx index 44a848a35..c4473fe1f 100644 --- a/src/SMESH_I/SMESH_DumpPython.cxx +++ b/src/SMESH_I/SMESH_DumpPython.cxx @@ -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 diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index 89cf79ca7..b2c90805c 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -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 index 000000000..fa52f66e6 --- /dev/null +++ b/src/SMESH_I/SMESH_Measurements_i.cxx @@ -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()<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(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( 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 index 000000000..899d5bc7e --- /dev/null +++ b/src/SMESH_I/SMESH_Measurements_i.hxx @@ -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 +#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 diff --git a/src/SMESH_I/SMESH_PythonDump.hxx b/src/SMESH_I/SMESH_PythonDump.hxx index 031b3c415..f1ee26581 100644 --- a/src/SMESH_I/SMESH_PythonDump.hxx +++ b/src/SMESH_I/SMESH_PythonDump.hxx @@ -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); diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index 10b0bf163..6958a9e22 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -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): # --------------------------------------------- -- 2.39.2