1 // Copyright (C) 2007-2022 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, or (at your option) any later version.
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 : SMESH_Mesh.cxx
24 // Author : Paul RASCLE, EDF
27 #include "SMESH_Mesh.hxx"
28 #include "SMESH_MesherHelper.hxx"
29 #include "SMDS_MeshVolume.hxx"
30 #include "SMDS_SetIterator.hxx"
31 #include "SMESHDS_Document.hxx"
32 #include "SMESHDS_Group.hxx"
33 #include "SMESHDS_GroupOnGeom.hxx"
34 #include "SMESHDS_Script.hxx"
35 #include "SMESHDS_TSubMeshHolder.hxx"
36 #include "SMESH_Gen.hxx"
37 #include "SMESH_Group.hxx"
38 #include "SMESH_HypoFilter.hxx"
39 #include "SMESH_Hypothesis.hxx"
40 #include "SMESH_subMesh.hxx"
42 #include "utilities.h"
44 #include "DriverDAT_W_SMDS_Mesh.h"
45 #include "DriverGMF_Read.hxx"
46 #include "DriverGMF_Write.hxx"
47 #include "DriverMED_R_SMESHDS_Mesh.h"
48 #include "DriverMED_W_SMESHDS_Mesh.h"
49 #include "DriverSTL_R_SMDS_Mesh.h"
50 #include "DriverSTL_W_SMDS_Mesh.h"
51 #include "DriverUNV_R_SMDS_Mesh.h"
52 #include "DriverUNV_W_SMDS_Mesh.h"
54 #include "DriverCGNS_Read.hxx"
55 #include "DriverCGNS_Write.hxx"
58 #include <GEOMUtils.hxx>
60 #undef _Precision_HeaderFile
61 #include <BRepBndLib.hxx>
62 #include <BRepPrimAPI_MakeBox.hxx>
63 #include <Bnd_Box.hxx>
64 #include <TColStd_MapOfInteger.hxx>
66 #include <TopExp_Explorer.hxx>
67 #include <TopTools_ListIteratorOfListOfShape.hxx>
68 #include <TopTools_ListOfShape.hxx>
69 #include <TopTools_MapOfShape.hxx>
70 #include <TopoDS_Iterator.hxx>
72 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
74 #include "Utils_ExceptHandlers.hxx"
77 #include <boost/thread/thread.hpp>
78 #include <boost/bind.hpp>
83 // maximum stored group name length in MED file
84 #define MAX_MED_GROUP_NAME_LENGTH 80
86 #define cSMESH_Hyp(h) static_cast<const SMESH_Hypothesis*>(h)
88 typedef SMESH_HypoFilter THypType;
90 class SMESH_Mesh::SubMeshHolder : public SMESHDS_TSubMeshHolder< SMESH_subMesh >
94 //=============================================================================
98 //=============================================================================
100 SMESH_Mesh::SMESH_Mesh(int theLocalId,
102 bool theIsEmbeddedMode,
103 SMESHDS_Document* theDocument):
104 _groupId( 0 ), _nbSubShapes( 0 )
106 MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)");
109 _document = theDocument;
110 _meshDS = theDocument->NewMesh(theIsEmbeddedMode,theLocalId);
111 _isShapeToMesh = false;
112 _isAutoColor = false;
114 _shapeDiagonal = 0.0;
116 _meshDS->ShapeToMesh( PseudoShape() );
117 _subMeshHolder = new SubMeshHolder;
119 // assure unique persistent ID
120 if ( _document->NbMeshes() > 1 )
123 for ( _document->InitMeshesIterator(); _document->MoreMesh(); )
125 SMESHDS_Mesh * meshDS =_document->NextMesh();
126 if ( meshDS != _meshDS )
127 ids.insert( meshDS->GetPersistentId() );
130 if ( ids.count( _meshDS->GetPersistentId() ))
132 int uniqueID = *ids.rbegin() + 1;
133 _meshDS->SetPersistentId( uniqueID );
138 //================================================================================
140 * \brief Constructor of SMESH_Mesh being a base of some descendant class
142 //================================================================================
144 SMESH_Mesh::SMESH_Mesh():
148 _isShapeToMesh( false ),
152 _isAutoColor( false ),
153 _isModified( false ),
154 _shapeDiagonal( 0.0 ),
157 _subMeshHolder = new SubMeshHolder;
163 void deleteMeshDS(SMESHDS_Mesh* meshDS)
165 //cout << "deleteMeshDS( " << meshDS << endl;
169 static void* deleteMeshDS(void* meshDS)
171 //cout << "deleteMeshDS( " << meshDS << endl;
172 SMESHDS_Mesh* m = (SMESHDS_Mesh*)meshDS;
181 //=============================================================================
185 //=============================================================================
187 SMESH_Mesh::~SMESH_Mesh()
189 MESSAGE("SMESH_Mesh::~SMESH_Mesh");
191 if ( _document ) // avoid destructing _meshDS from ~SMESH_Gen()
192 _document->RemoveMesh( _id );
195 // remove self from studyContext
198 StudyContextStruct * studyContext = _gen->GetStudyContext();
199 studyContext->mapMesh.erase( _id );
202 _meshDS->ClearMesh();
204 // issue 0020340: EDF 1022 SMESH : Crash with FindNodeClosestTo in a second new study
205 // Notify event listeners at least that something happens
206 if ( SMESH_subMesh * sm = GetSubMeshContaining(1))
207 sm->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED );
210 std::map < int, SMESH_Group * >::iterator itg;
211 for (itg = _mapGroup.begin(); itg != _mapGroup.end(); itg++) {
212 SMESH_Group *aGroup = (*itg).second;
218 delete _subMeshHolder;
220 if ( _callUp) delete _callUp;
224 // delete _meshDS, in a thread in order not to block closing a study with large meshes
226 boost::thread aThread(boost::bind( & deleteMeshDS, _meshDS ));
229 int result=pthread_create(&thread, NULL, deleteMeshDS, (void*)_meshDS);
234 //================================================================================
236 * \brief Return true if a mesh with given id exists
238 //================================================================================
240 bool SMESH_Mesh::MeshExists( int meshId ) const
242 return _document ? bool( _document->GetMesh( meshId )) : false;
245 //================================================================================
247 * \brief Return a mesh by id
249 //================================================================================
251 SMESH_Mesh* SMESH_Mesh::FindMesh( int meshId ) const
254 return (SMESH_Mesh*) this;
256 if ( StudyContextStruct *aStudyContext = _gen->GetStudyContext())
258 std::map < int, SMESH_Mesh * >::iterator i_m = aStudyContext->mapMesh.find( meshId );
259 if ( i_m != aStudyContext->mapMesh.end() )
265 //=============================================================================
267 * \brief Set geometry to be meshed
269 //=============================================================================
271 void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
273 MESSAGE("SMESH_Mesh::ShapeToMesh");
275 if ( !aShape.IsNull() && _isShapeToMesh ) {
276 if ( aShape.ShapeType() != TopAbs_COMPOUND && // group contents is allowed to change
277 _meshDS->ShapeToMesh().ShapeType() != TopAbs_COMPOUND )
278 throw SALOME_Exception(LOCALIZED ("a shape to mesh has already been defined"));
280 // clear current data
281 if ( !_meshDS->ShapeToMesh().IsNull() )
283 // removal of a shape to mesh, delete objects referring to sub-shapes:
285 _subMeshHolder->DeleteAll();
286 // - groups on geometry
287 std::map <int, SMESH_Group *>::iterator i_gr = _mapGroup.begin();
288 while ( i_gr != _mapGroup.end() ) {
289 if ( dynamic_cast<SMESHDS_GroupOnGeom*>( i_gr->second->GetGroupDS() )) {
290 _meshDS->RemoveGroup( i_gr->second->GetGroupDS() );
292 _mapGroup.erase( i_gr++ );
297 _mapAncestors.Clear();
300 TopoDS_Shape aNullShape;
301 _meshDS->ShapeToMesh( aNullShape );
303 _shapeDiagonal = 0.0;
306 // set a new geometry
307 if ( !aShape.IsNull() )
309 _meshDS->ShapeToMesh(aShape);
310 _isShapeToMesh = true;
311 _nbSubShapes = _meshDS->MaxShapeIndex();
313 // fill map of ancestors
314 fillAncestorsMap(aShape);
318 _isShapeToMesh = false;
319 _shapeDiagonal = 0.0;
320 _meshDS->ShapeToMesh( PseudoShape() );
325 //=======================================================================
327 * \brief Return geometry to be meshed. (It may be a PseudoShape()!)
329 //=======================================================================
331 TopoDS_Shape SMESH_Mesh::GetShapeToMesh() const
333 return _meshDS->ShapeToMesh();
336 //=======================================================================
338 * \brief Return a solid which is returned by GetShapeToMesh() if
339 * a real geometry to be meshed was not set
341 //=======================================================================
343 const TopoDS_Solid& SMESH_Mesh::PseudoShape()
345 static TopoDS_Solid aSolid;
346 if ( aSolid.IsNull() )
348 aSolid = BRepPrimAPI_MakeBox(1,1,1);
353 //=======================================================================
355 * \brief Return diagonal size of bounding box of a shape
357 //=======================================================================
359 double SMESH_Mesh::GetShapeDiagonalSize(const TopoDS_Shape & aShape)
361 if ( !aShape.IsNull() ) {
363 // avoid too long waiting on large shapes. PreciseBoundingBox() was added
364 // to assure same result which else depends on presence of triangulation (IPAL52557).
365 const int maxNbFaces = 4000;
367 for ( TopExp_Explorer f( aShape, TopAbs_FACE ); f.More() && nbFaces < maxNbFaces; f.Next() )
369 bool isPrecise = false;
370 if ( nbFaces < maxNbFaces )
373 GEOMUtils::PreciseBoundingBox( aShape, Box );
381 BRepBndLib::Add( aShape, Box );
384 return sqrt( Box.SquareExtent() );
389 //=======================================================================
391 * \brief Return diagonal size of bounding box of shape to mesh
393 //=======================================================================
395 double SMESH_Mesh::GetShapeDiagonalSize() const
397 if ( _shapeDiagonal == 0. && _isShapeToMesh )
398 const_cast<SMESH_Mesh*>(this)->_shapeDiagonal = GetShapeDiagonalSize( GetShapeToMesh() );
400 return _shapeDiagonal;
403 //================================================================================
405 * \brief Load mesh from study file
407 //================================================================================
409 void SMESH_Mesh::Load()
415 //=======================================================================
417 * \brief Remove all nodes and elements
419 //=======================================================================
421 void SMESH_Mesh::Clear()
423 if ( HasShapeToMesh() ) // remove all nodes and elements
426 _meshDS->ClearMesh();
428 // update compute state of submeshes
429 if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) )
431 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
432 sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
433 sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); // for event listeners (issue 0020918)
434 sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
437 else // remove only nodes/elements computed by algorithms
439 if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) )
441 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
442 sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
443 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
444 sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
447 GetMeshDS()->Modified();
451 //=======================================================================
453 * \brief Remove all nodes and elements of indicated shape
455 //=======================================================================
457 void SMESH_Mesh::ClearSubMesh(const int theShapeId)
459 // clear sub-meshes; get ready to re-compute as a side-effect
460 if ( SMESH_subMesh *sm = GetSubMeshContaining( theShapeId ) )
462 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
463 /*complexShapeFirst=*/false);
464 while ( smIt->more() )
467 TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();
468 if ( shapeType == TopAbs_VERTEX || shapeType < TopAbs_SOLID )
469 // all other shapes depends on vertices so they are already cleaned
470 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
471 // to recompute even if failed
472 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
477 //=======================================================================
478 //function : UNVToMesh
480 //=======================================================================
482 int SMESH_Mesh::UNVToMesh(const char* theFileName)
484 if ( _isShapeToMesh )
485 throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
486 _isShapeToMesh = false;
488 DriverUNV_R_SMDS_Mesh myReader;
489 myReader.SetMesh(_meshDS);
490 myReader.SetFile(theFileName);
491 myReader.SetMeshId(-1);
494 TGroupNamesMap& aGroupNames = myReader.GetGroupNamesMap();
495 TGroupNamesMap::iterator gr2names;
496 int anId = 1 + ( _mapGroup.empty() ? 0 : _mapGroup.rbegin()->first );
497 for ( gr2names = aGroupNames.begin(); gr2names != aGroupNames.end(); ++gr2names )
499 SMDS_MeshGroup* aGroup = gr2names->first;
500 const std::string& aName = gr2names->second;
501 SMESHDS_Group* aGroupDS = new SMESHDS_Group( anId++, _meshDS, aGroup->GetType() );
502 aGroupDS->SMDSGroup() = std::move( *aGroup );
503 aGroupDS->SetStoreName( aName.c_str() );
504 AddGroup( aGroupDS );
510 //=======================================================================
511 //function : MEDToMesh
513 //=======================================================================
515 int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
517 if ( _isShapeToMesh )
518 throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
519 _isShapeToMesh = false;
521 DriverMED_R_SMESHDS_Mesh myReader;
522 myReader.SetMesh(_meshDS);
523 myReader.SetMeshId(-1);
524 myReader.SetFile(theFileName);
525 myReader.SetMeshName(theMeshName);
526 Driver_Mesh::Status status = myReader.Perform();
528 if (SALOME::VerbosityActivated())
530 SMESH_ComputeErrorPtr er = myReader.GetError();
531 if ( er && !er->IsOK() ) std::cout << er->myComment << std::endl;
534 // Reading groups (sub-meshes are out of scope of MED import functionality)
535 std::list<TNameAndType> aGroupNames = myReader.GetGroupNamesAndTypes();
536 std::list<TNameAndType>::iterator name_type = aGroupNames.begin();
537 for ( ; name_type != aGroupNames.end(); name_type++ )
539 SMESH_Group* aGroup = AddGroup( name_type->second, name_type->first.c_str() );
541 SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
543 aGroupDS->SetStoreName( name_type->first.c_str() );
544 myReader.GetGroup( aGroupDS );
550 _meshDS->CompactMesh();
555 //=======================================================================
556 //function : STLToMesh
558 //=======================================================================
560 std::string SMESH_Mesh::STLToMesh(const char* theFileName)
563 throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
564 _isShapeToMesh = false;
566 DriverSTL_R_SMDS_Mesh myReader;
567 myReader.SetMesh(_meshDS);
568 myReader.SetFile(theFileName);
569 myReader.SetMeshId(-1);
572 return myReader.GetName();
575 //================================================================================
577 * \brief Reads the given mesh from the CGNS file
578 * \param theFileName - name of the file
579 * \retval int - Driver_Mesh::Status
581 //================================================================================
583 int SMESH_Mesh::CGNSToMesh(const char* theFileName,
584 const int theMeshIndex,
585 std::string& theMeshName)
587 int res = Driver_Mesh::DRS_FAIL;
590 DriverCGNS_Read myReader;
591 myReader.SetMesh(_meshDS);
592 myReader.SetFile(theFileName);
593 myReader.SetMeshId(theMeshIndex);
594 res = myReader.Perform();
595 theMeshName = myReader.GetMeshName();
604 //================================================================================
606 * \brief Fill its data by reading a GMF file
608 //================================================================================
610 SMESH_ComputeErrorPtr SMESH_Mesh::GMFToMesh(const char* theFileName,
611 bool theMakeRequiredGroups)
613 DriverGMF_Read myReader;
614 myReader.SetMesh(_meshDS);
615 myReader.SetFile(theFileName);
616 myReader.SetMakeRequiredGroups( theMakeRequiredGroups );
618 //theMeshName = myReader.GetMeshName();
623 return myReader.GetError();
626 //=============================================================================
630 //=============================================================================
632 SMESH_Hypothesis::Hypothesis_Status
633 SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
635 std::string* anError )
637 MESSAGE("SMESH_Mesh::AddHypothesis");
642 SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
643 if ( !subMesh || !subMesh->GetId())
644 return SMESH_Hypothesis::HYP_BAD_SUBSHAPE;
646 SMESH_Hypothesis *anHyp = GetHypothesis( anHypId );
648 throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
650 bool isGlobalHyp = IsMainShape( aSubShape );
652 // NotConformAllowed can be only global
655 // NOTE: this is not a correct way to check a name of hypothesis,
656 // there should be an attribute of hypothesis saying that it can/can't
658 std::string hypName = anHyp->GetName();
659 if ( hypName == "NotConformAllowed" )
661 MESSAGE( "Hypothesis <NotConformAllowed> can be only global" );
662 return SMESH_Hypothesis::HYP_INCOMPATIBLE;
668 bool isAlgo = ( anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
669 SMESH_subMesh::algo_event event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
671 SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
673 if ( anError && SMESH_Hypothesis::IsStatusFatal(ret) && subMesh->GetComputeError() )
674 *anError = subMesh->GetComputeError()->myComment;
677 if ( !SMESH_Hypothesis::IsStatusFatal(ret) &&
678 anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
680 event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP;
682 SMESH_Hypothesis::Hypothesis_Status ret2 =
683 subMesh->SubMeshesAlgoStateEngine(event, anHyp, /*exitOnFatal=*/true);
687 if ( SMESH_Hypothesis::IsStatusFatal( ret ))
689 if ( anError && subMesh->GetComputeError() )
690 *anError = subMesh->GetComputeError()->myComment;
692 event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
693 subMesh->AlgoStateEngine(event, anHyp);
697 // check concurrent hypotheses on ancestors
698 if (ret < SMESH_Hypothesis::HYP_CONCURRENT && !isGlobalHyp )
700 SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
701 while ( smIt->more() ) {
702 SMESH_subMesh* sm = smIt->next();
703 if ( sm->IsApplicableHypothesis( anHyp )) {
704 ret2 = sm->CheckConcurrentHypothesis( anHyp );
713 HasModificationsToDiscard(); // to reset _isModified flag if a mesh becomes empty
714 GetMeshDS()->Modified();
716 if(SALOME::VerbosityActivated()) subMesh->DumpAlgoState(true);
721 //=============================================================================
725 //=============================================================================
727 SMESH_Hypothesis::Hypothesis_Status
728 SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
731 MESSAGE("SMESH_Mesh::RemoveHypothesis");
733 StudyContextStruct *sc = _gen->GetStudyContext();
734 if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
735 throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
737 SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
738 SCRUTE(anHyp->GetType());
742 bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
743 SMESH_subMesh::algo_event event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
745 SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
747 SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
749 // there may appear concurrent hyps that were covered by the removed hyp
750 if (ret < SMESH_Hypothesis::HYP_CONCURRENT &&
751 subMesh->IsApplicableHypothesis( anHyp ) &&
752 subMesh->CheckConcurrentHypothesis( anHyp ) != SMESH_Hypothesis::HYP_OK)
753 ret = SMESH_Hypothesis::HYP_CONCURRENT;
756 if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
757 anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is removed from father
759 event = isAlgo ? SMESH_subMesh::REMOVE_FATHER_ALGO : SMESH_subMesh::REMOVE_FATHER_HYP;
761 SMESH_Hypothesis::Hypothesis_Status ret2 =
762 subMesh->SubMeshesAlgoStateEngine(event, anHyp);
763 if (ret2 > ret) // more severe
766 // check concurrent hypotheses on ancestors
767 if (ret < SMESH_Hypothesis::HYP_CONCURRENT && !IsMainShape( aSubShape ) )
769 SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
770 while ( smIt->more() ) {
771 SMESH_subMesh* sm = smIt->next();
772 if ( sm->IsApplicableHypothesis( anHyp )) {
773 ret2 = sm->CheckConcurrentHypothesis( anHyp );
783 HasModificationsToDiscard(); // to reset _isModified flag if mesh become empty
784 GetMeshDS()->Modified();
786 if(SALOME::VerbosityActivated()) subMesh->DumpAlgoState(true);
791 //=============================================================================
795 //=============================================================================
797 const std::list<const SMESHDS_Hypothesis*>&
798 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
800 return _meshDS->GetHypothesis(aSubShape);
803 //=======================================================================
805 * \brief Return the hypothesis assigned to the shape
806 * \param aSubShape - the shape to check
807 * \param aFilter - the hypothesis filter
808 * \param andAncestors - flag to check hypos assigned to ancestors of the shape
809 * \param assignedTo - to return the shape the found hypo is assigned to
810 * \retval SMESH_Hypothesis* - the first hypo passed through aFilter
812 //=======================================================================
814 const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape & aSubShape,
815 const SMESH_HypoFilter& aFilter,
816 const bool andAncestors,
817 TopoDS_Shape* assignedTo) const
819 return GetHypothesis( const_cast< SMESH_Mesh* >(this)->GetSubMesh( aSubShape ),
820 aFilter, andAncestors, assignedTo );
823 //=======================================================================
825 * \brief Return the hypothesis assigned to the shape of a sub-mesh
826 * \param aSubMesh - the sub-mesh to check
827 * \param aFilter - the hypothesis filter
828 * \param andAncestors - flag to check hypos assigned to ancestors of the shape
829 * \param assignedTo - to return the shape the found hypo is assigned to
830 * \retval SMESH_Hypothesis* - the first hypo passed through aFilter
832 //=======================================================================
834 const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const SMESH_subMesh * aSubMesh,
835 const SMESH_HypoFilter& aFilter,
836 const bool andAncestors,
837 TopoDS_Shape* assignedTo) const
839 if ( !aSubMesh ) return 0;
842 const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
843 const std::list<const SMESHDS_Hypothesis*>& hypList = _meshDS->GetHypothesis(aSubShape);
844 std::list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
845 for ( ; hyp != hypList.end(); hyp++ ) {
846 const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
847 if ( aFilter.IsOk( h, aSubShape)) {
848 if ( assignedTo ) *assignedTo = aSubShape;
855 // user sorted submeshes of ancestors, according to stored submesh priority
856 std::vector< SMESH_subMesh * > & ancestors =
857 const_cast< std::vector< SMESH_subMesh * > & > ( aSubMesh->GetAncestors() );
858 SortByMeshOrder( ancestors );
860 std::vector<SMESH_subMesh*>::const_iterator smIt = ancestors.begin();
861 for ( ; smIt != ancestors.end(); smIt++ )
863 const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
864 const std::list<const SMESHDS_Hypothesis*>& hypList = _meshDS->GetHypothesis(curSh);
865 std::list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
866 for ( ; hyp != hypList.end(); hyp++ ) {
867 const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
868 if (aFilter.IsOk( h, curSh )) {
869 if ( assignedTo ) *assignedTo = curSh;
878 //================================================================================
880 * \brief Return hypotheses assigned to the shape
881 * \param aSubShape - the shape to check
882 * \param aFilter - the hypothesis filter
883 * \param aHypList - the list of the found hypotheses
884 * \param andAncestors - flag to check hypos assigned to ancestors of the shape
885 * \retval int - number of unique hypos in aHypList
887 //================================================================================
889 int SMESH_Mesh::GetHypotheses(const TopoDS_Shape & aSubShape,
890 const SMESH_HypoFilter& aFilter,
891 std::list <const SMESHDS_Hypothesis * >& aHypList,
892 const bool andAncestors,
893 std::list< TopoDS_Shape > * assignedTo/*=0*/) const
895 return GetHypotheses( const_cast< SMESH_Mesh* >(this)->GetSubMesh( aSubShape ),
896 aFilter, aHypList, andAncestors, assignedTo );
899 //================================================================================
901 * \brief Return hypotheses assigned to the shape of a sub-mesh
902 * \param aSubShape - the sub-mesh to check
903 * \param aFilter - the hypothesis filter
904 * \param aHypList - the list of the found hypotheses
905 * \param andAncestors - flag to check hypos assigned to ancestors of the shape
906 * \retval int - number of unique hypos in aHypList
908 //================================================================================
910 int SMESH_Mesh::GetHypotheses(const SMESH_subMesh * aSubMesh,
911 const SMESH_HypoFilter& aFilter,
912 std::list <const SMESHDS_Hypothesis * >& aHypList,
913 const bool andAncestors,
914 std::list< TopoDS_Shape > * assignedTo/*=0*/) const
916 if ( !aSubMesh ) return 0;
918 std::set< std::string > hypTypes; // to exclude same type hypos from the result list
921 // only one main hypothesis is allowed
922 bool mainHypFound = false;
925 std::list<const SMESHDS_Hypothesis*>::const_iterator hyp;
926 for ( hyp = aHypList.begin(); hyp != aHypList.end(); hyp++ ) {
927 if ( hypTypes.insert( (*hyp)->GetName() ).second )
929 if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
933 // get hypos from aSubShape
935 const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
936 const std::list<const SMESHDS_Hypothesis*>& hypList = _meshDS->GetHypothesis(aSubShape);
937 for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
939 const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
940 if (( aFilter.IsOk( h, aSubShape )) &&
941 ( h->IsAuxiliary() || !mainHypFound ) &&
942 ( h->IsAuxiliary() || hypTypes.insert( h->GetName() ).second ))
944 aHypList.push_back( *hyp );
946 if ( !h->IsAuxiliary() )
948 if ( assignedTo ) assignedTo->push_back( aSubShape );
953 // get hypos from ancestors of aSubShape
956 // user sorted submeshes of ancestors, according to stored submesh priority
957 std::vector< SMESH_subMesh * > & ancestors =
958 const_cast< std::vector< SMESH_subMesh * > & > ( aSubMesh->GetAncestors() );
959 SortByMeshOrder( ancestors );
961 std::vector<SMESH_subMesh*>::const_iterator smIt = ancestors.begin();
962 for ( ; smIt != ancestors.end(); smIt++ )
964 const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
965 const std::list<const SMESHDS_Hypothesis*>& hypList = _meshDS->GetHypothesis(curSh);
966 for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
968 const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
969 if (( aFilter.IsOk( h, curSh )) &&
970 ( h->IsAuxiliary() || !mainHypFound ) &&
971 ( h->IsAuxiliary() || hypTypes.insert( h->GetName() ).second ))
973 aHypList.push_back( *hyp );
975 if ( !h->IsAuxiliary() )
977 if ( assignedTo ) assignedTo->push_back( curSh );
985 //================================================================================
987 * \brief Return a hypothesis by its ID
989 //================================================================================
991 SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const int anHypId) const
993 StudyContextStruct *sc = _gen->GetStudyContext();
994 if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
997 SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
1001 //=============================================================================
1005 //=============================================================================
1007 const std::list<SMESHDS_Command*> & SMESH_Mesh::GetLog()
1009 return _meshDS->GetScript()->GetCommands();
1012 //=============================================================================
1016 //=============================================================================
1017 void SMESH_Mesh::ClearLog()
1019 _meshDS->GetScript()->Clear();
1022 //=============================================================================
1024 * Get or Create the SMESH_subMesh object implementation
1026 //=============================================================================
1028 SMESH_subMesh * SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
1030 int index = _meshDS->ShapeToIndex(aSubShape);
1031 if ( !index && aSubShape.IsNull() )
1034 // for submeshes on GEOM Group
1035 if (( !index || index > _nbSubShapes ) && aSubShape.ShapeType() == TopAbs_COMPOUND )
1037 TopoDS_Iterator it( aSubShape );
1040 index = _meshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() );
1041 // fill map of Ancestors
1042 while ( _nbSubShapes < index )
1043 fillAncestorsMap( _meshDS->IndexToShape( ++_nbSubShapes ));
1047 // return NULL; // neither sub-shape nor a group
1049 SMESH_subMesh* aSubMesh = _subMeshHolder->Get( index );
1052 aSubMesh = new SMESH_subMesh(index, this, _meshDS, aSubShape);
1053 _subMeshHolder->Add( index, aSubMesh );
1055 // include non-computable sub-meshes in SMESH_subMesh::_ancestors of sub-submeshes
1056 switch ( aSubShape.ShapeType() ) {
1057 case TopAbs_COMPOUND:
1060 for ( TopoDS_Iterator subIt( aSubShape ); subIt.More(); subIt.Next() )
1062 SMESH_subMesh* sm = GetSubMesh( subIt.Value() );
1063 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*inclideSelf=*/true);
1064 while ( smIt->more() )
1065 smIt->next()->ClearAncestors();
1073 //=============================================================================
1075 * Get the SMESH_subMesh object implementation. Don't create it, return null
1076 * if it does not exist.
1078 //=============================================================================
1080 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape) const
1082 int index = _meshDS->ShapeToIndex(aSubShape);
1083 return GetSubMeshContaining( index );
1086 //=============================================================================
1088 * Get the SMESH_subMesh object implementation. Don't create it, return null
1089 * if it does not exist.
1091 //=============================================================================
1093 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID) const
1095 SMESH_subMesh *aSubMesh = _subMeshHolder->Get( aShapeID );
1099 //================================================================================
1101 * \brief Return sub-meshes of groups containing the given sub-shape
1103 //================================================================================
1105 std::list<SMESH_subMesh*>
1106 SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
1108 std::list<SMESH_subMesh*> found;
1110 SMESH_subMesh * subMesh = GetSubMeshContaining(aSubShape);
1114 // sub-meshes of groups have max IDs, so search from the map end
1115 SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator( /*reverse=*/true ) );
1116 while ( smIt->more() ) {
1117 SMESH_subMesh* sm = smIt->next();
1118 SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
1119 if ( ds && ds->IsComplexSubmesh() ) {
1120 if ( SMESH_MesherHelper::IsSubShape( aSubShape, sm->GetSubShape() ))
1122 found.push_back( sm );
1126 break; // the rest sub-meshes are not those of groups
1130 if ( found.empty() ) // maybe the main shape is a COMPOUND (issue 0021530)
1132 if ( SMESH_subMesh * mainSM = GetSubMeshContaining(1) )
1133 if ( mainSM->GetSubShape().ShapeType() == TopAbs_COMPOUND )
1135 TopoDS_Iterator it( mainSM->GetSubShape() );
1136 if ( it.Value().ShapeType() == aSubShape.ShapeType() &&
1137 SMESH_MesherHelper::IsSubShape( aSubShape, mainSM->GetSubShape() ))
1138 found.push_back( mainSM );
1141 else // issue 0023068
1143 if ( SMESH_subMesh * mainSM = GetSubMeshContaining(1) )
1144 if ( mainSM->GetSubShape().ShapeType() == TopAbs_COMPOUND )
1145 found.push_back( mainSM );
1149 //=======================================================================
1150 //function : IsUsedHypothesis
1151 //purpose : Return True if anHyp is used to mesh aSubShape
1152 //=======================================================================
1154 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
1155 const SMESH_subMesh* aSubMesh)
1157 SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
1159 // check if anHyp can be used to mesh aSubMesh
1160 if ( !aSubMesh || !aSubMesh->IsApplicableHypothesis( hyp ))
1163 SMESH_Algo *algo = aSubMesh->GetAlgo();
1166 if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
1167 return ( anHyp == algo );
1169 // algorithm parameter
1172 // look through hypotheses used by algo
1173 const SMESH_HypoFilter* hypoKind;
1174 if (( hypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() ))) {
1175 std::list <const SMESHDS_Hypothesis * > usedHyps;
1176 if ( GetHypotheses( aSubMesh, *hypoKind, usedHyps, true ))
1177 return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
1184 //=======================================================================
1185 //function : NotifySubMeshesHypothesisModification
1186 //purpose : Say all submeshes using theChangedHyp that it has been modified
1187 //=======================================================================
1189 void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* hyp)
1192 if ( !GetMeshDS()->IsUsedHypothesis( hyp ))
1195 smIdType nbEntities = ( _meshDS->NbNodes() + _meshDS->NbElements() );
1196 if ( hyp && _callUp && !_callUp->IsLoaded() ) // for not loaded mesh (#16648)
1198 _callUp->HypothesisModified( hyp->GetID(), /*updateIcons=*/true );
1199 nbEntities = ( _meshDS->NbNodes() + _meshDS->NbElements() ); // after loading mesh
1203 const SMESH_HypoFilter* compatibleHypoKind;
1204 std::list <const SMESHDS_Hypothesis * > usedHyps;
1205 std::vector< SMESH_subMesh* > smToNotify;
1206 bool allMeshedEdgesNotified = true;
1208 SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
1209 while ( smIt->more() )
1211 SMESH_subMesh* aSubMesh = smIt->next();
1212 bool toNotify = false;
1214 // if aSubMesh meshing depends on hyp,
1215 // we call aSubMesh->AlgoStateEngine( MODIF_HYP, hyp ) that causes either
1216 // 1) clearing already computed aSubMesh or
1217 // 2) changing algo_state from MISSING_HYP to HYP_OK when parameters of hyp becomes valid,
1218 // other possible changes are not interesting. (IPAL0052457 - assigning hyp performance pb)
1219 if ( aSubMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK ||
1220 aSubMesh->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE ||
1221 aSubMesh->GetAlgoState() == SMESH_subMesh::MISSING_HYP ||
1222 hyp->DataDependOnParams() )
1224 const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
1226 if (( aSubMesh->IsApplicableHypothesis( hyp )) &&
1227 ( algo = aSubMesh->GetAlgo() ) &&
1228 ( compatibleHypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() )) &&
1229 ( compatibleHypoKind->IsOk( hyp, aSubShape )))
1231 // check if hyp is used by algo
1233 toNotify = ( GetHypotheses( aSubMesh, *compatibleHypoKind, usedHyps, true ) &&
1234 std::find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() );
1239 smToNotify.push_back( aSubMesh );
1240 if ( aSubMesh->GetAlgoState() == SMESH_subMesh::MISSING_HYP )
1241 allMeshedEdgesNotified = false; // update of algo state needed, not mesh clearing
1245 if ( !aSubMesh->IsEmpty() &&
1246 aSubMesh->GetSubShape().ShapeType() == TopAbs_EDGE )
1247 allMeshedEdgesNotified = false;
1250 if ( smToNotify.empty() )
1253 // if all meshed EDGEs will be notified then the notification is equivalent
1254 // to the whole mesh clearing, which is usually faster
1255 if ( allMeshedEdgesNotified && NbNodes() > 0 )
1261 // notify in reverse order to avoid filling the pool of IDs
1262 for ( int i = smToNotify.size()-1; i >= 0; --i )
1263 smToNotify[i]->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
1264 const_cast< SMESH_Hypothesis*>( hyp ));
1266 HasModificationsToDiscard(); // to reset _isModified flag if mesh becomes empty
1267 GetMeshDS()->Modified();
1269 smIdType newNbEntities = ( _meshDS->NbNodes() + _meshDS->NbElements() );
1270 if ( hyp && _callUp )
1271 _callUp->HypothesisModified( hyp->GetID(), newNbEntities != nbEntities );
1274 //=============================================================================
1276 * Auto color functionality
1278 //=============================================================================
1279 void SMESH_Mesh::SetAutoColor(bool theAutoColor)
1281 _isAutoColor = theAutoColor;
1284 bool SMESH_Mesh::GetAutoColor()
1286 return _isAutoColor;
1289 //=======================================================================
1290 //function : SetIsModified
1291 //purpose : Set the flag meaning that the mesh has been edited "manually"
1292 //=======================================================================
1294 void SMESH_Mesh::SetIsModified(bool isModified)
1296 _isModified = isModified;
1299 // check if mesh becomes empty as result of modification
1300 HasModificationsToDiscard();
1303 //=======================================================================
1304 //function : HasModificationsToDiscard
1305 //purpose : Return true if the mesh has been edited since a total re-compute
1306 // and those modifications may prevent successful partial re-compute.
1307 // As a side effect reset _isModified flag if mesh is empty
1309 //=======================================================================
1311 bool SMESH_Mesh::HasModificationsToDiscard() const
1313 if ( ! _isModified )
1316 // return true if the next Compute() will be partial and
1317 // existing but changed elements may prevent successful re-compute
1318 bool hasComputed = false, hasNotComputed = false;
1319 SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
1320 while ( smIt->more() )
1322 const SMESH_subMesh* aSubMesh = smIt->next();
1323 switch ( aSubMesh->GetSubShape().ShapeType() )
1328 if ( aSubMesh->IsMeshComputed() )
1331 hasNotComputed = true;
1332 if ( hasComputed && hasNotComputed)
1338 if ( NbNodes() < 1 )
1339 const_cast<SMESH_Mesh*>(this)->_isModified = false;
1344 //=============================================================================
1346 * \brief Return true if all sub-meshes are computed OK - to update an icon
1348 //=============================================================================
1350 bool SMESH_Mesh::IsComputedOK()
1352 if ( NbNodes() == 0 )
1355 // if ( !HasShapeToMesh() )
1358 if ( SMESH_subMesh* mainSM = GetSubMeshContaining( 1 ))
1360 SMESH_subMeshIteratorPtr smIt = mainSM->getDependsOnIterator(/*includeSelf=*/true);
1361 while ( smIt->more() )
1363 const SMESH_subMesh* sm = smIt->next();
1364 if ( !sm->IsAlwaysComputed() )
1365 switch ( sm->GetComputeState() )
1367 case SMESH_subMesh::NOT_READY:
1368 case SMESH_subMesh::COMPUTE_OK:
1370 case SMESH_subMesh::FAILED_TO_COMPUTE:
1371 case SMESH_subMesh::READY_TO_COMPUTE:
1379 //================================================================================
1381 * \brief Check if any groups of the same type have equal names
1383 //================================================================================
1385 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
1387 // Corrected for Mantis issue 0020028
1388 std::map< SMDSAbs_ElementType, std::set< std::string > > aGroupNames;
1389 for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1391 SMESH_Group* aGroup = it->second;
1392 SMDSAbs_ElementType aType = aGroup->GetGroupDS()->GetType();
1393 std::string aGroupName = aGroup->GetName();
1394 aGroupName.resize( MAX_MED_GROUP_NAME_LENGTH );
1395 if ( !aGroupNames[aType].insert(aGroupName).second )
1402 //================================================================================
1404 * \brief Export the mesh to a writer
1406 //================================================================================
1408 void SMESH_Mesh::exportMEDCommmon(DriverMED_W_SMESHDS_Mesh& theWriter,
1409 const char* theMeshName,
1411 const SMESHDS_Mesh* theMeshPart,
1412 bool theAutoDimension,
1413 bool theAddODOnVertices,
1414 double theZTolerance,
1415 bool theSaveNumbers)
1417 Driver_Mesh::Status status = Driver_Mesh::DRS_OK;
1421 theWriter.SetMesh ( theMeshPart ? (SMESHDS_Mesh*) theMeshPart : _meshDS );
1422 theWriter.SetAutoDimension( theAutoDimension );
1423 theWriter.AddODOnVertices ( theAddODOnVertices );
1424 theWriter.SetZTolerance ( theZTolerance );
1425 theWriter.SetSaveNumbers ( theSaveNumbers );
1427 theWriter.SetMeshId ( _id );
1429 theWriter.SetMeshId ( -1 );
1430 theWriter.SetMeshName ( theMeshName );
1433 if ( theAutoGroups ) {
1434 theWriter.AddGroupOfNodes();
1435 theWriter.AddGroupOfEdges();
1436 theWriter.AddGroupOfFaces();
1437 theWriter.AddGroupOfVolumes();
1438 theWriter.AddGroupOf0DElems();
1439 theWriter.AddGroupOfBalls();
1442 // Pass groups to writer. Provide unique group names.
1443 //set<string> aGroupNames; // Corrected for Mantis issue 0020028
1446 std::map< SMDSAbs_ElementType, std::set<std::string> > aGroupNames;
1448 int maxNbIter = 10000; // to guarantee cycle finish
1449 for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin();
1450 it != _mapGroup.end();
1452 SMESH_Group* aGroup = it->second;
1453 SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1455 SMDSAbs_ElementType aType = aGroupDS->GetType();
1456 std::string aGroupName0 = aGroup->GetName();
1457 aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
1458 std::string aGroupName = aGroupName0;
1459 for (int i = 1; !aGroupNames[aType].insert(aGroupName).second && i < maxNbIter; i++) {
1460 sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
1461 aGroupName = aString;
1462 aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
1464 aGroupDS->SetStoreName( aGroupName.c_str() );
1465 theWriter.AddGroup( aGroupDS );
1470 status = theWriter.Perform();
1472 SMESH_CATCH( SMESH::throwSalomeEx );
1474 if ( status == Driver_Mesh::DRS_TOO_LARGE_MESH )
1475 throw TooLargeForExport("MED");
1478 //================================================================================
1480 * Same as SMESH_Mesh::ExportMED except for \a file and \a theVersion
1482 //================================================================================
1484 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte>
1485 SMESH_Mesh::ExportMEDCoupling(const char* theMeshName,
1487 const SMESHDS_Mesh* theMeshPart,
1488 bool theAutoDimension,
1489 bool theAddODOnVertices,
1490 double theZTolerance,
1491 bool theSaveNumbers)
1493 DriverMED_W_SMESHDS_Mesh_Mem writer;
1494 this->exportMEDCommmon( writer, theMeshName, theAutoGroups, theMeshPart, theAutoDimension,
1495 theAddODOnVertices, theZTolerance, theSaveNumbers);
1496 return writer.getData();
1499 //================================================================================
1501 * \brief Export the mesh to a med file
1502 * \param [in] theFile - name of the MED file
1503 * \param [in] theMeshName - name of this mesh
1504 * \param [in] theAutoGroups - boolean parameter for creating/not creating
1505 * the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
1506 * the typical use is auto_groups=false.
1507 * \param [in] theVersion - define the minor (xy, where version is x.y.z) of MED file format.
1508 * If theVersion is equal to -1, the minor version is not changed (default).
1509 * \param [in] theMeshPart - mesh data to export
1510 * \param [in] theAutoDimension - if \c true, a space dimension of a MED mesh can be either
1511 * - 1D if all mesh nodes lie on OX coordinate axis, or
1512 * - 2D if all mesh nodes lie on XOY coordinate plane, or
1513 * - 3D in the rest cases.
1514 * If \a theAutoDimension is \c false, the space dimension is always 3.
1515 * \param [in] theAddODOnVertices - to create 0D elements on all vertices
1516 * \param [in] theZTolerance - tolerance in Z direction. If Z coordinate of a node is close to zero
1517 * within a given tolerance, the coordinate is set to zero.
1518 * If \a ZTolerance is negative, the node coordinates are kept as is.
1519 * \param [in] theSaveNumbers : enable saving numbers of nodes and cells.
1520 * \return int - mesh index in the file
1522 //================================================================================
1524 void SMESH_Mesh::ExportMED(const char * theFile,
1525 const char* theMeshName,
1528 const SMESHDS_Mesh* theMeshPart,
1529 bool theAutoDimension,
1530 bool theAddODOnVertices,
1531 double theZTolerance,
1532 bool theSaveNumbers)
1534 MESSAGE("MED_VERSION:"<< theVersion);
1535 DriverMED_W_SMESHDS_Mesh writer;
1536 writer.SetFile( theFile, theVersion );
1537 this->exportMEDCommmon( writer, theMeshName, theAutoGroups, theMeshPart, theAutoDimension, theAddODOnVertices, theZTolerance, theSaveNumbers );
1540 //================================================================================
1542 * \brief Export the mesh to a DAT file
1544 //================================================================================
1546 void SMESH_Mesh::ExportDAT(const char * file,
1547 const SMESHDS_Mesh* meshPart,
1548 const bool renumber)
1550 Driver_Mesh::Status status;
1553 DriverDAT_W_SMDS_Mesh writer;
1554 writer.SetFile( file );
1555 writer.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _meshDS );
1556 writer.SetMeshId(_id);
1557 writer.SetRenumber( renumber );
1558 status = writer.Perform();
1560 SMESH_CATCH( SMESH::throwSalomeEx );
1562 if ( status == Driver_Mesh::DRS_TOO_LARGE_MESH )
1563 throw TooLargeForExport("DAT");
1566 //================================================================================
1568 * \brief Export the mesh to an UNV file
1570 //================================================================================
1572 void SMESH_Mesh::ExportUNV(const char * file,
1573 const SMESHDS_Mesh* meshPart,
1574 const bool renumber)
1576 Driver_Mesh::Status status;
1579 DriverUNV_W_SMDS_Mesh writer;
1580 writer.SetFile( file );
1581 writer.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _meshDS );
1582 writer.SetMeshId(_id);
1583 writer.SetRenumber( renumber );
1585 // pass group names to SMESHDS
1588 std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin();
1589 for ( ; it != _mapGroup.end(); it++ ) {
1590 SMESH_Group* aGroup = it->second;
1591 SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1593 std::string aGroupName = aGroup->GetName();
1594 aGroupDS->SetStoreName( aGroupName.c_str() );
1595 writer.AddGroup( aGroupDS );
1599 status = writer.Perform();
1601 SMESH_CATCH( SMESH::throwSalomeEx );
1603 if ( status == Driver_Mesh::DRS_TOO_LARGE_MESH )
1604 throw TooLargeForExport("UNV");
1607 //================================================================================
1609 * \brief Export the mesh to an STL file
1611 //================================================================================
1613 void SMESH_Mesh::ExportSTL(const char * file,
1616 const SMESHDS_Mesh* meshPart)
1618 Driver_Mesh::Status status;
1621 DriverSTL_W_SMDS_Mesh writer;
1622 writer.SetFile( file );
1623 writer.SetIsAscii( isascii );
1624 writer.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _meshDS);
1625 writer.SetMeshId(_id);
1626 if ( name ) writer.SetName( name );
1627 status = writer.Perform();
1629 SMESH_CATCH( SMESH::throwSalomeEx );
1631 if ( status == Driver_Mesh::DRS_TOO_LARGE_MESH )
1632 throw TooLargeForExport("STL");
1635 //================================================================================
1637 * \brief Export the mesh to the CGNS file
1639 //================================================================================
1641 void SMESH_Mesh::ExportCGNS(const char * file,
1642 const SMESHDS_Mesh* meshDS,
1643 const char * meshName,
1644 const bool groupElemsByType)
1647 int res = Driver_Mesh::DRS_FAIL;
1650 // pass group names to SMESHDS
1651 std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin();
1652 for ( ; it != _mapGroup.end(); it++ ) {
1653 SMESH_Group* group = it->second;
1654 SMESHDS_GroupBase* groupDS = group->GetGroupDS();
1656 std::string groupName = group->GetName();
1657 groupDS->SetStoreName( groupName.c_str() );
1662 DriverCGNS_Write writer;
1663 writer.SetFile( file );
1664 writer.SetMesh( const_cast<SMESHDS_Mesh*>( meshDS ));
1665 writer.SetMeshName( SMESH_Comment("Mesh_") << meshDS->GetPersistentId());
1666 if ( meshName && meshName[0] )
1667 writer.SetMeshName( meshName );
1668 writer.SetElementsByType( groupElemsByType );
1669 res = writer.Perform();
1670 if ( res != Driver_Mesh::DRS_OK )
1672 SMESH_ComputeErrorPtr err = writer.GetError();
1673 if ( err && !err->IsOK() && !err->myComment.empty() )
1674 throw SALOME_Exception(("Export failed: " + err->myComment ).c_str() );
1678 SMESH_CATCH( SMESH::throwSalomeEx );
1680 if ( res == Driver_Mesh::DRS_TOO_LARGE_MESH )
1681 throw TooLargeForExport("CGNS");
1683 if ( res != Driver_Mesh::DRS_OK )
1684 throw SALOME_Exception("Export failed");
1687 //================================================================================
1689 * \brief Export the mesh to a GMF file
1691 //================================================================================
1693 void SMESH_Mesh::ExportGMF(const char * file,
1694 const SMESHDS_Mesh* meshDS,
1695 bool withRequiredGroups)
1697 Driver_Mesh::Status status;
1700 DriverGMF_Write writer;
1701 writer.SetFile( file );
1702 writer.SetMesh( const_cast<SMESHDS_Mesh*>( meshDS ));
1703 writer.SetExportRequiredGroups( withRequiredGroups );
1705 status = writer.Perform();
1707 SMESH_CATCH( SMESH::throwSalomeEx );
1709 if ( status == Driver_Mesh::DRS_TOO_LARGE_MESH )
1710 throw TooLargeForExport("GMF");
1713 //================================================================================
1715 * \brief Return a ratio of "compute cost" of computed sub-meshes to the whole
1718 //================================================================================
1720 double SMESH_Mesh::GetComputeProgress() const
1722 double totalCost = 1e-100, computedCost = 0;
1723 const SMESH_subMesh* curSM = _gen->GetCurrentSubMesh();
1725 // get progress of a current algo
1726 TColStd_MapOfInteger currentSubIds;
1728 if ( SMESH_Algo* algo = curSM->GetAlgo() )
1730 int algoNotDoneCost = 0, algoDoneCost = 0;
1731 const std::vector<SMESH_subMesh*>& smToCompute = algo->SubMeshesToCompute();
1732 for ( size_t i = 0; i < smToCompute.size(); ++i )
1734 if ( smToCompute[i]->IsEmpty() || smToCompute.size() == 1 )
1735 algoNotDoneCost += smToCompute[i]->GetComputeCost();
1737 algoDoneCost += smToCompute[i]->GetComputeCost();
1738 currentSubIds.Add( smToCompute[i]->GetId() );
1744 rate = algo->GetProgress();
1747 if (SALOME::VerbosityActivated())
1748 std::cerr << "Exception in " << algo->GetName() << "::GetProgress()" << std::endl;
1750 if ( 0. < rate && rate < 1.001 )
1752 computedCost += rate * ( algoDoneCost + algoNotDoneCost );
1756 rate = algo->GetProgressByTic();
1757 computedCost += algoDoneCost + rate * algoNotDoneCost;
1759 // cout << "rate: "<<rate << " algoNotDoneCost: " << algoNotDoneCost << endl;
1762 // get cost of already treated sub-meshes
1763 if ( SMESH_subMesh* mainSM = GetSubMeshContaining( 1 ))
1765 SMESH_subMeshIteratorPtr smIt = mainSM->getDependsOnIterator(/*includeSelf=*/true);
1766 while ( smIt->more() )
1768 const SMESH_subMesh* sm = smIt->next();
1769 const int smCost = sm->GetComputeCost();
1770 totalCost += smCost;
1771 if ( !currentSubIds.Contains( sm->GetId() ) )
1773 if (( !sm->IsEmpty() ) ||
1774 ( sm->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE &&
1775 !sm->DependsOn( curSM ) ))
1776 computedCost += smCost;
1780 // cout << "Total: " << totalCost
1781 // << " computed: " << computedCost << " progress: " << computedCost / totalCost
1782 // << " nbElems: " << GetMeshDS()->GetMeshInfo().NbElements() << endl;
1783 return computedCost / totalCost;
1786 //================================================================================
1788 * \brief Return number of nodes in the mesh
1790 //================================================================================
1792 smIdType SMESH_Mesh::NbNodes() const
1794 return _meshDS->NbNodes();
1797 //================================================================================
1799 * \brief Return number of edges of given order in the mesh
1801 //================================================================================
1803 smIdType SMESH_Mesh::Nb0DElements() const
1805 return _meshDS->GetMeshInfo().Nb0DElements();
1808 //================================================================================
1810 * \brief Return number of edges of given order in the mesh
1812 //================================================================================
1814 smIdType SMESH_Mesh::NbEdges(SMDSAbs_ElementOrder order) const
1816 return _meshDS->GetMeshInfo().NbEdges(order);
1819 //================================================================================
1821 * \brief Return number of faces of given order in the mesh
1823 //================================================================================
1825 smIdType SMESH_Mesh::NbFaces(SMDSAbs_ElementOrder order) const
1827 return _meshDS->GetMeshInfo().NbFaces(order);
1830 //================================================================================
1832 * \brief Return the number of faces in the mesh
1834 //================================================================================
1836 smIdType SMESH_Mesh::NbTriangles(SMDSAbs_ElementOrder order) const
1838 return _meshDS->GetMeshInfo().NbTriangles(order);
1841 //================================================================================
1843 * \brief Return number of biquadratic triangles in the mesh
1845 //================================================================================
1847 smIdType SMESH_Mesh::NbBiQuadTriangles() const
1849 return _meshDS->GetMeshInfo().NbBiQuadTriangles();
1852 //================================================================================
1854 * \brief Return the number nodes faces in the mesh
1856 //================================================================================
1858 smIdType SMESH_Mesh::NbQuadrangles(SMDSAbs_ElementOrder order) const
1860 return _meshDS->GetMeshInfo().NbQuadrangles(order);
1863 //================================================================================
1865 * \brief Return number of biquadratic quadrangles in the mesh
1867 //================================================================================
1869 smIdType SMESH_Mesh::NbBiQuadQuadrangles() const
1871 return _meshDS->GetMeshInfo().NbBiQuadQuadrangles();
1874 //================================================================================
1876 * \brief Return the number of polygonal faces in the mesh
1878 //================================================================================
1880 smIdType SMESH_Mesh::NbPolygons(SMDSAbs_ElementOrder order) const
1882 return _meshDS->GetMeshInfo().NbPolygons(order);
1885 //================================================================================
1887 * \brief Return number of volumes of given order in the mesh
1889 //================================================================================
1891 smIdType SMESH_Mesh::NbVolumes(SMDSAbs_ElementOrder order) const
1893 return _meshDS->GetMeshInfo().NbVolumes(order);
1896 //================================================================================
1898 * \brief Return number of tetrahedrons of given order in the mesh
1900 //================================================================================
1902 smIdType SMESH_Mesh::NbTetras(SMDSAbs_ElementOrder order) const
1904 return _meshDS->GetMeshInfo().NbTetras(order);
1907 //================================================================================
1909 * \brief Return number of hexahedrons of given order in the mesh
1911 //================================================================================
1913 smIdType SMESH_Mesh::NbHexas(SMDSAbs_ElementOrder order) const
1915 return _meshDS->GetMeshInfo().NbHexas(order);
1918 //================================================================================
1920 * \brief Return number of triquadratic hexahedrons in the mesh
1922 //================================================================================
1924 smIdType SMESH_Mesh::NbTriQuadraticHexas() const
1926 return _meshDS->GetMeshInfo().NbTriQuadHexas();
1929 //================================================================================
1931 * \brief Return number of pyramids of given order in the mesh
1933 //================================================================================
1935 smIdType SMESH_Mesh::NbPyramids(SMDSAbs_ElementOrder order) const
1937 return _meshDS->GetMeshInfo().NbPyramids(order);
1940 //================================================================================
1942 * \brief Return number of prisms (penthahedrons) of given order in the mesh
1944 //================================================================================
1946 smIdType SMESH_Mesh::NbPrisms(SMDSAbs_ElementOrder order) const
1948 return _meshDS->GetMeshInfo().NbPrisms(order);
1951 smIdType SMESH_Mesh::NbQuadPrisms() const
1953 return _meshDS->GetMeshInfo().NbQuadPrisms();
1956 smIdType SMESH_Mesh::NbBiQuadPrisms() const
1958 return _meshDS->GetMeshInfo().NbBiQuadPrisms();
1962 //================================================================================
1964 * \brief Return number of hexagonal prisms in the mesh
1966 //================================================================================
1968 smIdType SMESH_Mesh::NbHexagonalPrisms() const
1970 return _meshDS->GetMeshInfo().NbHexPrisms();
1973 //================================================================================
1975 * \brief Return number of polyhedrons in the mesh
1977 //================================================================================
1979 smIdType SMESH_Mesh::NbPolyhedrons() const
1981 return _meshDS->GetMeshInfo().NbPolyhedrons();
1984 //================================================================================
1986 * \brief Return number of ball elements in the mesh
1988 //================================================================================
1990 smIdType SMESH_Mesh::NbBalls() const
1992 return _meshDS->GetMeshInfo().NbBalls();
1995 //================================================================================
1997 * \brief Return number of submeshes in the mesh
1999 //================================================================================
2001 smIdType SMESH_Mesh::NbSubMesh() const
2003 return _meshDS->NbSubMesh();
2006 //================================================================================
2008 * \brief Returns number of meshes in the Study, that is supposed to be
2009 * equal to SMESHDS_Document::NbMeshes()
2011 //================================================================================
2013 int SMESH_Mesh::NbMeshes() const // nb meshes in the Study
2015 return _document->NbMeshes();
2018 //=======================================================================
2019 //function : IsNotConformAllowed
2020 //purpose : check if a hypothesis allowing notconform mesh is present
2021 //=======================================================================
2023 bool SMESH_Mesh::IsNotConformAllowed() const
2025 MESSAGE("SMESH_Mesh::IsNotConformAllowed");
2027 static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
2028 return GetHypothesis( _meshDS->ShapeToMesh(), filter, false );
2031 //=======================================================================
2032 //function : IsMainShape
2034 //=======================================================================
2036 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
2038 return theShape.IsSame(_meshDS->ShapeToMesh() );
2041 //=======================================================================
2042 //function : GetShapeByEntry
2043 //purpose : return TopoDS_Shape by its study entry
2044 //=======================================================================
2046 TopoDS_Shape SMESH_Mesh::GetShapeByEntry(const std::string& entry) const
2048 return _callUp ? _callUp->GetShapeByEntry( entry ) : TopoDS_Shape();
2051 //=============================================================================
2055 //=============================================================================
2057 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
2058 const char* theName,
2060 const TopoDS_Shape& theShape,
2061 const SMESH_PredicatePtr& thePredicate)
2063 if ( _mapGroup.count( theId ))
2065 int id = ( theId < 0 ) ? _groupId : theId;
2066 SMESH_Group* aGroup = new SMESH_Group ( id, this, theType, theName, theShape, thePredicate );
2067 GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
2068 _mapGroup[ id ] = aGroup;
2069 _groupId = 1 + _mapGroup.rbegin()->first;
2073 //================================================================================
2075 * \brief Creates a group based on an existing SMESHDS group. Group ID should be unique
2077 //================================================================================
2079 SMESH_Group* SMESH_Mesh::AddGroup (SMESHDS_GroupBase* groupDS)
2082 throw SALOME_Exception(LOCALIZED ("SMESH_Mesh::AddGroup(): NULL SMESHDS_GroupBase"));
2084 std::map <int, SMESH_Group*>::iterator i_g = _mapGroup.find( groupDS->GetID() );
2085 if ( i_g != _mapGroup.end() && i_g->second )
2087 if ( i_g->second->GetGroupDS() == groupDS )
2090 throw SALOME_Exception(LOCALIZED ("SMESH_Mesh::AddGroup() wrong ID of SMESHDS_GroupBase"));
2092 SMESH_Group* aGroup = new SMESH_Group (groupDS);
2093 _mapGroup[ groupDS->GetID() ] = aGroup;
2094 GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
2096 _groupId = 1 + _mapGroup.rbegin()->first;
2102 //================================================================================
2104 * \brief Creates SMESH_Groups for not wrapped SMESHDS_Groups
2105 * \retval bool - true if new SMESH_Groups have been created
2108 //================================================================================
2110 bool SMESH_Mesh::SynchronizeGroups()
2112 const size_t nbGroups = _mapGroup.size();
2113 const std::set<SMESHDS_GroupBase*>& groups = _meshDS->GetGroups();
2114 std::set<SMESHDS_GroupBase*>::const_iterator gIt = groups.begin();
2115 for ( ; gIt != groups.end(); ++gIt )
2117 SMESHDS_GroupBase* groupDS = (SMESHDS_GroupBase*) *gIt;
2118 _groupId = groupDS->GetID();
2119 if ( !_mapGroup.count( _groupId ))
2120 _mapGroup[_groupId] = new SMESH_Group( groupDS );
2122 if ( !_mapGroup.empty() )
2123 _groupId = 1 + _mapGroup.rbegin()->first;
2125 return nbGroups < _mapGroup.size();
2128 //================================================================================
2130 * \brief Return iterator on all existing groups
2132 //================================================================================
2134 SMESH_Mesh::GroupIteratorPtr SMESH_Mesh::GetGroups() const
2136 typedef std::map <int, SMESH_Group *> TMap;
2137 return GroupIteratorPtr( new SMDS_mapIterator<TMap>( _mapGroup ));
2140 //=============================================================================
2142 * \brief Return a group by ID
2144 //=============================================================================
2146 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID) const
2148 std::map <int, SMESH_Group*>::const_iterator id_grp = _mapGroup.find( theGroupID );
2149 if ( id_grp == _mapGroup.end() )
2151 return id_grp->second;
2155 //=============================================================================
2157 * \brief Return IDs of all groups
2159 //=============================================================================
2161 std::list<int> SMESH_Mesh::GetGroupIds() const
2163 std::list<int> anIds;
2164 std::map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin();
2165 for ( ; it != _mapGroup.end(); it++ )
2166 anIds.push_back( it->first );
2171 //================================================================================
2173 * \brief Set a caller of methods at level of CORBA API implementation.
2174 * The set upCaller will be deleted by SMESH_Mesh
2176 //================================================================================
2178 void SMESH_Mesh::SetCallUp( TCallUp* upCaller )
2180 if ( _callUp ) delete _callUp;
2184 //=============================================================================
2188 //=============================================================================
2190 bool SMESH_Mesh::RemoveGroup( const int theGroupID )
2192 if (_mapGroup.find(theGroupID) == _mapGroup.end())
2194 GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
2195 delete _mapGroup[theGroupID];
2196 _mapGroup.erase (theGroupID);
2198 _callUp->RemoveGroup( theGroupID );
2202 //=======================================================================
2203 //function : GetAncestors
2204 //purpose : return list of ancestors of theSubShape in the order
2205 // that lower dimension shapes come first.
2206 //=======================================================================
2208 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
2210 if ( _mapAncestors.Contains( theS ) )
2211 return _mapAncestors.FindFromKey( theS );
2213 static TopTools_ListOfShape emptyList;
2217 //=======================================================================
2219 //purpose : dumps contents of mesh to stream [ debug purposes ]
2220 //=======================================================================
2222 ostream& SMESH_Mesh::Dump(ostream& save)
2225 save << "========================== Dump contents of mesh ==========================" << endl << endl;
2226 save << ++clause << ") Total number of nodes: \t" << NbNodes() << endl;
2227 save << ++clause << ") Total number of edges: \t" << NbEdges() << endl;
2228 save << ++clause << ") Total number of faces: \t" << NbFaces() << endl;
2229 save << ++clause << ") Total number of polygons: \t" << NbPolygons() << endl;
2230 save << ++clause << ") Total number of volumes: \t" << NbVolumes() << endl;
2231 save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
2232 for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
2234 std::string orderStr = isQuadratic ? "quadratic" : "linear";
2235 SMDSAbs_ElementOrder order = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
2237 save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
2238 save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
2239 if ( NbFaces(order) > 0 ) {
2240 smIdType nb3 = NbTriangles(order);
2241 smIdType nb4 = NbQuadrangles(order);
2242 save << clause << ".1) Number of " << orderStr << " triangles: \t" << nb3 << endl;
2243 save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
2244 if ( nb3 + nb4 != NbFaces(order) ) {
2245 std::map<int,int> myFaceMap;
2246 SMDS_FaceIteratorPtr itFaces=_meshDS->facesIterator();
2247 while( itFaces->more( ) ) {
2248 int nbNodes = itFaces->next()->NbNodes();
2249 if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
2250 myFaceMap[ nbNodes ] = 0;
2251 myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
2253 save << clause << ".3) Faces in detail: " << endl;
2254 std::map <int,int>::iterator itF;
2255 for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
2256 save << "--> nb nodes: " << itF->first << " - nb elements:\t" << itF->second << endl;
2259 save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
2260 if ( NbVolumes(order) > 0 ) {
2261 smIdType nb8 = NbHexas(order);
2262 smIdType nb4 = NbTetras(order);
2263 smIdType nb5 = NbPyramids(order);
2264 smIdType nb6 = NbPrisms(order);
2265 save << clause << ".1) Number of " << orderStr << " hexahedrons: \t" << nb8 << endl;
2266 save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
2267 save << clause << ".3) Number of " << orderStr << " prisms: \t" << nb6 << endl;
2268 save << clause << ".4) Number of " << orderStr << " pyramids: \t" << nb5 << endl;
2269 if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
2270 std::map<int,int> myVolumesMap;
2271 SMDS_VolumeIteratorPtr itVolumes=_meshDS->volumesIterator();
2272 while( itVolumes->more( ) ) {
2273 int nbNodes = itVolumes->next()->NbNodes();
2274 if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
2275 myVolumesMap[ nbNodes ] = 0;
2276 myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
2278 save << clause << ".5) Volumes in detail: " << endl;
2279 std::map <int,int>::iterator itV;
2280 for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
2281 save << "--> nb nodes: " << itV->first << " - nb elements:\t" << itV->second << endl;
2286 save << "===========================================================================" << endl;
2290 //=======================================================================
2291 //function : GetElementType
2292 //purpose : Returns type of mesh element with certain id
2293 //=======================================================================
2295 SMDSAbs_ElementType SMESH_Mesh::GetElementType( const smIdType id, const bool iselem )
2297 return _meshDS->GetElementType( id, iselem );
2300 //=============================================================================
2302 * \brief Convert group on geometry into standalone group
2304 //=============================================================================
2306 SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID )
2308 SMESH_Group* aGroup = 0;
2309 std::map < int, SMESH_Group * >::iterator itg = _mapGroup.find( theGroupID );
2310 if ( itg == _mapGroup.end() )
2313 SMESH_Group* anOldGrp = (*itg).second;
2314 if ( !anOldGrp || !anOldGrp->GetGroupDS() )
2316 SMESHDS_GroupBase* anOldGrpDS = anOldGrp->GetGroupDS();
2318 // create new standalone group
2319 aGroup = new SMESH_Group (theGroupID, this, anOldGrpDS->GetType(), anOldGrp->GetName() );
2320 _mapGroup[theGroupID] = aGroup;
2322 SMESHDS_Group* aNewGrpDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
2323 GetMeshDS()->RemoveGroup( anOldGrpDS );
2324 GetMeshDS()->AddGroup( aNewGrpDS );
2326 // add elements (or nodes) into new created group
2327 SMDS_ElemIteratorPtr anItr = anOldGrpDS->GetElements();
2328 while ( anItr->more() )
2329 aNewGrpDS->Add( (anItr->next())->GetID() );
2332 aNewGrpDS->SetColor( anOldGrpDS->GetColor() );
2340 //=============================================================================
2342 * \brief remove submesh order from Mesh
2344 //=============================================================================
2346 void SMESH_Mesh::ClearMeshOrder()
2348 _subMeshOrder.clear();
2351 //=============================================================================
2353 * \brief remove submesh order from Mesh
2355 //=============================================================================
2357 void SMESH_Mesh::SetMeshOrder(const TListOfListOfInt& theOrder )
2359 _subMeshOrder = theOrder;
2362 //=============================================================================
2364 * \brief return submesh order if any
2366 //=============================================================================
2368 const TListOfListOfInt& SMESH_Mesh::GetMeshOrder() const
2370 return _subMeshOrder;
2373 //=============================================================================
2375 * \brief fill _mapAncestors
2377 //=============================================================================
2379 void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
2381 int desType, ancType;
2382 if ( !theShape.IsSame( GetShapeToMesh()) && theShape.ShapeType() == TopAbs_COMPOUND )
2384 // a geom group is added. Insert it into lists of ancestors before
2385 // the first ancestor more complex than group members
2386 TopoDS_Iterator subIt( theShape );
2387 if ( !subIt.More() ) return;
2388 int memberType = subIt.Value().ShapeType();
2389 for ( desType = TopAbs_VERTEX; desType >= memberType; desType-- )
2390 for (TopExp_Explorer des( theShape, TopAbs_ShapeEnum( desType )); des.More(); des.Next())
2392 if ( !_mapAncestors.Contains( des.Current() )) continue;// issue 0020982
2393 TopTools_ListOfShape& ancList = _mapAncestors.ChangeFromKey( des.Current() );
2394 TopTools_ListIteratorOfListOfShape ancIt (ancList);
2395 while ( ancIt.More() && ancIt.Value().ShapeType() >= memberType )
2397 if ( ancIt.More() ) ancList.InsertBefore( theShape, ancIt );
2398 else ancList.Append( theShape );
2401 else // else added for 52457: Addition of hypotheses is 8 time longer than meshing
2403 for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- )
2404 for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
2405 TopExp::MapShapesAndAncestors ( theShape,
2406 (TopAbs_ShapeEnum) desType,
2407 (TopAbs_ShapeEnum) ancType,
2410 // visit COMPOUNDs inside a COMPOUND that are not reachable by TopExp_Explorer
2411 if ( theShape.ShapeType() == TopAbs_COMPOUND )
2413 TopoDS_Iterator sIt(theShape);
2414 if ( sIt.More() && sIt.Value().ShapeType() == TopAbs_COMPOUND )
2415 for ( ; sIt.More(); sIt.Next() )
2416 if ( sIt.Value().ShapeType() == TopAbs_COMPOUND )
2417 fillAncestorsMap( sIt.Value() );
2421 //=============================================================================
2423 * \brief sort submeshes according to stored mesh order
2424 * \param theListToSort in out list to be sorted
2425 * \return FALSE if nothing sorted
2427 //=============================================================================
2429 bool SMESH_Mesh::SortByMeshOrder(std::vector<SMESH_subMesh*>& theListToSort) const
2431 if ( _subMeshOrder.empty() || theListToSort.size() < 2 )
2435 // collect all ordered sub-meshes in smVec as pointers
2436 // and get their positions within theListToSort
2438 std::vector<SMESH_subMesh*> smVec;
2439 typedef std::vector<SMESH_subMesh*>::iterator TPosInList;
2440 std::map< size_t, size_t > sortedPos; // index in theListToSort to order
2441 TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end();
2442 TListOfListOfInt::const_iterator listIdsIt = _subMeshOrder.begin();
2443 bool needSort = false;
2444 for( ; listIdsIt != _subMeshOrder.end(); listIdsIt++)
2446 const TListOfInt& listOfId = *listIdsIt;
2447 // convert sm ids to sm's
2449 TListOfInt::const_iterator idIt = listOfId.begin();
2450 for ( ; idIt != listOfId.end(); idIt++ )
2452 if ( SMESH_subMesh * sm = GetSubMeshContaining( *idIt ))
2454 smVec.push_back( sm );
2455 if ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->IsComplexSubmesh() )
2457 smVec.reserve( smVec.size() + sm->GetSubMeshDS()->NbSubMeshes() );
2458 SMESHDS_SubMeshIteratorPtr smdsIt = sm->GetSubMeshDS()->GetSubMeshIterator();
2459 while ( smdsIt->more() )
2461 const SMESHDS_SubMesh* smDS = smdsIt->next();
2462 if (( sm = GetSubMeshContaining( smDS->GetID() )))
2463 smVec.push_back( sm );
2468 // find smVec items in theListToSort
2469 for ( size_t i = 0; i < smVec.size(); ++i )
2471 TPosInList smPos = find( smBeg, smEnd, smVec[i] ); // position in theListToSort
2472 if ( smPos != smEnd )
2474 size_t posInList = std::distance( smBeg, smPos );
2475 size_t order = sortedPos.size();
2476 sortedPos.insert( std::make_pair( posInList, order ));
2477 if ( posInList != order )
2485 // set sm of sortedPos from theListToSort to front of orderedSM
2486 // and the rest of theListToSort to orderedSM end
2488 std::vector<SMESH_subMesh*> orderedSM;
2489 orderedSM.reserve( theListToSort.size() );
2490 orderedSM.resize( sortedPos.size() );
2493 sortedPos.insert( std::make_pair( theListToSort.size(), sortedPos.size() ));
2494 for ( const auto & pos_order : sortedPos )
2496 const size_t& posInList = pos_order.first;
2497 const size_t& order = pos_order.second;
2498 if ( order < sortedPos.size() - 1 )
2499 orderedSM[ order ] = theListToSort[ posInList ];
2501 if ( iPrev < posInList )
2502 orderedSM.insert( orderedSM.end(),
2503 theListToSort.begin() + iPrev,
2504 theListToSort.begin() + posInList );
2505 iPrev = posInList + 1;
2508 theListToSort.swap( orderedSM );
2513 //================================================================================
2515 * \brief Return true if given order of sub-meshes is OK
2517 //================================================================================
2519 bool SMESH_Mesh::IsOrderOK( const SMESH_subMesh* smBefore,
2520 const SMESH_subMesh* smAfter ) const
2522 TListOfListOfInt::const_iterator listIdsIt = _subMeshOrder.begin();
2523 for( ; listIdsIt != _subMeshOrder.end(); listIdsIt++)
2525 const TListOfInt& listOfId = *listIdsIt;
2526 int iB = -1, iA = -1, i = 0;
2527 for ( TListOfInt::const_iterator id = listOfId.begin(); id != listOfId.end(); ++id, ++i )
2529 if ( *id == smBefore->GetId() )
2535 else if ( *id == smAfter->GetId() )
2543 return true; // no order imposed to given sub-meshes
2546 //=============================================================================
2548 * \brief sort submeshes according to stored mesh order
2549 * \param theListToSort in out list to be sorted
2550 * \return FALSE if nothing sorted
2552 //=============================================================================
2554 void SMESH_Mesh::getAncestorsSubMeshes (const TopoDS_Shape& theSubShape,
2555 std::vector< SMESH_subMesh* >& theSubMeshes) const
2557 theSubMeshes.clear();
2558 TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape ));
2559 for (; it.More(); it.Next() )
2560 if ( SMESH_subMesh* sm = GetSubMeshContaining( it.Value() ))
2561 theSubMeshes.push_back(sm);
2563 // sort submeshes according to stored mesh order
2564 SortByMeshOrder( theSubMeshes );