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"
37 #include <Bnd_Box.hxx>
38 #include <Precision.hxx>
43 //=======================================================================
44 //function : StdMeshers_CartesianParameters3D
45 //purpose : Constructor
46 //=======================================================================
48 StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int hypId,
51 : SMESH_Hypothesis(hypId, studyId, gen),
52 _sizeThreshold( 4.0 ), // default according to the customer specification
55 _name = "CartesianParameters3D"; // used by "Cartesian_3D"
56 _param_algo_dim = 3; // 3D
74 const char* axisName[3] = { "X", "Y", "Z" };
76 //================================================================================
78 * \brief Checks validity of an axis index, throws in case of invalidity
80 //================================================================================
82 void checkAxis(const int axis)
84 if ( axis < 0 || axis > 2 )
85 throw SALOME_Exception(SMESH_Comment("Invalid axis index ") << axis <<
86 ". Valid axis indices are 0, 1 and 2");
89 //================================================================================
91 * \brief Checks validity of spacing data, throws in case of invalidity
93 //================================================================================
95 void checkGridSpacing(std::vector<std::string>& spaceFunctions,
96 std::vector<double>& internalPoints,
97 const std::string& axis)
98 throw ( SALOME_Exception )
100 if ( spaceFunctions.empty() )
101 throw SALOME_Exception(SMESH_Comment("Empty space function for ") << axis );
103 for ( size_t i = 1; i < internalPoints.size(); ++i )
104 if ( internalPoints[i] - internalPoints[i-1] < 0 )
105 throw SALOME_Exception(SMESH_Comment("Wrong order of internal points along ") << axis);
106 else if ( internalPoints[i] - internalPoints[i-1] < 1e-3 )
107 throw SALOME_Exception(SMESH_Comment("Too close internal points along ") << axis );
109 const double tol = Precision::Confusion();
110 if ( !internalPoints.empty() &&
111 ( internalPoints.front() < -tol || internalPoints.back() > 1 + tol ))
112 throw SALOME_Exception(SMESH_Comment("Invalid internal points along ") << axis);
114 if ( internalPoints.empty() || internalPoints.front() > tol )
115 internalPoints.insert( internalPoints.begin(), 0. );
116 if ( internalPoints.size() < 2 || internalPoints.back() < 1 - tol )
117 internalPoints.push_back( 1. );
119 if ( internalPoints.size() != spaceFunctions.size() + 1 )
120 throw SALOME_Exception
121 (SMESH_Comment("Numbre of internal points mismatch number of functions for ") << axis);
123 for ( size_t i = 0; i < spaceFunctions.size(); ++i )
125 StdMeshers_NumberOfSegments::CheckExpressionFunction( spaceFunctions[i], -1 );
129 //=======================================================================
131 //purpose : Sets coordinates of node positions along an axes
132 //=======================================================================
134 void StdMeshers_CartesianParameters3D::SetGrid(std::vector<double>& coords, int axis)
135 throw ( SALOME_Exception )
139 if ( coords.size() < 2 )
140 throw SALOME_Exception(LOCALIZED("Wrong number of grid coordinates"));
142 std::sort( coords.begin(), coords.end() );
144 bool changed = ( _coords[axis] != coords );
147 _coords[axis] = coords;
148 NotifySubMeshesHypothesisModification();
151 _spaceFunctions[axis].clear();
152 _internalPoints[axis].clear();
155 //=======================================================================
156 //function : SetGridSpacing
157 //purpose : Set grid spacing along the three axes
158 //=======================================================================
160 void StdMeshers_CartesianParameters3D::SetGridSpacing(std::vector<string>& xSpaceFuns,
161 std::vector<double>& xInternalPoints,
163 throw ( SALOME_Exception )
167 checkGridSpacing( xSpaceFuns, xInternalPoints, axisName[axis] );
169 bool changed = ( xSpaceFuns != _spaceFunctions[axis] ||
170 xInternalPoints != _internalPoints[axis] );
172 _spaceFunctions[axis] = xSpaceFuns;
173 _internalPoints[axis] = xInternalPoints;
174 _coords[axis].clear();
177 NotifySubMeshesHypothesisModification();
180 //=======================================================================
181 //function : SetSizeThreshold
182 //purpose : Set size threshold
183 //=======================================================================
185 void StdMeshers_CartesianParameters3D::SetSizeThreshold(const double threshold)
186 throw ( SALOME_Exception )
188 if ( threshold <= 1.0 )
189 throw SALOME_Exception(LOCALIZED("threshold must be > 1.0"));
191 bool changed = fabs( _sizeThreshold - threshold ) > 1e-6;
192 _sizeThreshold = threshold;
195 NotifySubMeshesHypothesisModification();
198 //=======================================================================
199 //function : GetGridSpacing
200 //purpose : return spacing
201 //=======================================================================
203 void StdMeshers_CartesianParameters3D::GetGridSpacing(std::vector<std::string>& spaceFunctions,
204 std::vector<double>& internalPoints,
205 const int axis) const
206 throw ( SALOME_Exception )
208 if ( !IsGridBySpacing(axis) )
209 throw SALOME_Exception(LOCALIZED("The grid is defined by coordinates and not by spacing"));
211 spaceFunctions = _spaceFunctions[axis];
212 internalPoints = _internalPoints[axis];
215 //=======================================================================
216 //function : IsGridBySpacing
217 //=======================================================================
219 bool StdMeshers_CartesianParameters3D::IsGridBySpacing(const int axis) const
220 throw ( SALOME_Exception )
223 return !_spaceFunctions[axis].empty();
227 //=======================================================================
228 //function : ComputeCoordinates
229 //purpose : Computes node coordinates by spacing functions
230 //=======================================================================
232 void StdMeshers_CartesianParameters3D::ComputeCoordinates(const double x0,
234 vector<std::string>& spaceFuns,
235 vector<double>& points,
236 vector<double>& coords,
237 const std::string& axis )
238 throw ( SALOME_Exception )
240 checkGridSpacing( spaceFuns, points, axis );
243 for ( size_t i = 0; i < spaceFuns.size(); ++i )
245 FunctionExpr fun( spaceFuns[i].c_str(), /*convMode=*/-1 );
247 const double p0 = x0 * ( 1. - points[i]) + x1 * points[i];
248 const double p1 = x0 * ( 1. - points[i+1]) + x1 * points[i+1];
249 const double length = p1 - p0;
251 const size_t nbSections = 1000;
252 const double sectionLen = ( p1 - p0 ) / nbSections;
253 vector< double > nbSegments( nbSections + 1 );
254 nbSegments[ 0 ] = 0.;
256 double t, spacing = 0;
257 for ( size_t i = 1; i <= nbSections; ++i )
259 t = double( i ) / nbSections;
260 if ( !fun.value( t, spacing ) || spacing < std::numeric_limits<double>::min() )
261 throw SALOME_Exception(LOCALIZED("Invalid spacing function"));
262 nbSegments[ i ] = nbSegments[ i-1 ] + std::min( 1., sectionLen / spacing );
265 const int nbCells = max (1, int(floor(nbSegments.back()+0.5)));
266 const double corr = nbCells / nbSegments.back();
268 if ( coords.empty() ) coords.push_back( p0 );
270 for ( size_t iCell = 1, i = 1; i <= nbSections; ++i )
272 if ( nbSegments[i]*corr >= iCell )
274 t = (i - ( nbSegments[i] - iCell/corr )/( nbSegments[i] - nbSegments[i-1] )) / nbSections;
275 coords.push_back( p0 + t * length );
279 const double lastCellLen = coords.back() - coords[ coords.size() - 2 ];
280 if ( fabs( coords.back() - p1 ) > 0.5 * lastCellLen )
281 coords.push_back ( p1 );
285 //=======================================================================
286 //function : GetCoordinates
287 //purpose : Return coordinates of node positions along the three axes.
288 // If the grid is defined by spacing functions, the coordinates are computed
289 //=======================================================================
291 void StdMeshers_CartesianParameters3D::GetCoordinates(std::vector<double>& xNodes,
292 std::vector<double>& yNodes,
293 std::vector<double>& zNodes,
294 const Bnd_Box& bndBox) const
295 throw ( SALOME_Exception )
297 double x0,y0,z0, x1,y1,z1;
298 if ( IsGridBySpacing(0) || IsGridBySpacing(1) || IsGridBySpacing(2))
300 if ( bndBox.IsVoid() ||
301 bndBox.IsXThin( Precision::Confusion() ) ||
302 bndBox.IsYThin( Precision::Confusion() ) ||
303 bndBox.IsZThin( Precision::Confusion() ) )
304 throw SALOME_Exception(LOCALIZED("Invalid bounding box"));
305 bndBox.Get(x0,y0,z0, x1,y1,z1);
308 StdMeshers_CartesianParameters3D* me = const_cast<StdMeshers_CartesianParameters3D*>(this);
309 if ( IsGridBySpacing(0) )
310 ComputeCoordinates( x0, x1, me->_spaceFunctions[0], me->_internalPoints[0], xNodes, "X" );
314 if ( IsGridBySpacing(1) )
315 ComputeCoordinates( y0, y1, me->_spaceFunctions[1], me->_internalPoints[1], yNodes, "Y" );
319 if ( IsGridBySpacing(2) )
320 ComputeCoordinates( z0, z1, me->_spaceFunctions[2], me->_internalPoints[2], zNodes, "Z" );
325 //=======================================================================
326 //function : SetAxisDirs
327 //purpose : Sets directions of axes
328 //=======================================================================
330 void StdMeshers_CartesianParameters3D::SetAxisDirs(const double* the9DirComps)
331 throw ( SALOME_Exception )
333 gp_Vec x( the9DirComps[0],
336 gp_Vec y( the9DirComps[3],
339 gp_Vec z( the9DirComps[6],
342 if ( x.Magnitude() < RealSmall() ||
343 y.Magnitude() < RealSmall() ||
344 z.Magnitude() < RealSmall() )
345 throw SALOME_Exception("Zero magnitude of axis direction");
347 if ( x.IsParallel( y, M_PI / 180. ) ||
348 x.IsParallel( z, M_PI / 180. ) ||
349 y.IsParallel( z, M_PI / 180. ))
350 throw SALOME_Exception("Parallel axis directions");
352 bool isChanged = false;
353 for ( int i = 0; i < 9; ++i )
355 if ( Abs( _axisDirs[i] - the9DirComps[i] ) > 1e-7 )
357 _axisDirs[i] = the9DirComps[i];
360 NotifySubMeshesHypothesisModification();
363 //=======================================================================
365 //purpose : Return coordinates of node positions along the three axes
366 //=======================================================================
368 void StdMeshers_CartesianParameters3D::GetGrid(std::vector<double>& coords, int axis) const
369 throw ( SALOME_Exception )
371 if ( IsGridBySpacing(axis) )
372 throw SALOME_Exception(LOCALIZED("The grid is defined by spacing and not by coordinates"));
374 coords = _coords[axis];
377 //=======================================================================
378 //function : GetSizeThreshold
379 //purpose : Return size threshold
380 //=======================================================================
382 double StdMeshers_CartesianParameters3D::GetSizeThreshold() const
384 return _sizeThreshold;
387 //=======================================================================
388 //function : SetToAddEdges
389 //purpose : Enables implementation of geometrical edges into the mesh. If this feature
390 // is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
391 // they don't coincide with the grid lines
392 //=======================================================================
394 void StdMeshers_CartesianParameters3D::SetToAddEdges(bool toAdd)
396 if ( _toAddEdges != toAdd )
399 NotifySubMeshesHypothesisModification();
403 //=======================================================================
404 //function : GetToAddEdges
405 //purpose : Returns true if implementation of geometrical edges into the
407 //=======================================================================
409 bool StdMeshers_CartesianParameters3D::GetToAddEdges() const
414 //=======================================================================
415 //function : IsDefined
416 //purpose : Return true if parameters are well defined
417 //=======================================================================
419 bool StdMeshers_CartesianParameters3D::IsDefined() const
421 for ( int i = 0; i < 3; ++i )
422 if (_coords[i].empty() && (_spaceFunctions[i].empty() || _internalPoints[i].empty()))
425 return ( _sizeThreshold > 1.0 );
428 //=======================================================================
430 //purpose : store my parameters into a stream
431 //=======================================================================
433 std::ostream & StdMeshers_CartesianParameters3D::SaveTo(std::ostream & save)
435 save << _sizeThreshold << " ";
437 for ( int i = 0; i < 3; ++i )
439 save << _coords[i].size() << " ";
440 for ( size_t j = 0; j < _coords[i].size(); ++j )
441 save << _coords[i][j] << " ";
443 save << _internalPoints[i].size() << " ";
444 for ( size_t j = 0; j < _internalPoints[i].size(); ++j )
445 save << _internalPoints[i][j] << " ";
447 save << _spaceFunctions[i].size() << " ";
448 for ( size_t j = 0; j < _spaceFunctions[i].size(); ++j )
449 save << _spaceFunctions[i][j] << " ";
451 save << _toAddEdges << " ";
456 //=======================================================================
457 //function : LoadFrom
458 //purpose : resore my parameters from a stream
459 //=======================================================================
461 std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
465 ok = ( load >> _sizeThreshold );
466 for ( int ax = 0; ax < 3; ++ax )
474 _coords[ax].resize( i );
475 for ( i = 0; i < _coords[ax].size() && ok; ++i )
476 ok = (load >> _coords[ax][i] );
485 _internalPoints[ax].resize( i );
486 for ( i = 0; i < _internalPoints[ax].size() && ok; ++i )
487 ok = (load >> _internalPoints[ax][i] );
496 _spaceFunctions[ax].resize( i );
497 for ( i = 0; i < _spaceFunctions[ax].size() && ok; ++i )
498 ok = (load >> _spaceFunctions[ax][i] );
508 //=======================================================================
509 //function : SetParametersByMesh
510 //=======================================================================
512 bool StdMeshers_CartesianParameters3D::SetParametersByMesh(const SMESH_Mesh* ,
513 const TopoDS_Shape& )
518 //=======================================================================
519 //function : SetParametersByDefaults
520 //=======================================================================
522 bool StdMeshers_CartesianParameters3D::SetParametersByDefaults(const TDefaults& dflts,
523 const SMESH_Mesh* /*theMesh*/)
525 if ( dflts._elemLength > 1e-100 )
527 vector<string> spacing( 1, SMESH_Comment(dflts._elemLength));
528 vector<double> intPnts;
529 SetGridSpacing( spacing, intPnts, 0 );
530 SetGridSpacing( spacing, intPnts, 1 );
531 SetGridSpacing( spacing, intPnts, 2 );