X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_Mesh.cxx;h=d4497448fd32b96f40963be8cfc1e179cf23d757;hp=50c79329676349c7da612d027644a3c3ebac9dec;hb=40793ae45e14edfdc3aa185537e495f2c905b3c7;hpb=e4737e85f0da6d3f90fd08f6be1c2825195fe16f diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 50c793296..d4497448f 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -31,8 +31,10 @@ #include "SMESH_Gen.hxx" #include "SMESH_Hypothesis.hxx" #include "SMESH_Group.hxx" +#include "SMESH_HypoFilter.hxx" #include "SMESHDS_Group.hxx" #include "SMESHDS_Script.hxx" +#include "SMESHDS_GroupOnGeom.hxx" #include "SMDS_MeshVolume.hxx" #include "utilities.h" @@ -46,11 +48,19 @@ #include "DriverUNV_R_SMDS_Mesh.h" #include "DriverSTL_R_SMDS_Mesh.h" +#include +#include +#include + #include -#include -#include #include +#include +#include #include +#include + +#include + #include "Utils_ExceptHandlers.hxx" #ifdef _DEBUG_ @@ -103,15 +113,49 @@ SMESH_Mesh::~SMESH_Mesh() */ //============================================================================= -void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape){ +void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape) +{ if(MYDEBUG) MESSAGE("SMESH_Mesh::ShapeToMesh"); - if (_isShapeToMesh) - throw - SALOME_Exception(LOCALIZED - ("a shape to mesh as already been defined")); + + if ( !_myMeshDS->ShapeToMesh().IsNull() && aShape.IsNull() ) + { + // removal of a shape to mesh, delete objects referring to sub-shapes: + // - sub-meshes + map ::iterator i_sm = _mapSubMesh.begin(); + for ( ; i_sm != _mapSubMesh.end(); ++i_sm ) + delete i_sm->second; + _mapSubMesh.clear(); + // - groups on geometry + map ::iterator i_gr = _mapGroup.begin(); + while ( i_gr != _mapGroup.end() ) { + if ( dynamic_cast( i_gr->second->GetGroupDS() )) { + _myMeshDS->RemoveGroup( i_gr->second->GetGroupDS() ); + delete i_gr->second; + _mapGroup.erase( i_gr++ ); + } + else + i_gr++; + } + _mapPropagationChains.Clear(); + } + else + { + if (_isShapeToMesh) + throw SALOME_Exception(LOCALIZED ("a shape to mesh has already been defined")); + } _isShapeToMesh = true; _myMeshDS->ShapeToMesh(aShape); - + + // fill _mapAncestors + _mapAncestors.Clear(); + int desType, ancType; + for ( desType = TopAbs_EDGE; desType > TopAbs_COMPOUND; desType-- ) + for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- ) + TopExp::MapShapesAndAncestors ( aShape, + (TopAbs_ShapeEnum) desType, + (TopAbs_ShapeEnum) ancType, + _mapAncestors ); + // NRI : 24/02/03 //EAP: 1/9/04 TopExp::MapShapes(aShape, _subShapes); USE the same map of _myMeshDS } @@ -125,7 +169,7 @@ int SMESH_Mesh::UNVToMesh(const char* theFileName) { if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<GetSubMeshDS(); - if ( subMeshDS && subMeshDS->IsComplexSubmesh() ) + if ( subMeshDS && subMeshDS->IsComplexSubmesh() ) // group of sub-shapes and maybe of not sub- { + MESSAGE("AddHypothesis() to complex submesh"); // return the worst but not fatal state of all group memebers SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret; aBestRet = SMESH_Hypothesis::HYP_BAD_DIM; aWorstNotFatal = SMESH_Hypothesis::HYP_OK; for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next()) { + if ( !GetMeshDS()->ShapeToIndex( itS.Value() )) + continue; // not sub-shape ret = AddHypothesis( itS.Value(), anHypId ); if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal ) aWorstNotFatal = ret; @@ -254,8 +301,7 @@ SMESH_Hypothesis::Hypothesis_Status } SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId]; - if(MYDEBUG) SCRUTE( anHyp->GetName() ); - int event; + MESSAGE( "SMESH_Mesh::AddHypothesis " << anHyp->GetName() ); bool isGlobalHyp = IsMainShape( aSubShape ); @@ -272,6 +318,7 @@ SMESH_Hypothesis::Hypothesis_Status // shape + int event; if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO) event = SMESH_subMesh::ADD_HYP; else @@ -290,10 +337,26 @@ SMESH_Hypothesis::Hypothesis_Status subMesh->SubMeshesAlgoStateEngine(event, anHyp); if (ret2 > ret) ret = ret2; + + // check concurent hypotheses on ansestors + if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp ) + { + const map < int, SMESH_subMesh * >& smMap = subMesh->DependsOn(); + map < int, SMESH_subMesh * >::const_iterator smIt = smMap.begin(); + for ( ; smIt != smMap.end(); smIt++ ) { + if ( smIt->second->IsApplicableHypotesis( anHyp )) { + ret2 = smIt->second->CheckConcurentHypothesis( anHyp->GetType() ); + if (ret2 > ret) { + ret = ret2; + break; + } + } + } + } } - subMesh->DumpAlgoState(true); - if(MYDEBUG) SCRUTE(ret); + if(MYDEBUG) subMesh->DumpAlgoState(true); + SCRUTE(ret); return ret; } @@ -320,6 +383,8 @@ SMESH_Hypothesis::Hypothesis_Status aWorstNotFatal = SMESH_Hypothesis::HYP_OK; for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next()) { + if ( !GetMeshDS()->ShapeToIndex( itS.Value() )) + continue; // not sub-shape ret = RemoveHypothesis( itS.Value(), anHypId ); if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal ) aWorstNotFatal = ret; @@ -347,22 +412,44 @@ SMESH_Hypothesis::Hypothesis_Status else event = SMESH_subMesh::REMOVE_ALGO; SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp); - + + // there may appear concurrent hyps that were covered by the removed hyp + if (ret < SMESH_Hypothesis::HYP_CONCURENT && + subMesh->IsApplicableHypotesis( anHyp ) && + subMesh->CheckConcurentHypothesis( anHyp->GetType() ) != SMESH_Hypothesis::HYP_OK) + ret = SMESH_Hypothesis::HYP_CONCURENT; + // subShapes if (!SMESH_Hypothesis::IsStatusFatal(ret) && !subMesh->IsApplicableHypotesis( anHyp )) // is removed from father + { + if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO) + event = SMESH_subMesh::REMOVE_FATHER_HYP; + else + event = SMESH_subMesh::REMOVE_FATHER_ALGO; + SMESH_Hypothesis::Hypothesis_Status ret2 = + subMesh->SubMeshesAlgoStateEngine(event, anHyp); + if (ret2 > ret) // more severe + ret = ret2; + + // check concurent hypotheses on ansestors + if (ret < SMESH_Hypothesis::HYP_CONCURENT && !IsMainShape( aSubShape ) ) { - if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO) - event = SMESH_subMesh::REMOVE_FATHER_HYP; - else - event = SMESH_subMesh::REMOVE_FATHER_ALGO; - SMESH_Hypothesis::Hypothesis_Status ret2 = - subMesh->SubMeshesAlgoStateEngine(event, anHyp); - if (ret2 > ret) // more severe - ret = ret2; + const map < int, SMESH_subMesh * >& smMap = subMesh->DependsOn(); + map < int, SMESH_subMesh * >::const_iterator smIt = smMap.begin(); + for ( ; smIt != smMap.end(); smIt++ ) { + if ( smIt->second->IsApplicableHypotesis( anHyp )) { + ret2 = smIt->second->CheckConcurentHypothesis( anHyp->GetType() ); + if (ret2 > ret) { + ret = ret2; + break; + } + } + } } + } - subMesh->DumpAlgoState(true); + if(MYDEBUG) subMesh->DumpAlgoState(true); if(MYDEBUG) SCRUTE(ret); return ret; } @@ -392,6 +479,87 @@ SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const return _myMeshDS->GetHypothesis(aSubShape); } +//======================================================================= +//function : GetHypothesis +//purpose : +//======================================================================= + +const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape & aSubShape, + const SMESH_HypoFilter& aFilter, + const bool andAncestors) const +{ + { + const list& hypList = _myMeshDS->GetHypothesis(aSubShape); + list::const_iterator hyp = hypList.begin(); + for ( ; hyp != hypList.end(); hyp++ ) { + const SMESH_Hypothesis * h = static_cast( *hyp ); + if ( aFilter.IsOk( h, aSubShape)) + return h; + } + } + if ( andAncestors ) + { + TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape )); + for (; it.More(); it.Next() ) + { + const list& hypList = _myMeshDS->GetHypothesis(it.Value()); + list::const_iterator hyp = hypList.begin(); + for ( ; hyp != hypList.end(); hyp++ ) { + const SMESH_Hypothesis * h = static_cast( *hyp ); + if (aFilter.IsOk( h, it.Value() )) + return h; + } + } + } + return 0; +} + +//======================================================================= +//function : GetHypotheses +//purpose : +//======================================================================= + +bool SMESH_Mesh::GetHypotheses(const TopoDS_Shape & aSubShape, + const SMESH_HypoFilter& aFilter, + list & aHypList, + const bool andAncestors) const +{ + int nbHyp = 0; + { + const list& hypList = _myMeshDS->GetHypothesis(aSubShape); + list::const_iterator hyp = hypList.begin(); + for ( ; hyp != hypList.end(); hyp++ ) + if ( aFilter.IsOk (static_cast( *hyp ), aSubShape)) { + aHypList.push_back( *hyp ); + nbHyp++; + } + } + // get hypos from shape of one type only: if any hypo is found on edge, do + // not look up on faces + if ( !nbHyp && andAncestors ) + { + TopTools_MapOfShape map; + TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape )); + int shapeType = it.More() ? it.Value().ShapeType() : TopAbs_SHAPE; + for (; it.More(); it.Next() ) + { + if ( nbHyp && shapeType != it.Value().ShapeType() ) + break; + shapeType = it.Value().ShapeType(); + if ( !map.Add( it.Value() )) + continue; + const list& hypList = _myMeshDS->GetHypothesis(it.Value()); + list::const_iterator hyp = hypList.begin(); + for ( ; hyp != hypList.end(); hyp++ ) + if (aFilter.IsOk( static_cast( *hyp ), it.Value() )) { + aHypList.push_back( *hyp ); + nbHyp++; + } + } + } + return nbHyp; +} + //============================================================================= /*! * @@ -497,6 +665,24 @@ throw(SALOME_Exception) return aSubMesh; } +//============================================================================= +/*! + * Get the SMESH_subMesh object implementation. Dont create it, return null + * if it does not exist. + */ +//============================================================================= + +SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID) +throw(SALOME_Exception) +{ + Unexpect aCatch(SalomeException); + + map ::iterator i_sm = _mapSubMesh.find(aShapeID); + if (i_sm == _mapSubMesh.end()) + return NULL; + return i_sm->second; +} + //======================================================================= //function : IsUsedHypothesis //purpose : Return True if anHyp is used to mesh aSubShape @@ -505,10 +691,10 @@ throw(SALOME_Exception) bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp, const TopoDS_Shape & aSubShape) { + SMESH_Hypothesis* hyp = static_cast(anHyp); // check if anHyp is applicable to aSubShape SMESH_subMesh * subMesh = GetSubMeshContaining( aSubShape ); - if (!subMesh || - !subMesh->IsApplicableHypotesis(static_cast(anHyp))) + if ( !subMesh || !subMesh->IsApplicableHypotesis( hyp )) return false; SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape); @@ -523,37 +709,12 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp, // look trough hypotheses used by algo const list &usedHyps = algo->GetUsedHypothesis(*this, aSubShape); - list ::const_iterator itl; - for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++) - if (anHyp == (*itl)) - return true; + return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() ); } - else - { - // look through all assigned hypotheses - { - const list &usedHyps = - _myMeshDS->GetHypothesis( aSubShape ); - list ::const_iterator itl; - for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++) - if (anHyp == (*itl)) - return true; - } - // on ancestors - TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape )); - for (; it.More(); it.Next()) - { - const list &usedHyps = - _myMeshDS->GetHypothesis( aSubShape ); - list ::const_iterator itl; - for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++) - if (anHyp == (*itl)) - return true; - } - } - - return false; + // look through all assigned hypotheses + SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp )); + return GetHypothesis( aSubShape, filter, true ); } @@ -586,11 +747,15 @@ throw(SALOME_Exception) */ //============================================================================= -void SMESH_Mesh::ExportMED(const char *file, const char* theMeshName, bool theAutoGroups) throw(SALOME_Exception) +void SMESH_Mesh::ExportMED(const char *file, + const char* theMeshName, + bool theAutoGroups, + int theVersion) + throw(SALOME_Exception) { Unexpect aCatch(SalomeException); DriverMED_W_SMESHDS_Mesh myWriter; - myWriter.SetFile ( file ); + myWriter.SetFile ( file, MED::EVersion(theVersion) ); myWriter.SetMesh ( _myMeshDS ); if ( !theMeshName ) myWriter.SetMeshId ( _idDoc ); @@ -691,7 +856,12 @@ int SMESH_Mesh::NbTriangles() throw(SALOME_Exception) int Nb = 0; SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator(); - while(itFaces->more()) if(itFaces->next()->NbNodes()==3) Nb++; + //while(itFaces->more()) if(itFaces->next()->NbNodes()==3) Nb++; + const SMDS_MeshFace * curFace; + while (itFaces->more()) { + curFace = itFaces->next(); + if (!curFace->IsPoly() && curFace->NbNodes() == 3) Nb++; + } return Nb; } @@ -704,7 +874,25 @@ int SMESH_Mesh::NbQuadrangles() throw(SALOME_Exception) int Nb = 0; SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator(); - while(itFaces->more()) if(itFaces->next()->NbNodes()==4) Nb++; + //while(itFaces->more()) if(itFaces->next()->NbNodes()==4) Nb++; + const SMDS_MeshFace * curFace; + while (itFaces->more()) { + curFace = itFaces->next(); + if (!curFace->IsPoly() && curFace->NbNodes() == 4) Nb++; + } + return Nb; +} + +/////////////////////////////////////////////////////////////////////////////// +/// Return the number of polygonal faces in the mesh. This method run in O(n) +/////////////////////////////////////////////////////////////////////////////// +int SMESH_Mesh::NbPolygons() throw(SALOME_Exception) +{ + Unexpect aCatch(SalomeException); + int Nb = 0; + SMDS_FaceIteratorPtr itFaces = _myMeshDS->facesIterator(); + while (itFaces->more()) + if (itFaces->next()->IsPoly()) Nb++; return Nb; } @@ -724,7 +912,12 @@ int SMESH_Mesh::NbTetras() throw(SALOME_Exception) Unexpect aCatch(SalomeException); int Nb = 0; SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator(); - while(itVolumes->more()) if(itVolumes->next()->NbNodes()==4) Nb++; + //while(itVolumes->more()) if(itVolumes->next()->NbNodes()==4) Nb++; + const SMDS_MeshVolume * curVolume; + while (itVolumes->more()) { + curVolume = itVolumes->next(); + if (!curVolume->IsPoly() && curVolume->NbNodes() == 4) Nb++; + } return Nb; } @@ -733,7 +926,12 @@ int SMESH_Mesh::NbHexas() throw(SALOME_Exception) Unexpect aCatch(SalomeException); int Nb = 0; SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator(); - while(itVolumes->more()) if(itVolumes->next()->NbNodes()==8) Nb++; + //while(itVolumes->more()) if(itVolumes->next()->NbNodes()==8) Nb++; + const SMDS_MeshVolume * curVolume; + while (itVolumes->more()) { + curVolume = itVolumes->next(); + if (!curVolume->IsPoly() && curVolume->NbNodes() == 8) Nb++; + } return Nb; } @@ -742,7 +940,12 @@ int SMESH_Mesh::NbPyramids() throw(SALOME_Exception) Unexpect aCatch(SalomeException); int Nb = 0; SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator(); - while(itVolumes->more()) if(itVolumes->next()->NbNodes()==5) Nb++; + //while(itVolumes->more()) if(itVolumes->next()->NbNodes()==5) Nb++; + const SMDS_MeshVolume * curVolume; + while (itVolumes->more()) { + curVolume = itVolumes->next(); + if (!curVolume->IsPoly() && curVolume->NbNodes() == 5) Nb++; + } return Nb; } @@ -751,7 +954,22 @@ int SMESH_Mesh::NbPrisms() throw(SALOME_Exception) Unexpect aCatch(SalomeException); int Nb = 0; SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator(); - while(itVolumes->more()) if(itVolumes->next()->NbNodes()==6) Nb++; + //while(itVolumes->more()) if(itVolumes->next()->NbNodes()==6) Nb++; + const SMDS_MeshVolume * curVolume; + while (itVolumes->more()) { + curVolume = itVolumes->next(); + if (!curVolume->IsPoly() && curVolume->NbNodes() == 6) Nb++; + } + return Nb; +} + +int SMESH_Mesh::NbPolyhedrons() throw(SALOME_Exception) +{ + Unexpect aCatch(SalomeException); + int Nb = 0; + SMDS_VolumeIteratorPtr itVolumes = _myMeshDS->volumesIterator(); + while (itVolumes->more()) + if (itVolumes->next()->IsPoly()) Nb++; return Nb; } @@ -775,18 +993,8 @@ bool SMESH_Mesh::IsNotConformAllowed() const { if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed"); - const list& listHyp = - _myMeshDS->GetHypothesis( _myMeshDS->ShapeToMesh() ); - list::const_iterator it=listHyp.begin(); - while (it!=listHyp.end()) - { - const SMESHDS_Hypothesis *aHyp = *it; - string hypName = aHyp->GetName(); - if ( hypName == "NotConformAllowed" ) - return true; - it++; - } - return false; + SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" )); + return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false ); } //======================================================================= @@ -864,26 +1072,287 @@ void SMESH_Mesh::RemoveGroup (const int theGroupID) delete _mapGroup[theGroupID]; } +//============================================================================= +/*! + * IsLocal1DHypothesis + * Returns a local 1D hypothesis used for theEdge + */ +//============================================================================= +const SMESH_Hypothesis* SMESH_Mesh::IsLocal1DHypothesis (const TopoDS_Shape& theEdge) +{ + SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 )); + hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( GetMeshDS()->ShapeToMesh() )); + + return GetHypothesis( theEdge, hypo, true ); +} + +//============================================================================= +/*! + * IsPropagationHypothesis + */ +//============================================================================= +bool SMESH_Mesh::IsPropagationHypothesis (const TopoDS_Shape& theEdge) +{ + return _mapPropagationChains.Contains(theEdge); +} + +//============================================================================= +/*! + * IsPropagatedHypothesis + */ +//============================================================================= +bool SMESH_Mesh::IsPropagatedHypothesis (const TopoDS_Shape& theEdge, + TopoDS_Shape& theMainEdge) +{ + int nbChains = _mapPropagationChains.Extent(); + for (int i = 1; i <= nbChains; i++) { + //const TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i); + const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i); + if (aChain.Contains(theEdge)) { + theMainEdge = _mapPropagationChains.FindKey(i); + return true; + } + } + + return false; +} +//============================================================================= +/*! + * IsReversedInChain + */ +//============================================================================= + +bool SMESH_Mesh::IsReversedInChain (const TopoDS_Shape& theEdge, + const TopoDS_Shape& theMainEdge) +{ + if ( !theMainEdge.IsNull() && !theEdge.IsNull() && + _mapPropagationChains.Contains( theMainEdge )) + { + const SMESH_IndexedMapOfShape& aChain = + _mapPropagationChains.FindFromKey( theMainEdge ); + int index = aChain.FindIndex( theEdge ); + if ( index ) + return aChain(index).Orientation() == TopAbs_REVERSED; + } + return false; +} + +//============================================================================= +/*! + * CleanMeshOnPropagationChain + */ +//============================================================================= +void SMESH_Mesh::CleanMeshOnPropagationChain (const TopoDS_Shape& theMainEdge) +{ + const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromKey(theMainEdge); + int i, nbEdges = aChain.Extent(); + for (i = 1; i <= nbEdges; i++) { + TopoDS_Shape anEdge = aChain.FindKey(i); + SMESH_subMesh *subMesh = GetSubMesh(anEdge); + SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS(); + if (subMeshDS && subMeshDS->NbElements() > 0) { + subMesh->ComputeStateEngine(SMESH_subMesh::CLEANDEP); + } + } +} + +//============================================================================= +/*! + * RebuildPropagationChains + * Rebuild all existing propagation chains. + * Have to be used, if 1D hypothesis have been assigned/removed to/from any edge + */ +//============================================================================= +bool SMESH_Mesh::RebuildPropagationChains() +{ + bool ret = true; + + // Clean all chains, because they can be not up-to-date + int i, nbChains = _mapPropagationChains.Extent(); + for (i = 1; i <= nbChains; i++) { + TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i); + CleanMeshOnPropagationChain(aMainEdge); + _mapPropagationChains.ChangeFromIndex(i).Clear(); + } + + // Build all chains + for (i = 1; i <= nbChains; i++) { + TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i); + if (!BuildPropagationChain(aMainEdge)) + ret = false; + CleanMeshOnPropagationChain(aMainEdge); + } + + return ret; +} + +//============================================================================= +/*! + * RemovePropagationChain + * Have to be used, if Propagation hypothesis is removed from + */ +//============================================================================= +bool SMESH_Mesh::RemovePropagationChain (const TopoDS_Shape& theMainEdge) +{ + if (!_mapPropagationChains.Contains(theMainEdge)) + return false; + + // Clean mesh elements and nodes, built on the chain + CleanMeshOnPropagationChain(theMainEdge); + + // Clean the chain + _mapPropagationChains.ChangeFromKey(theMainEdge).Clear(); + + // Remove the chain from the map + int i = _mapPropagationChains.FindIndex(theMainEdge); + if ( i == _mapPropagationChains.Extent() ) + _mapPropagationChains.RemoveLast(); + else { + TopoDS_Vertex anEmptyShape; + BRep_Builder BB; + BB.MakeVertex(anEmptyShape, gp_Pnt(0,0,0), 0.1); + SMESH_IndexedMapOfShape anEmptyMap; + _mapPropagationChains.Substitute(i, anEmptyShape, anEmptyMap); + } + + return true; +} + +//============================================================================= +/*! + * BuildPropagationChain + */ +//============================================================================= +bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge) +{ + if (theMainEdge.ShapeType() != TopAbs_EDGE) return true; + + // Add new chain, if there is no + if (!_mapPropagationChains.Contains(theMainEdge)) { + SMESH_IndexedMapOfShape aNewChain; + _mapPropagationChains.Add(theMainEdge, aNewChain); + } + + // Check presence of 1D hypothesis to be propagated + const SMESH_Hypothesis* aMainHyp = IsLocal1DHypothesis(theMainEdge); + if (!aMainHyp) { + MESSAGE("Warning: There is no 1D hypothesis to propagate. Please, assign."); + return true; + } + + // Edges, on which the 1D hypothesis will be propagated from + SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.ChangeFromKey(theMainEdge); + if (aChain.Extent() > 0) { + CleanMeshOnPropagationChain(theMainEdge); + aChain.Clear(); + } + + // At first put in the chain + aChain.Add(theMainEdge); + + // List of edges, added to chain on the previous cycle pass + TopTools_ListOfShape listPrevEdges; + listPrevEdges.Append(theMainEdge.Oriented( TopAbs_FORWARD )); + +// 5____4____3____4____5____6 +// | | | | | | +// | | | | | | +// 4____3____2____3____4____5 +// | | | | | | Number in the each knot of +// | | | | | | grid indicates cycle pass, +// 3____2____1____2____3____4 on which corresponding edge +// | | | | | | (perpendicular to the plane +// | | | | | | of view) will be found. +// 2____1____0____1____2____3 +// | | | | | | +// | | | | | | +// 3____2____1____2____3____4 + + // Collect all edges pass by pass + while (listPrevEdges.Extent() > 0) { + // List of edges, added to chain on this cycle pass + TopTools_ListOfShape listCurEdges; + + // Find the next portion of edges + TopTools_ListIteratorOfListOfShape itE (listPrevEdges); + for (; itE.More(); itE.Next()) { + TopoDS_Shape anE = itE.Value(); + + // Iterate on faces, having edge + TopTools_ListIteratorOfListOfShape itA (GetAncestors(anE)); + for (; itA.More(); itA.Next()) { + TopoDS_Shape aW = itA.Value(); + + // There are objects of different type among the ancestors of edge + if (aW.ShapeType() == TopAbs_WIRE) { + TopoDS_Shape anOppE; + + BRepTools_WireExplorer aWE (TopoDS::Wire(aW)); + Standard_Integer nb = 1, found = 0; + TopTools_Array1OfShape anEdges (1,4); + for (; aWE.More(); aWE.Next(), nb++) { + if (nb > 4) { + found = 0; + break; + } + anEdges(nb) = aWE.Current(); + if (!_mapAncestors.Contains(anEdges(nb))) { + MESSAGE("WIRE EXPLORER HAVE GIVEN AN INVALID EDGE !!!"); + break; + } + if (anEdges(nb).IsSame(anE)) found = nb; + } + + if (nb == 5 && found > 0) { + // Quadrangle face found, get an opposite edge + Standard_Integer opp = found + 2; + if (opp > 4) opp -= 4; + anOppE = anEdges(opp); + + // add anOppE to aChain if ... + if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain + if (!IsLocal1DHypothesis(anOppE)) { // ... no other 1d hyp on anOppE + TopoDS_Shape aMainEdgeForOppEdge; // ... no other hyp is propagated to anOppE + if (!IsPropagatedHypothesis(anOppE, aMainEdgeForOppEdge)) + { + // Add found edge to the chain oriented so that to + // have it co-directed with a forward MainEdge + TopAbs_Orientation ori = anE.Orientation(); + if ( anEdges(opp).Orientation() == anEdges(found).Orientation() ) + ori = TopAbs::Reverse( ori ); + anOppE.Orientation( ori ); + aChain.Add(anOppE); + listCurEdges.Append(anOppE); + } + else { + // Collision! + MESSAGE("Error: Collision between propagated hypotheses"); + CleanMeshOnPropagationChain(theMainEdge); + aChain.Clear(); + return ( aMainHyp == IsLocal1DHypothesis(aMainEdgeForOppEdge) ); + } + } + } + } // if (nb == 5 && found > 0) + } // if (aF.ShapeType() == TopAbs_WIRE) + } // for (; itF.More(); itF.Next()) + } // for (; itE.More(); itE.Next()) + + listPrevEdges = listCurEdges; + } // while (listPrevEdges.Extent() > 0) + + CleanMeshOnPropagationChain(theMainEdge); + return true; +} + //======================================================================= //function : GetAncestors //purpose : return list of ancestors of theSubShape in the order // that lower dimention shapes come first. //======================================================================= -const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) +const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const { - if ( _mapAncestors.IsEmpty() ) - { - // fill _mapAncestors - int desType, ancType; - for ( desType = TopAbs_EDGE; desType > TopAbs_COMPOUND; desType-- ) - for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- ) - TopExp::MapShapesAndAncestors (_myMeshDS->ShapeToMesh(), - (TopAbs_ShapeEnum) desType, - (TopAbs_ShapeEnum) ancType, - _mapAncestors ); - } - if ( _mapAncestors.Contains( theS ) ) return _mapAncestors.FindFromKey( theS ); @@ -949,3 +1418,12 @@ ostream& SMESH_Mesh::Dump(ostream& save) save << "===========================================================================" << endl; return save; } + +//======================================================================= +//function : GetElementType +//purpose : Returns type of mesh element with certain id +//======================================================================= +SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem ) +{ + return _myMeshDS->GetElementType( id, iselem ); +}