-// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021 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.
+// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <gp_Dir.hxx>
+#include <gp_Mat.hxx>
#include <gp_Pln.hxx>
#include <gp_Vec.hxx>
//=======================================================================
StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int hypId,
- int studyId,
SMESH_Gen * gen)
- : SMESH_Hypothesis(hypId, studyId, gen),
+ : SMESH_Hypothesis(hypId, gen),
_sizeThreshold( 4.0 ), // default according to the customer specification
- _toAddEdges( false )
+ _toAddEdges( false ),
+ _toConsiderInternalFaces( false ),
+ _toUseThresholdForInternalFaces( false ),
+ _toCreateFaces( false )
{
_name = "CartesianParameters3D"; // used by "Cartesian_3D"
_param_algo_dim = 3; // 3D
void checkGridSpacing(std::vector<std::string>& spaceFunctions,
std::vector<double>& internalPoints,
const std::string& axis)
- throw ( SALOME_Exception )
{
if ( spaceFunctions.empty() )
throw SALOME_Exception(SMESH_Comment("Empty space function for ") << axis );
//=======================================================================
void StdMeshers_CartesianParameters3D::SetGrid(std::vector<double>& coords, int axis)
- throw ( SALOME_Exception )
{
checkAxis( axis );
void StdMeshers_CartesianParameters3D::SetGridSpacing(std::vector<string>& xSpaceFuns,
std::vector<double>& xInternalPoints,
const int axis)
- throw ( SALOME_Exception )
{
checkAxis( axis );
//purpose : Returns either false or (true + point coordinates)
//=======================================================================
-bool StdMeshers_CartesianParameters3D::GetFixedPoint(double p[3])
+bool StdMeshers_CartesianParameters3D::GetFixedPoint(double p[3]) const
{
if ( Precision::IsInfinite( _fixedPoint[0] ))
return false;
std::copy( &_fixedPoint[0], &_fixedPoint[0]+3, &p[0] );
+ return true;
}
//=======================================================================
void StdMeshers_CartesianParameters3D::SetSizeThreshold(const double threshold)
- throw ( SALOME_Exception )
{
if ( threshold <= 1.0 )
throw SALOME_Exception(LOCALIZED("threshold must be > 1.0"));
void StdMeshers_CartesianParameters3D::GetGridSpacing(std::vector<std::string>& spaceFunctions,
std::vector<double>& internalPoints,
const int axis) const
- throw ( SALOME_Exception )
{
if ( !IsGridBySpacing(axis) )
throw SALOME_Exception(LOCALIZED("The grid is defined by coordinates and not by spacing"));
//=======================================================================
bool StdMeshers_CartesianParameters3D::IsGridBySpacing(const int axis) const
- throw ( SALOME_Exception )
{
checkAxis(axis);
return !_spaceFunctions[axis].empty();
//purpose : Computes node coordinates by spacing functions
//=======================================================================
-void StdMeshers_CartesianParameters3D::ComputeCoordinates(const double x0,
- const double x1,
- vector<std::string>& spaceFuns,
- vector<double>& points,
- vector<double>& coords,
- const std::string& axis )
- throw ( SALOME_Exception )
+void StdMeshers_CartesianParameters3D::ComputeCoordinates(const double x0,
+ const double x1,
+ vector<string>& theSpaceFuns,
+ vector<double>& thePoints,
+ vector<double>& coords,
+ const string& axis,
+ const double* xForced )
{
- checkGridSpacing( spaceFuns, points, axis );
+ checkGridSpacing( theSpaceFuns, thePoints, axis );
+
+ vector<string> spaceFuns = theSpaceFuns;
+ vector<double> points = thePoints;
+
+ bool forced = false;
+ if (( forced = ( xForced && ( x0 < *xForced ) && ( *xForced < x1 ))))
+ {
+ // divide a range at xForced
+
+ // find a range to insert xForced
+ double pos = ( *xForced - x0 ) / ( x1 - x0 );
+ int iR = 1;
+ while ( pos > points[ iR ] ) ++iR;
+
+ // insert xForced
+ vector<double>::iterator pntIt = points.begin() + iR;
+ points.insert( pntIt, pos );
+ vector<string>::iterator funIt = spaceFuns.begin() + iR;
+ spaceFuns.insert( funIt, spaceFuns[ iR-1 ]);
+ }
coords.clear();
for ( size_t i = 0; i < spaceFuns.size(); ++i )
{
- FunctionExpr fun( spaceFuns[i].c_str(), /*convMode=*/-1 );
+ StdMeshers::FunctionExpr fun( spaceFuns[i].c_str(), /*convMode=*/-1 );
const double p0 = x0 * ( 1. - points[i]) + x1 * points[i];
const double p1 = x0 * ( 1. - points[i+1]) + x1 * points[i+1];
const double length = p1 - p0;
- const size_t nbSections = 1000;
+ const int nbSections = 1000;
const double sectionLen = ( p1 - p0 ) / nbSections;
vector< double > nbSegments( nbSections + 1 );
nbSegments[ 0 ] = 0.;
double t, spacing = 0;
- for ( size_t i = 1; i <= nbSections; ++i )
+ for ( int i = 1; i <= nbSections; ++i )
{
t = double( i ) / nbSections;
if ( !fun.value( t, spacing ) || spacing < std::numeric_limits<double>::min() )
if ( coords.empty() ) coords.push_back( p0 );
- for ( size_t iCell = 1, i = 1; i <= nbSections; ++i )
+ for ( int iCell = 1, j = 1; j <= nbSections; ++j )
{
- if ( nbSegments[i]*corr >= iCell )
+ if ( nbSegments[j]*corr >= iCell )
{
- t = (i - ( nbSegments[i] - iCell/corr )/( nbSegments[i] - nbSegments[i-1] )) / nbSections;
+ t = (j - ( nbSegments[j] - iCell/corr )/( nbSegments[j] - nbSegments[j-1] )) / nbSections;
coords.push_back( p0 + t * length );
++iCell;
}
if ( fabs( coords.back() - p1 ) > 0.5 * lastCellLen )
coords.push_back ( p1 );
}
+
+ // correct coords if a forced point is too close to a neighbor node
+ if ( forced )
+ {
+ size_t iF = 0;
+ double minLen = ( x1 - x0 );
+ for ( size_t i = 1; i < coords.size(); ++i )
+ {
+ if ( !iF && Abs( coords[i] - *xForced ) < 1e-20 )
+ iF = i++; // xForced found
+ else
+ minLen = Min( minLen, coords[i] - coords[i-1] );
+ }
+ const double tol = minLen * 1e-3;
+ int iRem = -1;
+ if (( iF > 1 ) && ( coords[iF] - coords[iF-1] < tol ))
+ iRem = (int) iF-1;
+ else if (( iF < coords.size()-2 ) && ( coords[iF+1] - coords[iF] < tol ))
+ iRem = (int) iF+1;
+ if ( iRem > 0 )
+ coords.erase( coords.begin() + iRem );
+ }
}
//=======================================================================
std::vector<double>& yNodes,
std::vector<double>& zNodes,
const Bnd_Box& bndBox) const
- throw ( SALOME_Exception )
{
double x0,y0,z0, x1,y1,z1;
if ( IsGridBySpacing(0) || IsGridBySpacing(1) || IsGridBySpacing(2))
bndBox.Get(x0,y0,z0, x1,y1,z1);
}
+ double fp[3], *pfp[3] = { NULL, NULL, NULL };
+ if ( GetFixedPoint( fp ))
+ {
+ // convert fp into a basis defined by _axisDirs
+ gp_XYZ axis[3] = { gp_XYZ( _axisDirs[0], _axisDirs[1], _axisDirs[2] ),
+ gp_XYZ( _axisDirs[3], _axisDirs[4], _axisDirs[5] ),
+ gp_XYZ( _axisDirs[6], _axisDirs[7], _axisDirs[8] ) };
+ axis[0].Normalize();
+ axis[1].Normalize();
+ axis[2].Normalize();
+
+ gp_Mat basis( axis[0], axis[1], axis[2] );
+ gp_Mat bi = basis.Inverted();
+
+ gp_XYZ p( fp[0], fp[1], fp[2] );
+ p *= bi;
+ p.Coord( fp[0], fp[1], fp[2] );
+
+ pfp[0] = & fp[0];
+ pfp[1] = & fp[1];
+ pfp[2] = & fp[2];
+ }
+
StdMeshers_CartesianParameters3D* me = const_cast<StdMeshers_CartesianParameters3D*>(this);
if ( IsGridBySpacing(0) )
- ComputeCoordinates( x0, x1, me->_spaceFunctions[0], me->_internalPoints[0], xNodes, "X" );
+ ComputeCoordinates
+ ( x0, x1, me->_spaceFunctions[0], me->_internalPoints[0], xNodes, "X", pfp[0] );
else
xNodes = _coords[0];
if ( IsGridBySpacing(1) )
- ComputeCoordinates( y0, y1, me->_spaceFunctions[1], me->_internalPoints[1], yNodes, "Y" );
+ ComputeCoordinates
+ ( y0, y1, me->_spaceFunctions[1], me->_internalPoints[1], yNodes, "Y", pfp[1] );
else
yNodes = _coords[1];
if ( IsGridBySpacing(2) )
- ComputeCoordinates( z0, z1, me->_spaceFunctions[2], me->_internalPoints[2], zNodes, "Z" );
+ ComputeCoordinates
+ ( z0, z1, me->_spaceFunctions[2], me->_internalPoints[2], zNodes, "Z", pfp[2] );
else
zNodes = _coords[2];
}
const TCooTriple* norm1 = 0;
double sumArea = 0;
vector< const TCooTriple* > norms;
- for ( int iF = 1; norm2a != areasByNormal.end(); ++norm2a, ++iF )
+ for ( size_t iF = 1; norm2a != areasByNormal.end(); ++norm2a, ++iF )
{
-
if ( !norm1 || !sameDir( *norm1, norm2a->first ))
{
if ( !norms.empty() )
//=======================================================================
void StdMeshers_CartesianParameters3D::SetAxisDirs(const double* the9DirComps)
- throw ( SALOME_Exception )
{
gp_Vec x( the9DirComps[0],
the9DirComps[1],
//=======================================================================
void StdMeshers_CartesianParameters3D::GetGrid(std::vector<double>& coords, int axis) const
- throw ( SALOME_Exception )
{
if ( IsGridBySpacing(axis) )
throw SALOME_Exception(LOCALIZED("The grid is defined by spacing and not by coordinates"));
return _toAddEdges;
}
+//=======================================================================
+//function : SetToConsiderInternalFaces
+//purpose : Enables treatment of geom faces either shared by solids or internal
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetToConsiderInternalFaces(bool toTreat)
+{
+ if ( _toConsiderInternalFaces != toTreat )
+ {
+ _toConsiderInternalFaces = toTreat;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//=======================================================================
+//function : SetToUseThresholdForInternalFaces
+//purpose : Enables applying size threshold to grid cells cut by internal geom faces.
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetToUseThresholdForInternalFaces(bool toUse)
+{
+ if ( _toUseThresholdForInternalFaces != toUse )
+ {
+ _toUseThresholdForInternalFaces = toUse;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//=======================================================================
+//function : SetToCreateFaces
+//purpose : Enables creation of mesh faces.
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetToCreateFaces(bool toCreate)
+{
+ if ( _toCreateFaces != toCreate )
+ {
+ _toCreateFaces = toCreate;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
//=======================================================================
//function : IsDefined
//purpose : Return true if parameters are well defined
for ( int i = 0; i < 3; ++i )
save << _fixedPoint[i] << " ";
+ save << " " << _toConsiderInternalFaces
+ << " " << _toUseThresholdForInternalFaces
+ << " " << _toCreateFaces;
+
return save;
}
//=======================================================================
//function : LoadFrom
-//purpose : resore my parameters from a stream
+//purpose : restore my parameters from a stream
//=======================================================================
std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
{
bool ok;
- ok = ( load >> _sizeThreshold );
+ ok = static_cast<bool>( load >> _sizeThreshold );
for ( int ax = 0; ax < 3; ++ax )
{
if (ok)
{
size_t i = 0;
- ok = (load >> i );
+ ok = static_cast<bool>(load >> i );
if ( i > 0 && ok )
{
_coords[ax].resize( i );
for ( i = 0; i < _coords[ax].size() && ok; ++i )
- ok = (load >> _coords[ax][i] );
+ ok = static_cast<bool>(load >> _coords[ax][i] );
}
}
if (ok)
{
size_t i = 0;
- ok = (load >> i );
+ ok = static_cast<bool>(load >> i );
if ( i > 0 && ok )
{
_internalPoints[ax].resize( i );
for ( i = 0; i < _internalPoints[ax].size() && ok; ++i )
- ok = (load >> _internalPoints[ax][i] );
+ ok = static_cast<bool>(load >> _internalPoints[ax][i] );
}
}
if (ok)
{
size_t i = 0;
- ok = (load >> i );
+ ok = static_cast<bool>(load >> i );
if ( i > 0 && ok )
{
_spaceFunctions[ax].resize( i );
for ( i = 0; i < _spaceFunctions[ax].size() && ok; ++i )
- ok = (load >> _spaceFunctions[ax][i] );
+ ok = static_cast<bool>(load >> _spaceFunctions[ax][i] );
}
}
}
- ok = ( load >> _toAddEdges );
+ ok = static_cast<bool>( load >> _toAddEdges );
for ( int i = 0; i < 9 && ok; ++i )
- ok = ( load >> _axisDirs[i]);
+ ok = static_cast<bool>( load >> _axisDirs[i]);
for ( int i = 0; i < 3 && ok ; ++i )
- ok = ( load >> _fixedPoint[i]);
+ ok = static_cast<bool>( load >> _fixedPoint[i]);
+
+ if ( load >> _toConsiderInternalFaces )
+ {
+ load >> _toUseThresholdForInternalFaces;
+ load >> _toCreateFaces;
+ }
return load;
}