From 4039f267f1074db87ed73e03bd51ac77b66611e0 Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 2 Dec 2020 11:51:19 +0300 Subject: [PATCH] bos #20282 EDF 22320 - general compute fails 1) Compute sub-meshes with prescribed order before the rest ones 2) Save sub-mesh order not as ids but as entries, because ids of groups within SMESHDS_Mesh can change at study loading if some group is no longer used as a base of sub-mesh of group on geometry --- src/SMESH/SMESH_Mesh.cxx | 62 +++++++++++------ src/SMESH_I/SMESH_Gen_i.cxx | 74 ++++++++++++++++++++- src/SMESH_I/SMESH_Mesh_i.cxx | 2 +- src/StdMeshers/StdMeshers_Prism_3D.cxx | 2 +- src/StdMeshers/StdMeshers_Quadrangle_2D.cxx | 5 +- 5 files changed, 117 insertions(+), 28 deletions(-) diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index e71853f0f..e35195d33 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -2414,18 +2414,19 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape) bool SMESH_Mesh::SortByMeshOrder(std::vector& theListToSort) const { - if ( !_mySubMeshOrder.size() || theListToSort.size() < 2) + if ( _mySubMeshOrder.empty() || theListToSort.size() < 2 ) return true; - - bool res = false; - std::vector onlyOrderedList, smVec; - // collect all ordered submeshes in one list as pointers + + // collect all ordered sub-meshes in smVec as pointers // and get their positions within theListToSort + + std::vector smVec; typedef std::vector::iterator TPosInList; - std::map< int, TPosInList > sortedPos; + std::map< size_t, size_t > sortedPos; // index in theListToSort to order TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end(); TListOfListOfInt::const_iterator listIdsIt = _mySubMeshOrder.begin(); + bool needSort = false; for( ; listIdsIt != _mySubMeshOrder.end(); listIdsIt++) { const TListOfInt& listOfId = *listIdsIt; @@ -2452,27 +2453,46 @@ bool SMESH_Mesh::SortByMeshOrder(std::vector& theListToSort) con // find smVec items in theListToSort for ( size_t i = 0; i < smVec.size(); ++i ) { - TPosInList smPos = find( smBeg, smEnd, smVec[i] ); - if ( smPos != smEnd ) { - sortedPos[ std::distance( smBeg, smPos )] = smPos; - if ( sortedPos.size() > onlyOrderedList.size() ) - onlyOrderedList.push_back( smVec[i] ); + TPosInList smPos = find( smBeg, smEnd, smVec[i] ); // position in theListToSort + if ( smPos != smEnd ) + { + size_t posInList = std::distance( smBeg, smPos ); + size_t order = sortedPos.size(); + sortedPos.insert( std::make_pair( posInList, order )); + if ( posInList != order ) + needSort = true; } } } - if (onlyOrderedList.size() < 2) - return res; - res = true; + if ( ! needSort ) + return false; - std::vector::iterator onlyBIt = onlyOrderedList.begin(); - std::vector::iterator onlyEIt = onlyOrderedList.end(); + // set sm of sortedPos from theListToSort to front of orderedSM + // and the rest of theListToSort to orderedSM end - // iterate on ordered sub-meshes and insert them in detected positions - std::map< int, TPosInList >::iterator i_pos = sortedPos.begin(); - for ( ; onlyBIt != onlyEIt; ++onlyBIt, ++i_pos ) - *(i_pos->second) = *onlyBIt; + std::vector orderedSM; + orderedSM.reserve( theListToSort.size() ); + orderedSM.resize( sortedPos.size() ); - return res; + size_t iPrev = 0; + sortedPos.insert( std::make_pair( theListToSort.size(), sortedPos.size() )); + for ( const auto & pos_order : sortedPos ) + { + const size_t& posInList = pos_order.first; + const size_t& order = pos_order.second; + if ( order < sortedPos.size() - 1 ) + orderedSM[ order ] = theListToSort[ posInList ]; + + if ( iPrev < posInList ) + orderedSM.insert( orderedSM.end(), + theListToSort.begin() + iPrev, + theListToSort.begin() + posInList ); + iPrev = posInList + 1; + } + + theListToSort.swap( orderedSM ); + + return true; } //================================================================================ diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 701de05a8..28957d7fe 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -144,6 +144,11 @@ #include #include +#include +#include +#include +#include + using namespace std; using SMESH::TPythonDump; using SMESH::TVar; @@ -4790,7 +4795,8 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, // store submesh order if any const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder(); - if ( theOrderIds.size() ) { + const bool isNewOrederVersion = true; // old version saves ids, new one, entries + if ( !theOrderIds.empty() && !isNewOrederVersion ) { // keep old version for reference char order_list[ 30 ]; strcpy( order_list, "Mesh Order" ); // count number of submesh ids @@ -4821,6 +4827,38 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, // delete[] smIDs; } + if ( !theOrderIds.empty() && isNewOrederVersion ) + { + // convert ids to entries + std::list< std::list< std::string > > orderEntryLists; + for ( const TListOfInt& idList : theOrderIds ) + { + orderEntryLists.emplace_back(); + std::list< std::string > & entryList = orderEntryLists.back(); + for ( const int& id : idList ) + { + const TopoDS_Shape& shape = mySMESHDSMesh->IndexToShape( id ); + GEOM::GEOM_Object_var go = ShapeToGeomObject( shape ); + SALOMEDS::SObject_var so = ObjectToSObject( go ); + if ( !so->_is_nil() ) + { + CORBA::String_var entry = so->GetID(); + entryList.emplace_back( entry.in() ); + } + } + } + // convert orderEntryLists to string + std::ostringstream ostream; + boost::archive::text_oarchive( ostream ) << orderEntryLists; + std::string orderEntryString = ostream.str(); + + // write HDF group + aSize[ 0 ] = orderEntryString.size() + 1; + aDataset = new HDFdataset( "MeshOrder_new", aTopGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk((char*) orderEntryString.data() ); + aDataset->CloseOnDisk(); + } // groups root sub-branch SALOMEDS::SObject_wrap myGroupsBranch; @@ -5968,7 +6006,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, } // read Sub-Mesh ORDER if any - if ( aTopGroup->ExistInternalObject( "Mesh Order" )) { + if ( aTopGroup->ExistInternalObject( "Mesh Order" )) { // old version keeps ids aDataset = new HDFdataset( "Mesh Order", aTopGroup ); aDataset->OpenOnDisk(); size = aDataset->GetSize(); @@ -5986,6 +6024,37 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds ); delete [] smIDs; } + if ( aTopGroup->ExistInternalObject( "MeshOrder_new" )) // new version keeps entries + { + aDataset = new HDFdataset( "MeshOrder_new", aTopGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + std::string dataString; dataString.resize( size ); + aDataset->ReadFromDisk((char*) dataString.data() ); + aDataset->CloseOnDisk(); + + std::istringstream istream( dataString.data() ); + boost::archive::text_iarchive archive( istream ); + std::list< std::list< std::string > > orderEntryLists; + try { + archive >> orderEntryLists; + } + catch (...) {} + + TListOfListOfInt anOrderIds; + for ( const std::list< std::string >& entryList : orderEntryLists ) + { + anOrderIds.emplace_back(); + for ( const std::string & entry : entryList ) + { + GEOM::GEOM_Object_var go = GetGeomObjectByEntry( entry ); + TopoDS_Shape shape = GeomObjectToShape( go ); + if ( SMESH_subMesh* sm = myNewMeshImpl->GetImpl().GetSubMesh( shape )) + anOrderIds.back().emplace_back( sm->GetId() ); + } + } + myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds ); + } } // loop on meshes // update hyps needing full mesh data restored (issue 20918) @@ -6045,7 +6114,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, } } } - pd << ""; // prevent optimizing pd out // creation of tree nodes for all data objects in the study // to support tree representation customization and drag-n-drop: diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 8455f6b46..fe179f9a1 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -6493,7 +6493,7 @@ class SMESH_DimHyp TopTools_MapIteratorOfMapOfShape anItr( theToCheck ); for (; !isShared && anItr.More(); anItr.Next() ) { - const TopoDS_Shape aSubSh = anItr.Key(); + const TopoDS_Shape& aSubSh = anItr.Key(); // check for case when concurrent dimensions are same isShared = theToFind.Contains( aSubSh ); // check for sub-shape with concurrent dimension diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx index b35e76ae3..78ed7f603 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.cxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx @@ -984,7 +984,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh } else { - meshedFaces.push_back( prism.myBottom ); + suspectSourceFaces.push_back( prism.myBottom ); if ( prism.myAlgoSM && prism.myAlgoSM->GetAlgo() ) meshedFace2AlgoSM.Bind( prism.myBottom, prism.myAlgoSM ); } diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx index dca028078..8ecdfa8c5 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx @@ -204,7 +204,7 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis //============================================================================= /*! - * + * Compute the mesh on the given shape */ //============================================================================= @@ -1606,7 +1606,8 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace, //============================================================================= /*! - * + * Return FaceQuadStruct where sides ordered CCW, top and left sides + * reversed to be co-directed with bottom and right sides */ //============================================================================= -- 2.30.2