-// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012 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
#include "Utils_ExceptHandlers.hxx"
#include <TopoDS_Iterator.hxx>
+#include <LDOMParser.hxx>
#include "memoire.h"
+#ifdef WNT
+ #include <windows.h>
+#endif\r
+
using namespace std;
+//#include <vtkDebugLeaks.h>
+
+
//=============================================================================
/*!
* Constructor
_segmentation = _nbSegments = 10;
SMDS_Mesh::_meshList.clear();
MESSAGE(SMDS_Mesh::_meshList.size());
- _counters = new counters(100);
+ //_counters = new counters(100);
#ifdef WITH_SMESH_CANCEL_COMPUTE
_compute_canceled = false;
_sm_current = NULL;
#endif
+ //vtkDebugLeaks::SetExitError(0);
}
//=============================================================================
SMESH_Gen::~SMESH_Gen()
{
MESSAGE("SMESH_Gen::~SMESH_Gen");
+ std::map < int, StudyContextStruct * >::iterator i_sc = _mapStudyContext.begin();
+ for ( ; i_sc != _mapStudyContext.end(); ++i_sc )
+ {
+ delete i_sc->second->myDocument;
+ delete i_sc->second;
+ }
}
//=============================================================================
// check for preview dimension limitations
if ( aShapesId && GetShapeDim( aShType ) > (int)aDim )
{
- // clear compute state to not show previous compute errors
+ // clear compute state not to show previous compute errors
// if preview invoked less dimension less than previous
smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
continue;
else
{
// -----------------------------------------------------------------
- // apply algos that DO NOT require descretized boundaries and DO NOT
+ // apply algos that DO NOT require Discreteized boundaries and DO NOT
// support submeshes, starting from the most complex shapes
// and collect submeshes with algos that DO support submeshes
// -----------------------------------------------------------------
continue;
SMESH_Algo* algo = GetAlgo( aMesh, aSubShape, &algoShape );
- if ( algo && !algo->NeedDescretBoundary() )
+ if ( algo && !algo->NeedDiscreteBoundary() )
{
if ( algo->SupportSubmeshes() )
{
// ------------------------------------------------------------
// compute submeshes under shapes with algos that DO NOT require
- // descretized boundaries and DO support submeshes
+ // Discreteized boundaries and DO support submeshes
// ------------------------------------------------------------
list< SMESH_subMesh* >::iterator subIt, subEnd;
subIt = smWithAlgoSupportingSubmeshes.begin();
SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
filter
.And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
- .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh.GetShapeToMesh() ));
+ .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
SMESH_Hypothesis::Hypothesis_Status status;
}
}
// ----------------------------------------------------------
- // apply the algos that do not require descretized boundaries
+ // apply the algos that do not require Discreteized boundaries
// ----------------------------------------------------------
for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
{
MEMOSTAT;
SMESHDS_Mesh *myMesh = aMesh.GetMeshDS();
- myMesh->adjustStructure();
MESSAGE("*** compactMesh after compute");
myMesh->compactMesh();
- //myMesh->adjustStructure();
- list<int> listind = myMesh->SubMeshIndices();
- list<int>::iterator it = listind.begin();
- int total = 0;
- for(; it != listind.end(); ++it)
- {
- ::SMESHDS_SubMesh *subMesh = myMesh->MeshElements(*it);
- total += subMesh->getSize();
- }
- MESSAGE("total elements and nodes in submesh sets:" << total);
- MESSAGE("Number of node objects " << SMDS_MeshNode::nbNodes);
- MESSAGE("Number of cell objects " << SMDS_MeshCell::nbCells);
- //myMesh->dumpGrid();
- //aMesh.GetMeshDS()->Modified();
// fix quadratic mesh by bending iternal links near concave boundary
if ( aShape.IsSame( aMesh.GetShapeToMesh() ) &&
{
SMESH_MesherHelper aHelper( aMesh );
if ( aHelper.IsQuadraticMesh() != SMESH_MesherHelper::LINEAR )
- aHelper.FixQuadraticElements();
+ {
+ aHelper.FixQuadraticElements( sm->GetComputeError() );
+ }
}
return ret;
}
}
else {
// -----------------------------------------------------------------
- // apply algos that DO NOT require descretized boundaries and DO NOT
+ // apply algos that DO NOT require Discreteized boundaries and DO NOT
// support submeshes, starting from the most complex shapes
// and collect submeshes with algos that DO support submeshes
// -----------------------------------------------------------------
if ( aShapeDim < 1 ) break;
SMESH_Algo* algo = GetAlgo( aMesh, aSubShape );
- if ( algo && !algo->NeedDescretBoundary() ) {
+ if ( algo && !algo->NeedDiscreteBoundary() ) {
if ( algo->SupportSubmeshes() ) {
smWithAlgoSupportingSubmeshes.push_front( smToCompute );
}
// ------------------------------------------------------------
// compute submeshes under shapes with algos that DO NOT require
- // descretized boundaries and DO support submeshes
+ // Discreteized boundaries and DO support submeshes
// ------------------------------------------------------------
list< SMESH_subMesh* >::iterator subIt, subEnd;
subIt = smWithAlgoSupportingSubmeshes.begin();
SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
filter
.And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
- .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh.GetShapeToMesh() ));
+ .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
SMESH_Hypothesis::Hypothesis_Status status;
}
}
// ----------------------------------------------------------
- // apply the algos that do not require descretized boundaries
+ // apply the algos that do not require Discreteized boundaries
// ----------------------------------------------------------
for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
{
if ( aLocIgnoAlgo ) // algo is hidden by a local algo of upper dim
{
+ theErrors.push_back( SMESH_Gen::TAlgoStateError() );
+ theErrors.back().Set( SMESH_Hypothesis::HYP_HIDDEN_ALGO, algo, false );
INFOS( "Local <" << algo->GetName() << "> is hidden by local <"
<< aLocIgnoAlgo->GetName() << ">");
}
int dim = algo->GetDim();
int aMaxGlobIgnoDim = ( aGlobIgnoAlgo ? aGlobIgnoAlgo->GetDim() : -1 );
- if ( dim < aMaxGlobIgnoDim )
+ if ( dim < aMaxGlobIgnoDim &&
+ ( isGlobal || !aGlobIgnoAlgo->SupportSubmeshes() ))
{
// algo is hidden by a global algo
+ theErrors.push_back( SMESH_Gen::TAlgoStateError() );
+ theErrors.back().Set( SMESH_Hypothesis::HYP_HIDDEN_ALGO, algo, true );
INFOS( ( isGlobal ? "Global" : "Local" )
<< " <" << algo->GetName() << "> is hidden by global <"
<< aGlobIgnoAlgo->GetName() << ">");
}
- else if ( !algo->NeedDescretBoundary() && !isGlobal)
+ else if ( !algo->NeedDiscreteBoundary() && !isGlobal)
{
// local algo is not hidden and hides algos on sub-shapes
if (checkConform && !aSubMesh->IsConform( algo ))
set<SMESH_subMesh*>& aCheckedMap,
list< SMESH_Gen::TAlgoStateError > & theErrors)
{
- if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX)
+ switch ( aSubMesh->GetSubShape().ShapeType() )
+ {
+ case TopAbs_EDGE:
+ case TopAbs_FACE:
+ case TopAbs_SOLID: break; // check this submesh, it can be meshed
+ default:
+ return true; // not meshable submesh
+ }
+ if ( aCheckedMap.count( aSubMesh ))
return true;
//MESSAGE("=====checkMissing");
}
case SMESH_subMesh::MISSING_HYP: {
// notify if an algo missing hyp is attached to aSubMesh
- algo = aGen->GetAlgo( aMesh, aSubMesh->GetSubShape() );
+ algo = aSubMesh->GetAlgo();
ASSERT( algo );
bool IsGlobalHypothesis = aGen->IsGlobalHypothesis( algo, aMesh );
if (!IsGlobalHypothesis || !globalChecked[ algo->GetDim() ])
break;
}
case SMESH_subMesh::HYP_OK:
- algo = aGen->GetAlgo( aMesh, aSubMesh->GetSubShape() );
+ algo = aSubMesh->GetAlgo();
ret = true;
+ if (!algo->NeedDiscreteBoundary())
+ {
+ SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false,
+ /*complexShapeFirst=*/false);
+ while ( itsub->more() )
+ aCheckedMap.insert( itsub->next() );
+ }
break;
default: ASSERT(0);
}
ASSERT (algo);
bool isTopLocalAlgo =
( aTopAlgoDim <= algo->GetDim() && !aGen->IsGlobalHypothesis( algo, aMesh ));
- if (!algo->NeedDescretBoundary() || isTopLocalAlgo)
+ if (!algo->NeedDiscreteBoundary() || isTopLocalAlgo)
{
- bool checkNoAlgo2 = ( algo->NeedDescretBoundary() );
+ bool checkNoAlgo2 = ( algo->NeedDiscreteBoundary() );
SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false,
- /*complexShapeFirst=*/false);
+ /*complexShapeFirst=*/true);
while ( itsub->more() )
{
// sub-meshes should not be checked further more
SMESH_subMesh* sm = itsub->next();
- aCheckedMap.insert( sm );
if (isTopLocalAlgo)
{
checkNoAlgo2 = false;
}
}
+ aCheckedMap.insert( sm );
}
}
return ret;
bool ret = true;
bool hasAlgo = false;
- SMESH_subMesh* sm = theMesh.GetSubMesh(theShape);
+ SMESH_subMesh* sm = theMesh.GetSubMesh(theShape);
const SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
- TopoDS_Shape mainShape = meshDS->ShapeToMesh();
+ TopoDS_Shape mainShape = meshDS->ShapeToMesh();
// -----------------
// get global algos
// --------------------------------------------------------
// info on algos that will be ignored because of ones that
- // don't NeedDescretBoundary() attached to super-shapes,
+ // don't NeedDiscreteBoundary() attached to super-shapes,
// check that a conform mesh will be produced
// --------------------------------------------------------
for (dim = 3; dim > 0; dim--)
{
if (aGlobAlgoArr[ dim ] &&
- !aGlobAlgoArr[ dim ]->NeedDescretBoundary())
+ !aGlobAlgoArr[ dim ]->NeedDiscreteBoundary() /*&&
+ !aGlobAlgoArr[ dim ]->SupportSubmeshes()*/ )
{
aGlobIgnoAlgo = aGlobAlgoArr[ dim ];
break;
if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX)
break;
- if ( aCheckedSubs.insert( smToCheck ).second ) // not yet checked
- if (!checkMissing (this, theMesh, smToCheck, aTopAlgoDim,
- globalChecked, checkNoAlgo, aCheckedSubs, theErrors))
- {
- ret = false;
- if (smToCheck->GetAlgoState() == SMESH_subMesh::NO_ALGO )
- checkNoAlgo = false;
- }
+ if (!checkMissing (this, theMesh, smToCheck, aTopAlgoDim,
+ globalChecked, checkNoAlgo, aCheckedSubs, theErrors))
+ {
+ ret = false;
+ if (smToCheck->GetAlgoState() == SMESH_subMesh::NO_ALGO )
+ checkNoAlgo = false;
+ }
}
if ( !hasAlgo ) {
return aMesh.GetHypothesis( aMesh.GetMeshDS()->ShapeToMesh(), filter, false );
}
+//================================================================================
+/*!
+ * \brief Return paths to xml files of plugins
+ */
+//================================================================================
+
+std::vector< std::string > SMESH_Gen::GetPluginXMLPaths()
+{
+ // Get paths to xml files of plugins
+ vector< string > xmlPaths;
+ string sep;
+ if ( const char* meshersList = getenv("SMESH_MeshersList") )
+ {
+ string meshers = meshersList, plugin;
+ string::size_type from = 0, pos;
+ while ( from < meshers.size() )
+ {
+ // cut off plugin name
+ pos = meshers.find( ':', from );
+ if ( pos != string::npos )
+ plugin = meshers.substr( from, pos-from );
+ else
+ plugin = meshers.substr( from ), pos = meshers.size();
+ from = pos + 1;
+
+ // get PLUGIN_ROOT_DIR path
+ string rootDirVar, pluginSubDir = plugin;
+ if ( plugin == "StdMeshers" )
+ rootDirVar = "SMESH", pluginSubDir = "smesh";
+ else
+ for ( pos = 0; pos < plugin.size(); ++pos )
+ rootDirVar += toupper( plugin[pos] );
+ rootDirVar += "_ROOT_DIR";
+
+ const char* rootDir = getenv( rootDirVar.c_str() );
+ if ( !rootDir || strlen(rootDir) == 0 )
+ {
+ rootDirVar = plugin + "_ROOT_DIR"; // HexoticPLUGIN_ROOT_DIR
+ rootDir = getenv( rootDirVar.c_str() );
+ if ( !rootDir || strlen(rootDir) == 0 ) continue;
+ }
+
+ // get a separator from rootDir
+ for ( pos = strlen( rootDir )-1; pos >= 0 && sep.empty(); --pos )
+ if ( rootDir[pos] == '/' || rootDir[pos] == '\\' )
+ {
+ sep = rootDir[pos];
+ break;
+ }
+#ifdef WNT
+ if (sep.empty() ) sep = "\\";
+#else
+ if (sep.empty() ) sep = "/";
+#endif
+
+ // get a path to resource file
+ string xmlPath = rootDir;
+ if ( xmlPath[ xmlPath.size()-1 ] != sep[0] )
+ xmlPath += sep;
+ xmlPath += "share" + sep + "salome" + sep + "resources" + sep;
+ for ( pos = 0; pos < pluginSubDir.size(); ++pos )
+ xmlPath += tolower( pluginSubDir[pos] );
+ xmlPath += sep + plugin + ".xml";
+ bool fileOK;
+#ifdef WNT
+ fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES);
+#else
+ fileOK = (access(xmlPath.c_str(), F_OK) == 0);
+#endif
+ if ( fileOK )
+ xmlPaths.push_back( xmlPath );
+ }
+ }
+
+ return xmlPaths;
+}
+
+//=======================================================================
+namespace // Access to type of input and output of an algorithm
+//=======================================================================
+{
+ struct AlgoData
+ {
+ int _dim;
+ set<SMDSAbs_GeometryType> _inElemTypes; // acceptable types of input mesh element
+ set<SMDSAbs_GeometryType> _outElemTypes; // produced types of mesh elements
+
+ bool IsCompatible( const AlgoData& algo2 ) const
+ {
+ if ( _dim > algo2._dim ) return algo2.IsCompatible( *this );
+ // algo2 is of highter dimension
+ if ( _outElemTypes.empty() || algo2._inElemTypes.empty() )
+ return false;
+ bool compatible = true;
+ set<SMDSAbs_GeometryType>::const_iterator myOutType = _outElemTypes.begin();
+ for ( ; myOutType != _outElemTypes.end() && compatible; ++myOutType )
+ compatible = algo2._inElemTypes.count( *myOutType );
+ return compatible;
+ }
+ };
+
+ //================================================================================
+ /*!
+ * \brief Return AlgoData of the algorithm
+ */
+ //================================================================================
+
+ const AlgoData& getAlgoData( const SMESH_Algo* algo )
+ {
+ static map< string, AlgoData > theDataByName;
+ if ( theDataByName.empty() )
+ {
+ // Read Plugin.xml files
+ vector< string > xmlPaths = SMESH_Gen::GetPluginXMLPaths();
+ LDOMParser xmlParser;
+ for ( size_t iXML = 0; iXML < xmlPaths.size(); ++iXML )
+ {
+ bool error = xmlParser.parse( xmlPaths[iXML].c_str() );
+ if ( error )
+ {
+ TCollection_AsciiString data;
+ INFOS( xmlParser.GetError(data) );
+ continue;
+ }
+ // <algorithm type="Regular_1D"
+ // ...
+ // input="EDGE"
+ // output="QUAD,TRIA">
+ //
+ LDOM_Document xmlDoc = xmlParser.getDocument();
+ LDOM_NodeList algoNodeList = xmlDoc.getElementsByTagName( "algorithm" );
+ for ( int i = 0; i < algoNodeList.getLength(); ++i )
+ {
+ LDOM_Node algoNode = algoNodeList.item( i );
+ LDOM_Element& algoElem = (LDOM_Element&) algoNode;
+ TCollection_AsciiString algoType = algoElem.getAttribute("type");
+ TCollection_AsciiString input = algoElem.getAttribute("input");
+ TCollection_AsciiString output = algoElem.getAttribute("output");
+ TCollection_AsciiString dim = algoElem.getAttribute("dim");
+ if ( algoType.IsEmpty() ) continue;
+ AlgoData & data = theDataByName[ algoType.ToCString() ];
+ data._dim = dim.IntegerValue();
+ for ( int isInput = 0; isInput < 2; ++isInput )
+ {
+ TCollection_AsciiString& typeStr = isInput ? input : output;
+ set<SMDSAbs_GeometryType>& typeSet = isInput ? data._inElemTypes : data._outElemTypes;
+ int beg = 1, end;
+ while ( beg <= typeStr.Length() )
+ {
+ while ( beg < typeStr.Length() && !isalpha( typeStr.Value( beg ) ))
+ ++beg;
+ end = beg;
+ while ( end < typeStr.Length() && isalpha( typeStr.Value( end + 1 ) ))
+ ++end;
+ if ( end > beg )
+ {
+ TCollection_AsciiString typeName = typeStr.SubString( beg, end );
+ if ( typeName == "EDGE" ) typeSet.insert( SMDSGeom_EDGE );
+ else if ( typeName == "TRIA" ) typeSet.insert( SMDSGeom_TRIANGLE );
+ else if ( typeName == "QUAD" ) typeSet.insert( SMDSGeom_QUADRANGLE );
+ }
+ beg = end + 1;
+ }
+ }
+ }
+ }
+ }
+ return theDataByName[ algo->GetName() ];
+ }
+}
+
//=============================================================================
/*!
* Finds algo to mesh a shape. Optionally returns a shape the found algo is bound to
SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
filter.And( filter.IsApplicableTo( aShape ));
- return (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, assignedTo );
+ TopoDS_Shape assignedToShape;
+ SMESH_Algo* algo =
+ (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, &assignedToShape );
+
+ if ( algo &&
+ aShape.ShapeType() == TopAbs_FACE &&
+ !aShape.IsSame( assignedToShape ) &&
+ SMESH_MesherHelper::NbAncestors( aShape, aMesh, TopAbs_SOLID ) > 1 )
+ {
+ // Issue 0021559. If there is another 2D algo with different types of output
+ // elements that can be used to mesh aShape, and 3D algos on adjacent SOLIDs
+ // have different types of input elements, we choose a most appropriate 2D algo.
+
+ // try to find a concurrent 2D algo
+ filter.AndNot( filter.Is( algo ));
+ TopoDS_Shape assignedToShape2;
+ SMESH_Algo* algo2 =
+ (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, &assignedToShape2 );
+ if ( algo2 && // algo found
+ !assignedToShape2.IsSame( aMesh.GetShapeToMesh() ) && // algo is local
+ ( SMESH_MesherHelper::GetGroupType( assignedToShape2 ) == // algo of the same level
+ SMESH_MesherHelper::GetGroupType( assignedToShape )) &&
+ aMesh.IsOrderOK( aMesh.GetSubMesh( assignedToShape2 ), // no forced order
+ aMesh.GetSubMesh( assignedToShape )))
+ {
+ // get algos on the adjacent SOLIDs
+ filter.Init( filter.IsAlgo() ).And( filter.HasDim( 3 ));
+ vector< SMESH_Algo* > algos3D;
+ PShapeIteratorPtr solidIt = SMESH_MesherHelper::GetAncestors( aShape, aMesh,
+ TopAbs_SOLID );
+ while ( const TopoDS_Shape* solid = solidIt->next() )
+ if ( SMESH_Algo* algo3D = (SMESH_Algo*) aMesh.GetHypothesis( *solid, filter, true ))
+ {
+ algos3D.push_back( algo3D );
+ filter.AndNot( filter.HasName( algo3D->GetName() ));
+ }
+ // check compatibility of algos
+ if ( algos3D.size() > 1 )
+ {
+ const AlgoData& algoData = getAlgoData( algo );
+ const AlgoData& algoData2 = getAlgoData( algo2 );
+ const AlgoData& algoData3d0 = getAlgoData( algos3D[0] );
+ const AlgoData& algoData3d1 = getAlgoData( algos3D[1] );
+ if (( algoData2.IsCompatible( algoData3d0 ) &&
+ algoData2.IsCompatible( algoData3d1 ))
+ &&
+ !(algoData.IsCompatible( algoData3d0 ) &&
+ algoData.IsCompatible( algoData3d1 )))
+ algo = algo2;
+ }
+ }
+ }
+
+ if ( assignedTo && algo )
+ * assignedTo = assignedToShape;
+
+ return algo;
}
//=============================================================================