Back to index

salome-smesh  6.5.0
StdMeshers_CartesianParameters3D.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 
00023 //  File   : StdMeshers_CartesianParameters3D.cxx
00024 //  Author : Edward AGAPOV
00025 //  Module : SMESH
00026 //
00027 #include "StdMeshers_CartesianParameters3D.hxx"
00028 
00029 #include "StdMeshers_NumberOfSegments.hxx"
00030 #include "StdMeshers_Distribution.hxx"
00031 #include "SMESH_Gen.hxx"
00032 
00033 #include "utilities.h"
00034 
00035 #include <Precision.hxx>
00036 #include <Bnd_Box.hxx>
00037 
00038 #include <limits>
00039 
00040 using namespace std;
00041 
00042 //=======================================================================
00043 //function : StdMeshers_CartesianParameters3D
00044 //purpose  : Constructor
00045 //=======================================================================
00046 
00047 StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int         hypId,
00048                                                                    int         studyId,
00049                                                                    SMESH_Gen * gen)
00050   : SMESH_Hypothesis(hypId, studyId, gen),
00051     _sizeThreshold( 4.0 ) // default according to the customer specification
00052 {
00053   _name = "CartesianParameters3D"; // used by "Cartesian_3D"
00054   _param_algo_dim = 3; // 3D
00055 }
00056 
00057 
00058 namespace
00059 {
00060   const char* axisName[3] = { "X", "Y", "Z" };
00061 
00062   //================================================================================
00066   //================================================================================
00067 
00068   void checkAxis(const int axis)
00069   {
00070     if ( axis < 0 || axis > 2 )
00071       throw SALOME_Exception(SMESH_Comment("Invalid axis index ") << axis <<
00072                              ". Valid axis indices are 0, 1 and 2");
00073   }
00074 
00075   //================================================================================
00079   //================================================================================
00080 
00081   void checkGridSpacing(std::vector<std::string>& spaceFunctions,
00082                         std::vector<double>&      internalPoints,
00083                         const std::string&        axis)
00084     throw ( SALOME_Exception )
00085   {
00086     if ( spaceFunctions.empty() )
00087       throw SALOME_Exception(SMESH_Comment("Empty space function for ") << axis );
00088 
00089     for ( size_t i = 1; i < internalPoints.size(); ++i )
00090       if ( internalPoints[i] - internalPoints[i-1] < 0 )
00091         throw SALOME_Exception(SMESH_Comment("Wrong order of internal points along ") << axis);
00092       else if ( internalPoints[i] - internalPoints[i-1] < 1e-3 )
00093         throw SALOME_Exception(SMESH_Comment("Too close internal points along ") << axis );
00094 
00095     const double tol = Precision::Confusion();
00096     if ( !internalPoints.empty() &&
00097          ( internalPoints.front() < -tol || internalPoints.back() > 1 + tol ))
00098       throw SALOME_Exception(SMESH_Comment("Invalid internal points along ") << axis);
00099 
00100     if ( internalPoints.empty() || internalPoints.front() > tol )
00101       internalPoints.insert( internalPoints.begin(), 0. );
00102     if ( internalPoints.size() < 2 || internalPoints.back() < 1 - tol )
00103       internalPoints.push_back( 1. );
00104 
00105     if ( internalPoints.size() != spaceFunctions.size() + 1 )
00106       throw SALOME_Exception
00107         (SMESH_Comment("Numbre of internal points mismatch number of functions for ") << axis);
00108 
00109     for ( size_t i = 0; i < spaceFunctions.size(); ++i )
00110       spaceFunctions[i] =
00111         StdMeshers_NumberOfSegments::CheckExpressionFunction( spaceFunctions[i], -1 );
00112   }
00113 }
00114 
00115 //=======================================================================
00116 //function : SetGrid
00117 //purpose  : Sets coordinates of node positions along an axes
00118 //=======================================================================
00119 
00120 void StdMeshers_CartesianParameters3D::SetGrid(std::vector<double>& coords, int axis)
00121   throw ( SALOME_Exception )
00122 {
00123   checkAxis( axis );
00124 
00125   if ( coords.size() < 2 )
00126     throw SALOME_Exception(LOCALIZED("Wrong number of grid coordinates"));
00127 
00128   std::sort( coords.begin(), coords.end() );
00129 
00130   bool changed = ( _coords[axis] != coords );
00131   if ( changed )
00132   {
00133     _coords[axis] = coords;
00134     NotifySubMeshesHypothesisModification();
00135   }
00136 
00137   _spaceFunctions[axis].clear();
00138   _internalPoints[axis].clear();
00139 }
00140 
00141 //=======================================================================
00142 //function : SetGridSpacing
00143 //purpose  : Set grid spacing along the three axes
00144 //=======================================================================
00145 
00146 void StdMeshers_CartesianParameters3D::SetGridSpacing(std::vector<string>& xSpaceFuns,
00147                                                       std::vector<double>& xInternalPoints,
00148                                                       const int            axis)
00149   throw ( SALOME_Exception )
00150 {
00151   checkAxis( axis );
00152 
00153   checkGridSpacing( xSpaceFuns, xInternalPoints, axisName[axis] );
00154 
00155   bool changed = ( xSpaceFuns      != _spaceFunctions[axis] ||
00156                    xInternalPoints != _internalPoints[axis] );
00157 
00158   _spaceFunctions[axis] = xSpaceFuns;
00159   _internalPoints[axis] = xInternalPoints;
00160   _coords[axis].clear();
00161 
00162   if ( changed )
00163     NotifySubMeshesHypothesisModification();
00164 }
00165 
00166 //=======================================================================
00167 //function : SetSizeThreshold
00168 //purpose  : Set size threshold
00169 //=======================================================================
00170 
00171 void StdMeshers_CartesianParameters3D::SetSizeThreshold(const double threshold)
00172   throw ( SALOME_Exception )
00173 {
00174   if ( threshold <= 1.0 )
00175     throw SALOME_Exception(LOCALIZED("threshold must be > 1.0"));
00176 
00177   bool changed = fabs( _sizeThreshold - threshold ) > 1e-6;
00178   _sizeThreshold = threshold;
00179 
00180   if ( changed )
00181     NotifySubMeshesHypothesisModification();
00182 }
00183 
00184 //=======================================================================
00185 //function : GetGridSpacing
00186 //purpose  : return spacing
00187 //=======================================================================
00188 
00189 void StdMeshers_CartesianParameters3D::GetGridSpacing(std::vector<std::string>& spaceFunctions,
00190                                                       std::vector<double>&      internalPoints,
00191                                                       const int                 axis) const
00192   throw ( SALOME_Exception )
00193 {
00194   if ( !IsGridBySpacing(axis) )
00195     throw SALOME_Exception(LOCALIZED("The grid is defined by coordinates and not by spacing"));
00196 
00197   spaceFunctions = _spaceFunctions[axis];
00198   internalPoints = _internalPoints[axis];
00199 }
00200 
00201 //=======================================================================
00202 //function : IsGridBySpacing
00203 //=======================================================================
00204 
00205 bool StdMeshers_CartesianParameters3D::IsGridBySpacing(const int axis) const
00206   throw ( SALOME_Exception )
00207 {
00208   checkAxis(axis);
00209   return !_spaceFunctions[axis].empty();
00210 }
00211 
00212 
00213 //=======================================================================
00214 //function : ComputeCoordinates
00215 //purpose  : Computes node coordinates by spacing functions
00216 //=======================================================================
00217 
00218 void StdMeshers_CartesianParameters3D::ComputeCoordinates(const double         x0,
00219                                                           const double         x1,
00220                                                           vector<std::string>& spaceFuns,
00221                                                           vector<double>&      points,
00222                                                           vector<double>&      coords,
00223                                                           const std::string&   axis )
00224   throw ( SALOME_Exception )
00225 {
00226   checkGridSpacing( spaceFuns, points, axis );
00227 
00228   coords.clear();
00229   for ( size_t i = 0; i < spaceFuns.size(); ++i )
00230   {
00231     FunctionExpr fun( spaceFuns[i].c_str(), /*convMode=*/-1 );
00232 
00233     const double p0 = x0 * ( 1. - points[i])   + x1 * points[i];
00234     const double p1 = x0 * ( 1. - points[i+1]) + x1 * points[i+1];
00235     const double length = p1 - p0;
00236 
00237     const size_t nbSections = 1000;
00238     const double sectionLen = ( p1 - p0 ) / nbSections;
00239     vector< double > nbSegments( nbSections + 1 );
00240     nbSegments[ 0 ] = 0.;
00241 
00242     double t, spacing = 0;
00243     for ( size_t i = 1; i <= nbSections; ++i )
00244     {
00245       t = double( i ) / nbSections;
00246       if ( !fun.value( t, spacing ) || spacing < std::numeric_limits<double>::min() )
00247         throw SALOME_Exception(LOCALIZED("Invalid spacing function"));
00248       nbSegments[ i ] = nbSegments[ i-1 ] + std::min( 1., sectionLen / spacing );
00249     }
00250 
00251     const int nbCells = max (1, int(floor(nbSegments.back()+0.5)));
00252     const double corr = nbCells / nbSegments.back();
00253 
00254     if ( coords.empty() ) coords.push_back( p0 );
00255 
00256     for ( size_t iCell = 1, i = 1; i <= nbSections; ++i )
00257     {
00258       if ( nbSegments[i]*corr >= iCell )
00259       {
00260         t = (i - ( nbSegments[i] - iCell/corr )/( nbSegments[i] - nbSegments[i-1] )) / nbSections;
00261         coords.push_back( p0 + t * length );
00262         ++iCell;
00263       }
00264     }
00265     const double lastCellLen = coords.back() - coords[ coords.size() - 2 ];
00266     if ( fabs( coords.back() - p1 ) > 0.5 * lastCellLen )
00267       coords.push_back ( p1 );
00268   }
00269 }
00270 
00271 //=======================================================================
00272 //function : GetCoordinates
00273 //purpose  : Return coordinates of node positions along the three axes.
00274 //           If the grid is defined by spacing functions, the coordinates are computed
00275 //=======================================================================
00276 
00277 void StdMeshers_CartesianParameters3D::GetCoordinates(std::vector<double>& xNodes,
00278                                                       std::vector<double>& yNodes,
00279                                                       std::vector<double>& zNodes,
00280                                                       const Bnd_Box&       bndBox) const
00281   throw ( SALOME_Exception )
00282 {
00283   double x0,y0,z0, x1,y1,z1;
00284   if ( IsGridBySpacing(0) || IsGridBySpacing(1) || IsGridBySpacing(2))
00285   {
00286     if ( bndBox.IsVoid() ||
00287          bndBox.IsXThin( Precision::Confusion() ) ||
00288          bndBox.IsYThin( Precision::Confusion() ) ||
00289          bndBox.IsZThin( Precision::Confusion() ) )
00290       throw SALOME_Exception(LOCALIZED("Invalid bounding box"));
00291     bndBox.Get(x0,y0,z0, x1,y1,z1);
00292   }
00293 
00294   StdMeshers_CartesianParameters3D* me = const_cast<StdMeshers_CartesianParameters3D*>(this);
00295   if ( IsGridBySpacing(0) )
00296     ComputeCoordinates( x0, x1, me->_spaceFunctions[0], me->_internalPoints[0], xNodes, "X" );
00297   else
00298     xNodes = _coords[0];
00299 
00300   if ( IsGridBySpacing(1) )
00301     ComputeCoordinates( y0, y1, me->_spaceFunctions[1], me->_internalPoints[1], yNodes, "Y" );
00302   else
00303     yNodes = _coords[1];
00304 
00305   if ( IsGridBySpacing(2) )
00306     ComputeCoordinates( z0, z1, me->_spaceFunctions[2], me->_internalPoints[2], zNodes, "Z" );
00307   else
00308     zNodes = _coords[2];
00309 }
00310 
00311 //=======================================================================
00312 //function : GetGrid
00313 //purpose  : Return coordinates of node positions along the three axes
00314 //=======================================================================
00315 
00316 void StdMeshers_CartesianParameters3D::GetGrid(std::vector<double>& coords, int axis) const
00317   throw ( SALOME_Exception )
00318 {
00319   if ( IsGridBySpacing(axis) )
00320     throw SALOME_Exception(LOCALIZED("The grid is defined by spacing and not by coordinates"));
00321 
00322   coords = _coords[axis];
00323 }
00324 
00325 //=======================================================================
00326 //function : GetSizeThreshold
00327 //purpose  : Return size threshold
00328 //=======================================================================
00329 
00330 double StdMeshers_CartesianParameters3D::GetSizeThreshold() const
00331 {
00332   return _sizeThreshold;
00333 }
00334 
00335 //=======================================================================
00336 //function : IsDefined
00337 //purpose  : Return true if parameters are well defined
00338 //=======================================================================
00339 
00340 bool StdMeshers_CartesianParameters3D::IsDefined() const
00341 {
00342   for ( int i = 0; i < 3; ++i )
00343     if (_coords[i].empty() && (_spaceFunctions[i].empty() || _internalPoints[i].empty()))
00344       return false;
00345 
00346   return ( _sizeThreshold > 1.0 );
00347 }
00348 
00349 //=======================================================================
00350 //function : SaveTo
00351 //purpose  : store my parameters into a stream
00352 //=======================================================================
00353 
00354 std::ostream & StdMeshers_CartesianParameters3D::SaveTo(std::ostream & save)
00355 {
00356   save << _sizeThreshold << " ";
00357 
00358   for ( int i = 0; i < 3; ++i )
00359   {
00360     save << _coords[i].size() << " ";
00361     for ( size_t j = 0; j < _coords[i].size(); ++j )
00362       save << _coords[i][j] << " ";
00363 
00364     save << _internalPoints[i].size() << " ";
00365     for ( size_t j = 0; j < _internalPoints[i].size(); ++j )
00366       save << _internalPoints[i][j] << " ";
00367 
00368     save << _spaceFunctions[i].size() << " ";
00369     for ( size_t j = 0; j < _spaceFunctions[i].size(); ++j )
00370       save << _spaceFunctions[i][j] << " ";
00371   }
00372 
00373   return save;
00374 }
00375 
00376 //=======================================================================
00377 //function : LoadFrom
00378 //purpose  : resore my parameters from a stream
00379 //=======================================================================
00380 
00381 std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
00382 {
00383   bool ok;
00384 
00385   ok = (load >> _sizeThreshold  );
00386   for ( int ax = 0; ax < 3; ++ax )
00387   {
00388     if (ok)
00389     {
00390       size_t i = 0;
00391       ok = (load >> i  );
00392       if ( i > 0 && ok )
00393       {
00394         _coords[ax].resize( i );
00395         for ( i = 0; i < _coords[ax].size() && ok; ++i )
00396           ok = (load >> _coords[ax][i]  );
00397       }
00398     }
00399     if (ok)
00400     {
00401       size_t i = 0;
00402       ok = (load >> i  );
00403       if ( i > 0 && ok )
00404       {
00405         _internalPoints[ax].resize( i );
00406         for ( i = 0; i < _internalPoints[ax].size() && ok; ++i )
00407           ok = (load >> _internalPoints[ax][i]  );
00408       }
00409     }
00410     if (ok)
00411     {
00412       size_t i = 0;
00413       ok = (load >> i  );
00414       if ( i > 0 && ok )
00415       {
00416         _spaceFunctions[ax].resize( i );
00417         for ( i = 0; i < _spaceFunctions[ax].size() && ok; ++i )
00418           ok = (load >> _spaceFunctions[ax][i]  );
00419       }
00420     }
00421   }
00422   return load;
00423 }
00424 
00425 //=======================================================================
00426 //function : SetParametersByMesh
00427 //=======================================================================
00428 
00429 bool StdMeshers_CartesianParameters3D::SetParametersByMesh(const SMESH_Mesh*   ,
00430                                                            const TopoDS_Shape& )
00431 {
00432   return false;
00433 }
00434 
00435 //=======================================================================
00436 //function : SetParametersByDefaults
00437 //=======================================================================
00438 
00439 bool StdMeshers_CartesianParameters3D::SetParametersByDefaults(const TDefaults&  dflts,
00440                                                                const SMESH_Mesh* /*theMesh*/)
00441 {
00442   if ( dflts._elemLength > 1e-100 )
00443   {
00444     vector<string> spacing( 1, SMESH_Comment(dflts._elemLength));
00445     vector<double> intPnts;
00446     SetGridSpacing( spacing, intPnts, 0 );
00447     SetGridSpacing( spacing, intPnts, 1 );
00448     SetGridSpacing( spacing, intPnts, 2 );
00449     return true;
00450   }
00451   return false;
00452 }
00453