1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : StdMeshers_CartesianParameters3D.cxx
24 // Author : Edward AGAPOV
27 #include "StdMeshers_CartesianParameters3D.hxx"
29 #include "StdMeshers_NumberOfSegments.hxx"
30 #include "StdMeshers_Distribution.hxx"
31 #include "SMESH_Gen.hxx"
33 #include "utilities.h"
35 #include <Precision.hxx>
36 #include <Bnd_Box.hxx>
42 //=======================================================================
43 //function : StdMeshers_CartesianParameters3D
44 //purpose : Constructor
45 //=======================================================================
47 StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int hypId,
50 : SMESH_Hypothesis(hypId, studyId, gen),
51 _sizeThreshold( 4.0 ) // default according to the customer specification
53 _name = "CartesianParameters3D"; // used by "Cartesian_3D"
54 _param_algo_dim = 3; // 3D
60 const char* axisName[3] = { "X", "Y", "Z" };
62 //================================================================================
64 * \brief Checks validity of an axis index, throws in case of invalidity
66 //================================================================================
68 void checkAxis(const int axis)
70 if ( axis < 0 || axis > 2 )
71 throw SALOME_Exception(SMESH_Comment("Invalid axis index ") << axis <<
72 ". Valid axis indices are 0, 1 and 2");
75 //================================================================================
77 * \brief Checks validity of spacing data, throws in case of invalidity
79 //================================================================================
81 void checkGridSpacing(std::vector<std::string>& spaceFunctions,
82 std::vector<double>& internalPoints,
83 const std::string& axis)
84 throw ( SALOME_Exception )
86 if ( spaceFunctions.empty() )
87 throw SALOME_Exception(SMESH_Comment("Empty space function for ") << axis );
89 for ( size_t i = 1; i < internalPoints.size(); ++i )
90 if ( internalPoints[i] - internalPoints[i-1] < 0 )
91 throw SALOME_Exception(SMESH_Comment("Wrong order of internal points along ") << axis);
92 else if ( internalPoints[i] - internalPoints[i-1] < 1e-3 )
93 throw SALOME_Exception(SMESH_Comment("Too close internal points along ") << axis );
95 const double tol = Precision::Confusion();
96 if ( !internalPoints.empty() &&
97 ( internalPoints.front() < -tol || internalPoints.back() > 1 + tol ))
98 throw SALOME_Exception(SMESH_Comment("Invalid internal points along ") << axis);
100 if ( internalPoints.empty() || internalPoints.front() > tol )
101 internalPoints.insert( internalPoints.begin(), 0. );
102 if ( internalPoints.size() < 2 || internalPoints.back() < 1 - tol )
103 internalPoints.push_back( 1. );
105 if ( internalPoints.size() != spaceFunctions.size() + 1 )
106 throw SALOME_Exception
107 (SMESH_Comment("Numbre of internal points mismatch number of functions for ") << axis);
109 for ( size_t i = 0; i < spaceFunctions.size(); ++i )
111 StdMeshers_NumberOfSegments::CheckExpressionFunction( spaceFunctions[i], -1 );
115 //=======================================================================
117 //purpose : Sets coordinates of node positions along an axes
118 //=======================================================================
120 void StdMeshers_CartesianParameters3D::SetGrid(std::vector<double>& coords, int axis)
121 throw ( SALOME_Exception )
125 if ( coords.size() < 2 )
126 throw SALOME_Exception(LOCALIZED("Wrong number of grid coordinates"));
128 std::sort( coords.begin(), coords.end() );
130 bool changed = ( _coords[axis] != coords );
133 _coords[axis] = coords;
134 NotifySubMeshesHypothesisModification();
137 _spaceFunctions[axis].clear();
138 _internalPoints[axis].clear();
141 //=======================================================================
142 //function : SetGridSpacing
143 //purpose : Set grid spacing along the three axes
144 //=======================================================================
146 void StdMeshers_CartesianParameters3D::SetGridSpacing(std::vector<string>& xSpaceFuns,
147 std::vector<double>& xInternalPoints,
149 throw ( SALOME_Exception )
153 checkGridSpacing( xSpaceFuns, xInternalPoints, axisName[axis] );
155 bool changed = ( xSpaceFuns != _spaceFunctions[axis] ||
156 xInternalPoints != _internalPoints[axis] );
158 _spaceFunctions[axis] = xSpaceFuns;
159 _internalPoints[axis] = xInternalPoints;
160 _coords[axis].clear();
163 NotifySubMeshesHypothesisModification();
166 //=======================================================================
167 //function : SetSizeThreshold
168 //purpose : Set size threshold
169 //=======================================================================
171 void StdMeshers_CartesianParameters3D::SetSizeThreshold(const double threshold)
172 throw ( SALOME_Exception )
174 if ( threshold <= 1.0 )
175 throw SALOME_Exception(LOCALIZED("threshold must be > 1.0"));
177 bool changed = fabs( _sizeThreshold - threshold ) > 1e-6;
178 _sizeThreshold = threshold;
181 NotifySubMeshesHypothesisModification();
184 //=======================================================================
185 //function : GetGridSpacing
186 //purpose : return spacing
187 //=======================================================================
189 void StdMeshers_CartesianParameters3D::GetGridSpacing(std::vector<std::string>& spaceFunctions,
190 std::vector<double>& internalPoints,
191 const int axis) const
192 throw ( SALOME_Exception )
194 if ( !IsGridBySpacing(axis) )
195 throw SALOME_Exception(LOCALIZED("The grid is defined by coordinates and not by spacing"));
197 spaceFunctions = _spaceFunctions[axis];
198 internalPoints = _internalPoints[axis];
201 //=======================================================================
202 //function : IsGridBySpacing
203 //=======================================================================
205 bool StdMeshers_CartesianParameters3D::IsGridBySpacing(const int axis) const
206 throw ( SALOME_Exception )
209 return !_spaceFunctions[axis].empty();
213 //=======================================================================
214 //function : ComputeCoordinates
215 //purpose : Computes node coordinates by spacing functions
216 //=======================================================================
218 void StdMeshers_CartesianParameters3D::ComputeCoordinates(const double x0,
220 vector<std::string>& spaceFuns,
221 vector<double>& points,
222 vector<double>& coords,
223 const std::string& axis )
224 throw ( SALOME_Exception )
226 checkGridSpacing( spaceFuns, points, axis );
229 for ( size_t i = 0; i < spaceFuns.size(); ++i )
231 FunctionExpr fun( spaceFuns[i].c_str(), /*convMode=*/-1 );
233 const double p0 = x0 * ( 1. - points[i]) + x1 * points[i];
234 const double p1 = x0 * ( 1. - points[i+1]) + x1 * points[i+1];
235 const double length = p1 - p0;
237 const size_t nbSections = 1000;
238 const double sectionLen = ( p1 - p0 ) / nbSections;
239 vector< double > nbSegments( nbSections + 1 );
240 nbSegments[ 0 ] = 0.;
242 double t, spacing = 0;
243 for ( size_t i = 1; i <= nbSections; ++i )
245 t = double( i ) / nbSections;
246 if ( !fun.value( t, spacing ) || spacing < std::numeric_limits<double>::min() )
247 throw SALOME_Exception(LOCALIZED("Invalid spacing function"));
248 nbSegments[ i ] = nbSegments[ i-1 ] + std::min( 1., sectionLen / spacing );
251 const int nbCells = max (1, int(floor(nbSegments.back()+0.5)));
252 const double corr = nbCells / nbSegments.back();
254 if ( coords.empty() ) coords.push_back( p0 );
256 for ( size_t iCell = 1, i = 1; i <= nbSections; ++i )
258 if ( nbSegments[i]*corr >= iCell )
260 t = (i - ( nbSegments[i] - iCell/corr )/( nbSegments[i] - nbSegments[i-1] )) / nbSections;
261 coords.push_back( p0 + t * length );
265 const double lastCellLen = coords.back() - coords[ coords.size() - 2 ];
266 if ( fabs( coords.back() - p1 ) > 0.5 * lastCellLen )
267 coords.push_back ( p1 );
271 //=======================================================================
272 //function : GetCoordinates
273 //purpose : Return coordinates of node positions along the three axes.
274 // If the grid is defined by spacing functions, the coordinates are computed
275 //=======================================================================
277 void StdMeshers_CartesianParameters3D::GetCoordinates(std::vector<double>& xNodes,
278 std::vector<double>& yNodes,
279 std::vector<double>& zNodes,
280 const Bnd_Box& bndBox) const
281 throw ( SALOME_Exception )
283 double x0,y0,z0, x1,y1,z1;
284 if ( IsGridBySpacing(0) || IsGridBySpacing(1) || IsGridBySpacing(2))
286 if ( bndBox.IsVoid() ||
287 bndBox.IsXThin( Precision::Confusion() ) ||
288 bndBox.IsYThin( Precision::Confusion() ) ||
289 bndBox.IsZThin( Precision::Confusion() ) )
290 throw SALOME_Exception(LOCALIZED("Invalid bounding box"));
291 bndBox.Get(x0,y0,z0, x1,y1,z1);
294 StdMeshers_CartesianParameters3D* me = const_cast<StdMeshers_CartesianParameters3D*>(this);
295 if ( IsGridBySpacing(0) )
296 ComputeCoordinates( x0, x1, me->_spaceFunctions[0], me->_internalPoints[0], xNodes, "X" );
300 if ( IsGridBySpacing(1) )
301 ComputeCoordinates( y0, y1, me->_spaceFunctions[1], me->_internalPoints[1], yNodes, "Y" );
305 if ( IsGridBySpacing(2) )
306 ComputeCoordinates( z0, z1, me->_spaceFunctions[2], me->_internalPoints[2], zNodes, "Z" );
311 //=======================================================================
313 //purpose : Return coordinates of node positions along the three axes
314 //=======================================================================
316 void StdMeshers_CartesianParameters3D::GetGrid(std::vector<double>& coords, int axis) const
317 throw ( SALOME_Exception )
319 if ( IsGridBySpacing(axis) )
320 throw SALOME_Exception(LOCALIZED("The grid is defined by spacing and not by coordinates"));
322 coords = _coords[axis];
325 //=======================================================================
326 //function : GetSizeThreshold
327 //purpose : Return size threshold
328 //=======================================================================
330 double StdMeshers_CartesianParameters3D::GetSizeThreshold() const
332 return _sizeThreshold;
335 //=======================================================================
336 //function : IsDefined
337 //purpose : Return true if parameters are well defined
338 //=======================================================================
340 bool StdMeshers_CartesianParameters3D::IsDefined() const
342 for ( int i = 0; i < 3; ++i )
343 if (_coords[i].empty() && (_spaceFunctions[i].empty() || _internalPoints[i].empty()))
346 return ( _sizeThreshold > 1.0 );
349 //=======================================================================
351 //purpose : store my parameters into a stream
352 //=======================================================================
354 std::ostream & StdMeshers_CartesianParameters3D::SaveTo(std::ostream & save)
356 save << _sizeThreshold << " ";
358 for ( int i = 0; i < 3; ++i )
360 save << _coords[i].size() << " ";
361 for ( size_t j = 0; j < _coords[i].size(); ++j )
362 save << _coords[i][j] << " ";
364 save << _internalPoints[i].size() << " ";
365 for ( size_t j = 0; j < _internalPoints[i].size(); ++j )
366 save << _internalPoints[i][j] << " ";
368 save << _spaceFunctions[i].size() << " ";
369 for ( size_t j = 0; j < _spaceFunctions[i].size(); ++j )
370 save << _spaceFunctions[i][j] << " ";
376 //=======================================================================
377 //function : LoadFrom
378 //purpose : resore my parameters from a stream
379 //=======================================================================
381 std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
385 ok = (load >> _sizeThreshold );
386 for ( int ax = 0; ax < 3; ++ax )
394 _coords[ax].resize( i );
395 for ( i = 0; i < _coords[ax].size() && ok; ++i )
396 ok = (load >> _coords[ax][i] );
405 _internalPoints[ax].resize( i );
406 for ( i = 0; i < _internalPoints[ax].size() && ok; ++i )
407 ok = (load >> _internalPoints[ax][i] );
416 _spaceFunctions[ax].resize( i );
417 for ( i = 0; i < _spaceFunctions[ax].size() && ok; ++i )
418 ok = (load >> _spaceFunctions[ax][i] );
425 //=======================================================================
426 //function : SetParametersByMesh
427 //=======================================================================
429 bool StdMeshers_CartesianParameters3D::SetParametersByMesh(const SMESH_Mesh* ,
430 const TopoDS_Shape& )
435 //=======================================================================
436 //function : SetParametersByDefaults
437 //=======================================================================
439 bool StdMeshers_CartesianParameters3D::SetParametersByDefaults(const TDefaults& dflts,
440 const SMESH_Mesh* /*theMesh*/)
442 if ( dflts._elemLength > 1e-100 )
444 vector<string> spacing( 1, SMESH_Comment(dflts._elemLength));
445 vector<double> intPnts;
446 SetGridSpacing( spacing, intPnts, 0 );
447 SetGridSpacing( spacing, intPnts, 1 );
448 SetGridSpacing( spacing, intPnts, 2 );