Back to index

salome-smesh  6.5.0
SMESH_Measurements_i.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 //  File   : SMESH_Measurements_i.cxx
00023 //  Author : Pavel TELKOV, Open CASCADE S.A.S. (pavel.telkov@opencascade.com)
00024 
00025 #include "SMESH_Measurements_i.hxx"
00026 
00027 #include "SMESH_Gen_i.hxx"
00028 #include "SMESH_PythonDump.hxx"
00029 
00030 #include "SMDS_Mesh.hxx"
00031 #include "SMDS_MeshNode.hxx"
00032 #include "SMDS_MeshElement.hxx"
00033 #include "SMDS_ElemIterator.hxx"
00034 
00035 #include "SMESHDS_Mesh.hxx"
00036 
00037 
00038 using namespace SMESH;
00039 
00043 static void initMeasure( SMESH::Measure& theMeasure)
00044 {
00045 
00046   theMeasure.minX = theMeasure.minY = theMeasure.minZ = 0.;
00047   theMeasure.maxX = theMeasure.maxY = theMeasure.maxZ = 0.;
00048   theMeasure.node1 = theMeasure.node2 = -1;
00049   theMeasure.elem1 = theMeasure.elem2 = -1;
00050   theMeasure.value = 0.;
00051 }
00052 
00053 //=============================================================================
00059 //=============================================================================
00060 
00061 SMESH::Measurements_ptr SMESH_Gen_i::CreateMeasurements()
00062 {
00063   SMESH::Measurements_i* aMeasure = new SMESH::Measurements_i();
00064   SMESH::Measurements_var anObj = aMeasure->_this();
00065   return anObj._retn();
00066 }
00067 
00068   
00069 /*
00070   Class       : Measurements
00071   Description : make measure of mesh qunatities
00072 */
00073 
00074 //=======================================================================
00075 // name    : Measurements_i
00076 // Purpose : Constructor
00077 //=======================================================================
00078 Measurements_i::Measurements_i()
00079 : SALOME::GenericObj_i( SMESH_Gen_i::GetPOA() )
00080 {
00081   //Base class Salome_GenericObject do it inmplicitly by overriding PortableServer::POA_ptr _default_POA() method
00082   //PortableServer::ObjectId_var anObjectId =
00083   //  SMESH_Gen_i::GetPOA()->activate_object( this );
00084 }
00085 
00086 //=======================================================================
00087 // name    : ~Measurements_i
00088 // Purpose : Destructor
00089 //=======================================================================
00090 Measurements_i::~Measurements_i()
00091 {
00092   //TPythonDump()<<this<<".UnRegister()";
00093 }
00094 
00095 static bool getNodeNodeDistance (SMESH::Measure& theMeasure,
00096                                  const SMDS_MeshNode* theNode1,
00097                                  const SMDS_MeshNode* theNode2 = 0)
00098 {
00099   double dist = 0., dd = 0.;
00100 
00101   if (!theNode1)
00102     return false;
00103 
00104   dd = theNode1->X(); if (theNode2) dd -= theNode2->X(); theMeasure.minX = dd; dd *= dd; dist += dd;
00105   dd = theNode1->Y(); if (theNode2) dd -= theNode2->Y(); theMeasure.minY = dd; dd *= dd; dist += dd;
00106   dd = theNode1->Z(); if (theNode2) dd -= theNode2->Z(); theMeasure.minZ = dd; dd *= dd; dist += dd;
00107 
00108   if (dist < 0)
00109     return false;
00110   
00111   theMeasure.value = sqrt(dist);
00112   theMeasure.node1 = theNode1->GetID();
00113   theMeasure.node2 = theNode2 ? theNode2->GetID() : 0;
00114 
00115   return true;
00116 }
00117 
00118 static SMESHDS_Mesh* getMesh(SMESH::SMESH_IDSource_ptr theSource)
00119 {
00120   if (!CORBA::is_nil( theSource ))
00121   {
00122     SMESH_Mesh_i* anImplPtr = DownCast<SMESH_Mesh_i*>(theSource->GetMesh());
00123     if (anImplPtr)
00124       return anImplPtr->GetImpl().GetMeshDS();
00125   }
00126   return 0;
00127 }
00128 
00129 static bool isNodeType (SMESH::array_of_ElementType_var theTypes)
00130 {
00131   return theTypes->length() > 0 && theTypes[0] == SMESH::NODE;
00132 }
00133 
00134 //=======================================================================
00135 // name    : MinDistance
00136 // Purpose : minimal distance between two given entities
00137 //=======================================================================
00138 SMESH::Measure Measurements_i::MinDistance
00139  (SMESH::SMESH_IDSource_ptr theSource1,
00140   SMESH::SMESH_IDSource_ptr theSource2)
00141 {
00142   SMESH::Measure aMeasure;
00143   initMeasure(aMeasure);
00144 
00145   if (CORBA::is_nil( theSource1 ))
00146     return aMeasure;
00147   
00148   // if second source is null, min distance from theSource1 to the origin is calculated
00149   bool isOrigin =  CORBA::is_nil( theSource2 );
00150 
00151   // calculate minimal distance between two mesh entities
00152   SMESH::array_of_ElementType_var types1 = theSource1->GetTypes();
00153   SMESH::array_of_ElementType_var types2;
00154   if ( !isOrigin ) types2 = theSource2->GetTypes();
00155 
00156   // here we assume that type of all IDs defined by first type in array
00157   bool isNode1 = isNodeType(types1);
00158   bool isNode2 = isOrigin || isNodeType(types2);
00159 
00160   SMESH::long_array_var aElementsId1 = theSource1->GetIDs();
00161   SMESH::long_array_var aElementsId2;
00162   if ( !isOrigin ) aElementsId2 = theSource2->GetIDs();
00163 
00164   // compute distance between two entities
00165   /* NOTE: currently only node-to-node case is implemented
00166    * all other cases will be implemented later
00167    * below IF should be replaced by complete switch
00168    * on mesh entities types
00169    */
00170   if (isNode1 && isNode2)
00171   {
00172     // node - node
00173     const SMESHDS_Mesh* aMesh1 = getMesh( theSource1 );
00174     const SMESHDS_Mesh* aMesh2 = isOrigin ? 0 : getMesh( theSource2 );
00175     const SMDS_MeshNode* theNode1 = aMesh1 ? aMesh1->FindNode( aElementsId1[0] ) : 0;
00176     const SMDS_MeshNode* theNode2 = aMesh2 ? aMesh2->FindNode( aElementsId2[0] ) : 0;
00177     getNodeNodeDistance( aMeasure, theNode1, theNode2 );
00178   }
00179   else
00180   {
00181     // NOT_IMPLEMENTED
00182   }
00183 
00184   return aMeasure;
00185 }
00186 
00187 //=======================================================================
00188 // name    : enlargeBoundingBox
00189 // Purpose : 
00190 //=======================================================================
00191 static void enlargeBoundingBox(const SMDS_MeshNode* theNode,
00192                                SMESH::Measure&      theMeasure)
00193 {
00194   if (!theNode)
00195     return;
00196   if ( theMeasure.node1 == -1 ) {
00197     // we use this attribute as a flag that it is the first node added to the bnd box 
00198     theMeasure.minX = theMeasure.maxX = theNode->X();
00199     theMeasure.minY = theMeasure.maxY = theNode->Y();
00200     theMeasure.minZ = theMeasure.maxZ = theNode->Z();
00201     theMeasure.node1 = theNode->GetID();
00202   }
00203   else {
00204     theMeasure.minX = min( theMeasure.minX, theNode->X() );
00205     theMeasure.maxX = max( theMeasure.maxX, theNode->X() );
00206     theMeasure.minY = min( theMeasure.minY, theNode->Y() );
00207     theMeasure.maxY = max( theMeasure.maxY, theNode->Y() );
00208     theMeasure.minZ = min( theMeasure.minZ, theNode->Z() );
00209     theMeasure.maxZ = max( theMeasure.maxZ, theNode->Z() );
00210   }
00211 }
00212 
00213 //=======================================================================
00214 // name    : enlargeBoundingBox
00215 // Purpose : 
00216 //=======================================================================
00217 static void enlargeBoundingBox(const SMESH::SMESH_IDSource_ptr theObject,
00218                                SMESH::Measure&                 theMeasure)
00219 {
00220   if ( CORBA::is_nil( theObject ) )
00221     return;
00222   const SMESHDS_Mesh* aMesh = getMesh( theObject );
00223   if ( !aMesh )
00224     return;
00225   SMESH::array_of_ElementType_var types = theObject->GetTypes();
00226   SMESH::long_array_var     aElementsId = theObject->GetIDs();
00227   // here we assume that type of all IDs defined by first type in array
00228   const bool isNode = isNodeType( types );
00229   for(int i = 0, n = aElementsId->length(); i < n; i++)
00230   {
00231     if (isNode)
00232       enlargeBoundingBox( aMesh->FindNode( aElementsId[i] ), theMeasure);
00233     else
00234     {
00235       const SMDS_MeshElement* elem = aMesh->FindElement( aElementsId[i] );
00236       if (!elem)
00237         continue;
00238       SMDS_ElemIteratorPtr aNodeIter = elem->nodesIterator();
00239       while( aNodeIter->more() )
00240         enlargeBoundingBox( dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() ), theMeasure);
00241     }
00242   }
00243 }
00244                                
00245 //=======================================================================
00246 // name    : BoundingBox
00247 // Purpose : compute common bounding box of entities
00248 //=======================================================================
00249 SMESH::Measure Measurements_i::BoundingBox (const SMESH::ListOfIDSources& theSources)
00250 {
00251   SMESH::Measure aMeasure;
00252   initMeasure(aMeasure);
00253 
00254   // calculate bounding box on sources
00255   for ( int i = 0, n = theSources.length(); i < n ; ++i )
00256     enlargeBoundingBox( theSources[i], aMeasure );
00257 
00258   return aMeasure;
00259 }