1 // Copyright (C) 2007-2024 CEA, EDF, 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
22 // File : SMESH_Mesh_i.cxx
23 // Author : Paul RASCLE, EDF
26 #include "SMESH_Mesh_i.hxx"
28 #include "DriverMED_R_SMESHDS_Mesh.h"
29 #include "DriverMED_W_Field.h"
30 #include "DriverMED_W_SMESHDS_Mesh.h"
31 #include "MED_Factory.hxx"
32 #include "SMDS_LinearEdge.hxx"
33 #include "SMDS_EdgePosition.hxx"
34 #include "SMDS_ElemIterator.hxx"
35 #include "SMDS_FacePosition.hxx"
36 #include "SMDS_IteratorOnIterators.hxx"
37 #include "SMDS_MeshGroup.hxx"
38 #include "SMDS_SetIterator.hxx"
39 #include "SMDS_StdIterator.hxx"
40 #include "SMDS_VolumeTool.hxx"
41 #include "SMESHDS_Command.hxx"
42 #include "SMESHDS_CommandType.hxx"
43 #include "SMESHDS_Group.hxx"
44 #include "SMESHDS_GroupOnGeom.hxx"
45 #include "SMESH_Controls.hxx"
46 #include "SMESH_File.hxx"
47 #include "SMESH_Filter_i.hxx"
48 #include "SMESH_Gen_i.hxx"
49 #include "SMESH_Group.hxx"
50 #include "SMESH_Group_i.hxx"
51 #include "SMESH_Mesh.hxx"
52 #include "SMESH_MeshAlgos.hxx"
53 #include "SMESH_MeshEditor.hxx"
54 #include "SMESH_MeshEditor_i.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PreMeshInfo.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMesh_i.hxx"
60 #include "SMESH_Meshio.h"
62 #include <SALOMEDS_Attributes_wrap.hxx>
63 #include <SALOMEDS_wrap.hxx>
64 #include <Utils_ExceptHandlers.hxx>
65 #include <utilities.h>
67 #include <GEOMImpl_Types.hxx>
68 #include <GEOM_wrap.hxx>
71 #include <BRep_Builder.hxx>
72 #include <Standard_ErrorHandler.hxx>
73 #include <TColStd_MapOfInteger.hxx>
75 #include <TopExp_Explorer.hxx>
76 #include <TopTools_DataMapOfShapeShape.hxx>
77 #include <TopTools_MapIteratorOfMapOfShape.hxx>
78 #include <TopTools_MapOfShape.hxx>
79 #include <TopoDS_Compound.hxx>
86 #include <vtkUnstructuredGridWriter.h>
88 // to pass CORBA exception and TooLargeForExport exception through SMESH_TRY
89 #define SMY_OWN_CATCH \
90 catch( SALOME::SALOME_Exception& se ) { throw se; } \
91 catch( ::SMESH_Mesh::TooLargeForExport& ex ) \
92 { SALOME::ExceptionStruct se = { \
94 CORBA::string_dup(SMESH_Comment("Mesh is too large for export in format ") << ex.what()), \
95 CORBA::string_dup(SMESH_Comment("format=") << ex.what() ), 0 }; \
96 throw SALOME::SALOME_Exception( se ); }
98 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
101 using SMESH::TPythonDump;
104 int SMESH_Mesh_i::_idGenerator = 0;
106 //=============================================================================
110 //=============================================================================
112 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
114 : SALOME::GenericObj_i( thePOA )
118 _id = _idGenerator++;
121 _previewEditor = NULL;
126 //=============================================================================
130 //=============================================================================
132 SMESH_Mesh_i::~SMESH_Mesh_i()
135 map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
136 for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
137 if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
139 aGroup->UnRegister();
140 SMESH::SMESH_GroupBase_var( itGr->second );
145 map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
146 for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
147 if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
149 aSubMesh->UnRegister();
150 SMESH::SMESH_subMesh_var( itSM->second );
152 _mapSubMeshIor.clear();
154 // destroy hypotheses. _mapHypo contains all hyps ever been assigned
155 map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
156 for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
157 if ( SMESH_Hypothesis_i* hyp_i = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
158 if ( SMESH_Hypothesis * smHyp = _impl->GetHypothesis( itH->first ))
159 if ( _impl->GetMeshDS()->IsUsedHypothesis( smHyp ))
162 SMESH::SMESH_Hypothesis_var( itH->second ); // decref CORBA object
166 // clear cached shapes if no more meshes remain; (the cache is blame,
167 // together with publishing, of spent time increasing in issue 22874)
168 if ( _impl->NbMeshes() == 1 )
169 _gen_i->GetShapeReader()->ClearClientBuffer();
171 delete _editor; _editor = NULL;
172 delete _previewEditor; _previewEditor = NULL;
173 delete _impl; _impl = NULL;
174 delete _preMeshInfo; _preMeshInfo = NULL;
177 //=============================================================================
181 * Associate <this> mesh with <theShape> and put a reference
182 * to <theShape> into the current study;
183 * the previous shape is substituted by the new one.
185 //=============================================================================
187 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
189 Unexpect aCatch(SALOME_SalomeException);
191 _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
193 catch(SALOME_Exception & S_ex) {
194 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
196 // to track changes of GEOM groups
197 SMESH::SMESH_Mesh_var mesh = _this();
198 addGeomGroupData( theShapeObject, mesh );
199 if ( !CORBA::is_nil( theShapeObject ))
200 _mainShapeTick = theShapeObject->GetTick();
203 //================================================================================
205 * \brief Return true if mesh has a shape to build a shape on
207 //================================================================================
209 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
211 Unexpect aCatch(SALOME_SalomeException);
214 res = _impl->HasShapeToMesh();
216 catch(SALOME_Exception & S_ex) {
217 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
222 //================================================================================
224 * \brief Return the shape to mesh
226 //================================================================================
228 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
230 Unexpect aCatch(SALOME_SalomeException);
231 GEOM::GEOM_Object_var aShapeObj;
233 TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
236 aShapeObj = _gen_i->ShapeToGeomObject( S );
237 if ( aShapeObj->_is_nil() )
239 // S was removed from GEOM_Client by newGroupShape() called by other mesh;
240 // find GEOM_Object by entry (IPAL52735)
241 list<TGeomGroupData>::iterator data = _geomGroupData.begin();
242 for ( ; data != _geomGroupData.end(); ++data )
243 if ( data->_smeshObject->_is_equivalent( _this() ))
245 SALOMEDS::SObject_wrap so = _gen_i->getStudyServant()->FindObjectID( data->_groupEntry.c_str() );
246 CORBA::Object_var obj = _gen_i->SObjectToObject( so );
247 aShapeObj = GEOM::GEOM_Object::_narrow( obj );
253 catch(SALOME_Exception & S_ex) {
254 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
256 return aShapeObj._retn();
259 //================================================================================
261 * \brief Return false if the mesh is not yet fully loaded from the study file
263 //================================================================================
265 CORBA::Boolean SMESH_Mesh_i::IsLoaded()
267 Unexpect aCatch(SALOME_SalomeException);
268 return !_preMeshInfo;
271 //================================================================================
273 * \brief Load full mesh data from the study file
275 //================================================================================
277 void SMESH_Mesh_i::Load()
279 Unexpect aCatch(SALOME_SalomeException);
281 _preMeshInfo->FullLoadFromFile();
284 //================================================================================
286 * \brief Remove all nodes and elements
288 //================================================================================
290 void SMESH_Mesh_i::Clear()
292 Unexpect aCatch(SALOME_SalomeException);
294 _preMeshInfo->ForgetOrLoad(); // load in case if !HasShapeToMesh()
298 //CheckGeomGroupModif(); // issue 20145
300 catch(SALOME_Exception & S_ex) {
301 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
304 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".Clear()";
306 SMESH::SMESH_Mesh_var mesh = _this();
307 _gen_i->UpdateIcons( mesh );
310 //================================================================================
312 * \brief Remove all nodes and elements for indicated shape
314 //================================================================================
316 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
318 Unexpect aCatch(SALOME_SalomeException);
320 _preMeshInfo->FullLoadFromFile();
323 _impl->ClearSubMesh( ShapeID );
325 catch(SALOME_Exception & S_ex) {
326 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
328 _impl->GetMeshDS()->Modified();
330 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ClearSubMesh( " << ShapeID << " )";
333 //=============================================================================
335 * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
337 //=============================================================================
339 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
341 SMESH::DriverMED_ReadStatus res;
344 case DriverMED_R_SMESHDS_Mesh::DRS_OK:
345 res = SMESH::DRS_OK; break;
346 case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
347 res = SMESH::DRS_EMPTY; break;
348 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
349 res = SMESH::DRS_WARN_RENUMBER; break;
350 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
351 res = SMESH::DRS_WARN_SKIP_ELEM; break;
352 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_DESCENDING:
353 res = SMESH::DRS_WARN_DESCENDING; break;
354 case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
356 res = SMESH::DRS_FAIL; break;
361 //=============================================================================
363 * Convert ::SMESH_ComputeError to SMESH::ComputeError
365 //=============================================================================
367 static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr )
369 SMESH::ComputeError_var errVar = new SMESH::ComputeError();
370 errVar->subShapeID = -1;
371 errVar->hasBadMesh = false;
373 if ( !errorPtr || errorPtr->IsOK() )
375 errVar->code = SMESH::COMPERR_OK;
379 errVar->code = ConvertDriverMEDReadStatus( errorPtr->myName );
380 errVar->comment = errorPtr->myComment.c_str();
382 return errVar._retn();
385 //=============================================================================
389 * Import mesh data from MED file
391 //=============================================================================
393 SMESH::DriverMED_ReadStatus
394 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
396 Unexpect aCatch(SALOME_SalomeException);
399 status = _impl->MEDToMesh( theFileName, theMeshName );
401 catch( SALOME_Exception& S_ex ) {
402 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
405 THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
408 CreateGroupServants();
410 int major, minor, release;
411 major = minor = release = 0;
412 MED::GetMEDVersion(theFileName, major, minor, release);
413 _medFileInfo = new SMESH::MedFileInfo();
414 _medFileInfo->fileName = theFileName;
415 _medFileInfo->fileSize = 0;
416 _medFileInfo->major = major;
417 _medFileInfo->minor = minor;
418 _medFileInfo->release = release;
419 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
421 return ConvertDriverMEDReadStatus(status);
424 //================================================================================
426 * \brief Import mesh data from the CGNS file
428 //================================================================================
430 SMESH::DriverMED_ReadStatus SMESH_Mesh_i::ImportCGNSFile( const char* theFileName,
431 const int theMeshIndex,
432 std::string& theMeshName )
434 Unexpect aCatch(SALOME_SalomeException);
437 status = _impl->CGNSToMesh( theFileName, theMeshIndex, theMeshName );
439 catch( SALOME_Exception& S_ex ) {
440 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
443 THROW_SALOME_CORBA_EXCEPTION("ImportCGNSFile(): unknown exception", SALOME::BAD_PARAM);
446 CreateGroupServants();
448 _medFileInfo = new SMESH::MedFileInfo();
449 _medFileInfo->fileName = theFileName;
450 _medFileInfo->major = 0;
451 _medFileInfo->minor = 0;
452 _medFileInfo->release = 0;
453 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
455 return ConvertDriverMEDReadStatus(status);
458 //================================================================================
460 * \brief Return string representation of a MED file version comprising nbDigits
462 //================================================================================
464 char* SMESH_Mesh_i::GetVersionString(CORBA::Long minor, CORBA::Short nbDigits)
466 string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(minor, nbDigits);
467 return CORBA::string_dup( ver.c_str() );
470 //================================================================================
472 * Return the list of med versions compatibles for write/append,
473 * encoded in 10*major+minor (for instance, code for med 3.2.1 is 32)
475 //================================================================================
477 SMESH::long_array* SMESH_Mesh_i::GetMEDVersionsCompatibleForAppend()
479 SMESH::long_array_var aResult = new SMESH::long_array();
480 std::vector<int> mvok = MED::GetMEDVersionsAppendCompatible();
481 long nbver = mvok.size();
482 aResult->length( nbver );
483 for ( int i = 0; i < nbver; i++ )
484 aResult[i] = mvok[i];
485 return aResult._retn();
488 //=============================================================================
492 * Import mesh data from MED file
494 //=============================================================================
496 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
500 // Read mesh with name = <theMeshName> into SMESH_Mesh
501 _impl->UNVToMesh( theFileName );
503 CreateGroupServants();
505 _medFileInfo = new SMESH::MedFileInfo();
506 _medFileInfo->fileName = theFileName;
507 _medFileInfo->major = 0;
508 _medFileInfo->minor = 0;
509 _medFileInfo->release = 0;
510 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
512 SMESH_CATCH( SMESH::throwCorbaException );
517 //=============================================================================
521 * Import mesh data from STL file
523 //=============================================================================
525 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
529 // Read mesh with name = <theMeshName> into SMESH_Mesh
530 std::string name = _impl->STLToMesh( theFileName );
533 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( _this() );
534 _gen_i->SetName( meshSO, name.c_str() );
536 _medFileInfo = new SMESH::MedFileInfo();
537 _medFileInfo->fileName = theFileName;
538 _medFileInfo->major = 0;
539 _medFileInfo->minor = 0;
540 _medFileInfo->release = 0;
541 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
543 SMESH_CATCH( SMESH::throwCorbaException );
548 //================================================================================
550 * \brief Function used in SMESH_CATCH by ImportGMFFile()
552 //================================================================================
556 SMESH_ComputeErrorPtr exceptionToComputeError(const char* excText)
558 return SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, excText );
562 //================================================================================
564 * \brief Import data from a GMF file and return an error description
566 //================================================================================
568 SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName,
569 bool theMakeRequiredGroups )
571 SMESH_ComputeErrorPtr error;
574 #define SMESH_CAUGHT error =
577 error = _impl->GMFToMesh( theFileName, theMakeRequiredGroups );
579 _medFileInfo = new SMESH::MedFileInfo();
580 _medFileInfo->fileName = theFileName;
581 _medFileInfo->major = 0;
582 _medFileInfo->minor = 0;
583 _medFileInfo->release = 0;
584 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
586 SMESH_CATCH( exceptionToComputeError );
590 CreateGroupServants();
592 return ConvertComputeError( error );
595 //=============================================================================
597 * \brief Convert SMESH_Hypothesis::Hypothesis_Status into SMESH::Hypothesis_Status
599 //=============================================================================
601 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
603 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
604 (SMESH_Hypothesis::Hypothesis_Status theStatus)
607 RETURNCASE( HYP_OK );
608 RETURNCASE( HYP_MISSING );
609 RETURNCASE( HYP_CONCURRENT );
610 RETURNCASE( HYP_BAD_PARAMETER );
611 RETURNCASE( HYP_HIDDEN_ALGO );
612 RETURNCASE( HYP_HIDING_ALGO );
613 RETURNCASE( HYP_UNKNOWN_FATAL );
614 RETURNCASE( HYP_INCOMPATIBLE );
615 RETURNCASE( HYP_NOTCONFORM );
616 RETURNCASE( HYP_ALREADY_EXIST );
617 RETURNCASE( HYP_BAD_DIM );
618 RETURNCASE( HYP_BAD_SUBSHAPE );
619 RETURNCASE( HYP_BAD_GEOMETRY );
620 RETURNCASE( HYP_NEED_SHAPE );
621 RETURNCASE( HYP_INCOMPAT_HYPS );
624 return SMESH::HYP_UNKNOWN_FATAL;
627 //=============================================================================
631 * Call internal addHypothesis() and then add a reference to <anHyp> under
632 * the SObject actually having a reference to <aSubShape>.
633 * NB: For this method to work, it is necessary to add a reference to sub-shape first.
635 //=============================================================================
637 SMESH::Hypothesis_Status
638 SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShape,
639 SMESH::SMESH_Hypothesis_ptr anHyp,
640 CORBA::String_out anErrorText)
642 Unexpect aCatch(SALOME_SalomeException);
644 const smIdType prevNbMeshEnt = NbNodes() + NbElements();
647 _preMeshInfo->ForgetOrLoad();
650 SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
651 anErrorText = error.c_str();
653 SMESH::SMESH_Mesh_var mesh( _this() );
654 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
656 _gen_i->AddHypothesisToShape( mesh, aSubShape, anHyp );
658 //int newNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements();
659 if ( prevNbMeshEnt > 0 /*newNbMeshEnt != prevNbMeshEnt*/ )
660 _gen_i->UpdateIcons( mesh );
662 MESSAGE( " AddHypothesis(): status = " << status );
664 // Update Python script
665 TPythonDump() << "status = " << mesh << ".AddHypothesis( "
666 << aSubShape << ", " << anHyp << " )";
668 return ConvertHypothesisStatus(status);
671 //================================================================================
673 * \brief Create a sub-mesh and add a hypothesis to it
675 //================================================================================
677 SMESH_Hypothesis::Hypothesis_Status
678 SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShape,
679 SMESH::SMESH_Hypothesis_ptr anHyp,
680 std::string* anErrorText)
682 MESSAGE("addHypothesis");
684 if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
685 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
687 if (CORBA::is_nil( anHyp ))
688 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",SALOME::BAD_PARAM);
690 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
693 TopoDS_Shape myLocSubShape;
694 //use PseudoShape in case if mesh has no shape
696 myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
698 myLocSubShape = _impl->GetShapeToMesh();
700 const int hypId = anHyp->GetId();
702 status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
703 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
705 _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
707 // assure there is a corresponding submesh
708 if ( !_impl->IsMainShape( myLocSubShape )) {
709 int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
710 if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
711 SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
714 else if ( anErrorText )
716 *anErrorText = error;
719 catch(SALOME_Exception & S_ex)
721 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
726 //================================================================================
728 * \brief Un-assign a hypothesis from a sub-mesh dedicate to the given sub-shape
730 //================================================================================
732 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
733 SMESH::SMESH_Hypothesis_ptr anHyp)
735 Unexpect aCatch(SALOME_SalomeException);
737 _preMeshInfo->ForgetOrLoad();
739 SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
740 SMESH::SMESH_Mesh_var mesh = _this();
742 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
744 _gen_i->RemoveHypothesisFromShape( mesh, aSubShape, anHyp );
745 _gen_i->UpdateIcons( mesh );
747 // Update Python script
748 if(_impl->HasShapeToMesh())
749 TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
750 << aSubShape << ", " << anHyp << " )";
752 TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
755 return ConvertHypothesisStatus(status);
758 //=============================================================================
760 * \brief Un-assign a hypothesis from a sub-mesh dedicate to the given sub-shape
762 //=============================================================================
764 SMESH_Hypothesis::Hypothesis_Status
765 SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShape,
766 SMESH::SMESH_Hypothesis_ptr anHyp)
768 MESSAGE("removeHypothesis()");
770 if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
771 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
773 if (CORBA::is_nil( anHyp ))
774 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
777 _preMeshInfo->ForgetOrLoad();
779 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
782 TopoDS_Shape myLocSubShape;
783 //use PseudoShape in case if mesh has no shape
784 if( _impl->HasShapeToMesh() )
785 myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
787 myLocSubShape = _impl->GetShapeToMesh();
789 const int hypId = anHyp->GetId();
790 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
791 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
793 // _mapHypo.erase( hypId ); EAP: hyp can be used on many sub-shapes
797 catch(SALOME_Exception & S_ex)
799 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
804 //================================================================================
806 * \brief Return hypotheses assigned to a given sub-shape
808 //================================================================================
810 SMESH::ListOfHypothesis *
811 SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
813 Unexpect aCatch(SALOME_SalomeException);
814 MESSAGE("GetHypothesisList");
815 if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
816 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
818 SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
821 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
822 if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
823 myLocSubShape = _impl->GetShapeToMesh();
824 const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
825 int i = 0, n = aLocalList.size();
828 list<const SMESHDS_Hypothesis*>::const_iterator aHyp = aLocalList.begin();
829 std::map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id_hypptr;
830 for ( ; i < n && aHyp != aLocalList.end(); aHyp++ )
832 id_hypptr = _mapHypo.find( (*aHyp)->GetID() );
833 if ( id_hypptr != _mapHypo.end() )
834 aList[i++] = SMESH::SMESH_Hypothesis::_narrow( id_hypptr->second );
838 catch(SALOME_Exception & S_ex) {
839 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
842 return aList._retn();
845 //================================================================================
847 * \brief Return sub-meshes
849 //================================================================================
851 SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes()
853 Unexpect aCatch(SALOME_SalomeException);
854 MESSAGE("GetSubMeshes");
856 SMESH::submesh_array_var aList = new SMESH::submesh_array();
859 TPythonDump aPythonDump;
860 if ( !_mapSubMeshIor.empty() )
864 aList->length( _mapSubMeshIor.size() );
866 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.begin();
867 for ( ; it != _mapSubMeshIor.end(); it++ ) {
868 if ( CORBA::is_nil( it->second )) continue;
869 aList[i++] = SMESH::SMESH_subMesh::_duplicate( it->second );
871 if (i > 1) aPythonDump << ", ";
872 aPythonDump << it->second;
876 catch(SALOME_Exception & S_ex) {
877 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
880 // Update Python script
881 if ( !_mapSubMeshIor.empty() )
882 aPythonDump << " ] = " << SMESH::SMESH_Mesh_var( _this() ) << ".GetSubMeshes()";
884 return aList._retn();
887 //================================================================================
889 * \brief Create and return a sub-mesh on the given sub-shape
891 //================================================================================
893 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
894 const char* theName )
896 Unexpect aCatch(SALOME_SalomeException);
897 if (CORBA::is_nil(aSubShape))
898 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
900 SMESH::SMESH_subMesh_var subMesh;
901 SMESH::SMESH_Mesh_var aMesh = _this();
903 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
905 //Get or Create the SMESH_subMesh object implementation
907 TopoDS_Iterator it( myLocSubShape );
908 int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
909 bool isValidSub = ( subMeshId || _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape ));
910 if ( isValidSub && myLocSubShape.ShapeType() == TopAbs_COMPOUND )
911 isValidSub = !it.Value().IsSame( _impl->GetShapeToMesh() );
915 THROW_SALOME_CORBA_EXCEPTION("Not a sub-shape of the main shape", SALOME::BAD_PARAM);
917 subMesh = getSubMesh( subMeshId );
919 // create a new subMesh object servant if there is none for the shape
920 if ( subMesh->_is_nil() )
921 subMesh = createSubMesh( aSubShape );
922 if ( _gen_i->CanPublishInStudy( subMesh ))
924 SALOMEDS::SObject_wrap aSO =
925 _gen_i->PublishSubMesh( aMesh, subMesh, aSubShape, theName );
926 if ( !aSO->_is_nil()) {
927 // Update Python script
928 TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
929 << aSubShape << ", '" << theName << "' )";
933 catch(SALOME_Exception & S_ex) {
934 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
936 return subMesh._retn();
939 //================================================================================
941 * \brief Remove a sub-mesh
943 //================================================================================
945 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
949 if ( theSubMesh->_is_nil() )
952 GEOM::GEOM_Object_var aSubShape;
953 // Remove submesh's SObject
954 SALOMEDS::SObject_wrap anSO = _gen_i->ObjectToSObject( theSubMesh );
955 if ( !anSO->_is_nil() ) {
956 long aTag = SMESH_Gen_i::GetRefOnShapeTag();
957 SALOMEDS::SObject_wrap anObj, aRef;
958 if ( anSO->FindSubObject( aTag, anObj.inout() ) &&
959 anObj->ReferencedObject( aRef.inout() ))
961 CORBA::Object_var obj = aRef->GetObject();
962 aSubShape = GEOM::GEOM_Object::_narrow( obj );
964 // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
965 // aSubShape = theSubMesh->GetSubShape();
967 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
968 builder->RemoveObjectWithChildren( anSO );
970 // Update Python script
971 TPythonDump() << SMESH::SMESH_Mesh_var( _this() ) << ".RemoveSubMesh( " << anSO << " )";
974 if ( removeSubMesh( theSubMesh, aSubShape.in() ))
976 _preMeshInfo->ForgetOrLoad();
978 SMESH_CATCH( SMESH::throwCorbaException );
981 //================================================================================
983 * \brief Create a standalone group
985 //================================================================================
987 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
988 const char* theName )
990 Unexpect aCatch(SALOME_SalomeException);
992 _preMeshInfo->FullLoadFromFile();
994 SMESH::SMESH_Group_var aNewGroup =
995 SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
997 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
999 SMESH::SMESH_Mesh_var mesh = _this();
1000 SALOMEDS::SObject_wrap aSO =
1001 _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName);
1002 if ( !aSO->_is_nil())
1003 // Update Python script
1004 TPythonDump() << aSO << " = " << mesh << ".CreateGroup( "
1005 << theElemType << ", '" << theName << "' )";
1007 return aNewGroup._retn();
1010 //================================================================================
1012 * \brief Create a group based on the given geometry
1014 //================================================================================
1016 SMESH::SMESH_GroupOnGeom_ptr
1017 SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType theElemType,
1018 const char* theName,
1019 GEOM::GEOM_Object_ptr theGeomObj)
1021 Unexpect aCatch(SALOME_SalomeException);
1023 _preMeshInfo->FullLoadFromFile();
1025 SMESH::SMESH_GroupOnGeom_var aNewGroup;
1027 TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
1028 if ( !aShape.IsNull() )
1031 SMESH::SMESH_GroupOnGeom::_narrow( createGroup( theElemType, theName, /*id=*/-1, aShape ));
1033 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1035 SMESH::SMESH_Mesh_var mesh = _this();
1036 SALOMEDS::SObject_wrap aSO =
1037 _gen_i->PublishGroup( mesh, aNewGroup, theGeomObj, theName );
1038 if ( !aSO->_is_nil())
1039 TPythonDump() << aSO << " = " << mesh << ".CreateGroupFromGEOM( "
1040 << theElemType << ", '" << theName << "', " << theGeomObj << " )";
1044 return aNewGroup._retn();
1047 //================================================================================
1049 * \brief Creates a group whose contents is defined by filter
1050 * \param theElemType - group type
1051 * \param theName - group name
1052 * \param theFilter - the filter
1053 * \retval SMESH::SMESH_GroupOnFilter_ptr - group defined by filter
1055 //================================================================================
1057 SMESH::SMESH_GroupOnFilter_ptr
1058 SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
1059 const char* theName,
1060 SMESH::Filter_ptr theFilter )
1062 Unexpect aCatch(SALOME_SalomeException);
1064 _preMeshInfo->FullLoadFromFile();
1066 if ( CORBA::is_nil( theFilter ))
1067 THROW_SALOME_CORBA_EXCEPTION("NULL filter", SALOME::BAD_PARAM);
1069 SMESH_PredicatePtr predicate = SMESH_GroupOnFilter_i::GetPredicate( theFilter );
1071 THROW_SALOME_CORBA_EXCEPTION("Invalid filter", SALOME::BAD_PARAM);
1073 SMESH::SMESH_GroupOnFilter_var aNewGroup = SMESH::SMESH_GroupOnFilter::_narrow
1074 ( createGroup( theElemType, theName, /*id=*/-1, TopoDS_Shape(), predicate ));
1077 if ( !aNewGroup->_is_nil() )
1078 aNewGroup->SetFilter( theFilter );
1080 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1082 SMESH::SMESH_Mesh_var mesh = _this();
1083 SALOMEDS::SObject_wrap aSO =
1084 _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName );
1086 if ( !aSO->_is_nil())
1087 pd << aSO << " = " << mesh << ".CreateGroupFromFilter( "
1088 << theElemType << ", '" << theName << "', " << theFilter << " )";
1090 return aNewGroup._retn();
1093 //================================================================================
1095 * \brief Remove a group
1097 //================================================================================
1099 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
1101 if ( theGroup->_is_nil() )
1106 SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
1110 if ( aGroup->GetMeshServant() != this )
1111 THROW_SALOME_CORBA_EXCEPTION( "RemoveGroup(): group does not belong to this mesh",
1112 SALOME::BAD_PARAM );
1114 SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( theGroup );
1115 if ( !aGroupSO->_is_nil() )
1117 // Update Python script
1118 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroup( " << aGroupSO << " )";
1120 // Remove group's SObject
1121 SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->NewBuilder();
1122 builder->RemoveObjectWithChildren( aGroupSO );
1124 aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
1126 // Remove the group from SMESH data structures
1127 removeGroup( aGroup->GetLocalID() );
1129 SMESH_CATCH( SMESH::throwCorbaException );
1132 //=============================================================================
1134 * Remove group with its contents
1136 //=============================================================================
1138 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
1142 _preMeshInfo->FullLoadFromFile();
1144 if ( theGroup->_is_nil() )
1147 SMESH_GroupBase_i* groupImpl = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup );
1148 if ( !groupImpl || groupImpl->GetMeshServant() != this )
1149 THROW_SALOME_CORBA_EXCEPTION( "RemoveGroupWithContents(): group does not belong to this mesh",
1152 vector<smIdType> nodeIds; // to remove nodes becoming free
1153 bool isNodal = ( theGroup->GetType() == SMESH::NODE );
1154 if ( !isNodal && !theGroup->IsEmpty() )
1156 SMESH::smIdType elemID = theGroup->GetID( 1 );
1157 int nbElemNodes = GetElemNbNodes( elemID );
1158 if ( nbElemNodes > 0 )
1159 nodeIds.reserve( theGroup->Size() * nbElemNodes );
1162 // Retrieve contents
1163 SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );
1164 SMDS_ElemIteratorPtr elemIt = GetElements( idSrc, theGroup->GetType() );
1165 SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > elemBeg( elemIt ), elemEnd;
1166 std::vector< const SMDS_MeshElement* > elems( theGroup->Size() );
1167 elems.assign( elemBeg, elemEnd );
1169 TPythonDump pyDump; // Suppress dump from RemoveGroup()
1172 RemoveGroup( theGroup );
1175 for ( size_t i = 0; i < elems.size(); ++i )
1177 // if ( !_impl->GetMeshDS()->Contains( elems[i] ))
1181 for ( SMDS_ElemIteratorPtr nIt = elems[i]->nodesIterator(); nIt->more(); )
1182 nodeIds.push_back( nIt->next()->GetID() );
1184 _impl->GetMeshDS()->RemoveFreeElement( elems[i], /*sm=*/0 );
1188 _impl->GetMeshDS()->RemoveElement( elems[i] );
1192 // Remove free nodes
1193 for ( size_t i = 0 ; i < nodeIds.size(); ++i )
1194 if ( const SMDS_MeshNode* n = _impl->GetMeshDS()->FindNode( nodeIds[i] ))
1195 if ( n->NbInverseElements() == 0 )
1196 _impl->GetMeshDS()->RemoveFreeNode( n, /*sm=*/0 );
1198 _impl->GetMeshDS()->Modified();
1199 _impl->SetIsModified( true );
1201 // Update Python script (theGroup must be alive for this)
1202 pyDump << SMESH::SMESH_Mesh_var(_this())
1203 << ".RemoveGroupWithContents( " << theGroup << " )";
1205 SMESH_CATCH( SMESH::throwCorbaException );
1208 //================================================================================
1210 * \brief Get the list of groups existing in the mesh
1211 * \retval SMESH::ListOfGroups * - list of groups
1213 //================================================================================
1215 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups()
1217 Unexpect aCatch(SALOME_SalomeException);
1218 MESSAGE("GetGroups");
1220 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
1223 TPythonDump aPythonDump;
1224 if ( !_mapGroups.empty() )
1226 aPythonDump << "[ ";
1228 aList->length( _mapGroups.size() );
1230 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
1231 for ( ; it != _mapGroups.end(); it++ ) {
1232 if ( CORBA::is_nil( it->second )) continue;
1233 aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
1235 if (i > 1) aPythonDump << ", ";
1236 aPythonDump << it->second;
1240 catch(SALOME_Exception & S_ex) {
1241 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1243 aPythonDump << " ] = " << SMESH::SMESH_Mesh_var(_this()) << ".GetGroups()";
1245 return aList._retn();
1248 //=============================================================================
1250 * Get number of groups existing in the mesh
1252 //=============================================================================
1254 CORBA::Long SMESH_Mesh_i::NbGroups()
1256 Unexpect aCatch(SALOME_SalomeException);
1257 return _mapGroups.size();
1260 //=============================================================================
1262 * New group including all mesh elements present in initial groups is created.
1264 //=============================================================================
1266 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1267 SMESH::SMESH_GroupBase_ptr theGroup2,
1268 const char* theName )
1270 SMESH::SMESH_Group_var aResGrp;
1274 _preMeshInfo->FullLoadFromFile();
1276 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1277 THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): NULL Group",
1279 if ( theGroup1->GetType() != theGroup2->GetType() )
1280 THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): different group types",
1285 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1286 if ( aResGrp->_is_nil() )
1287 return SMESH::SMESH_Group::_nil();
1289 aResGrp->AddFrom( theGroup1 );
1290 aResGrp->AddFrom( theGroup2 );
1292 // Update Python script
1293 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this())
1294 << ".UnionGroups( " << theGroup1 << ", " << theGroup2 << ", '" << theName << "' )";
1296 SMESH_CATCH( SMESH::throwCorbaException );
1298 return aResGrp._retn();
1301 //=============================================================================
1303 * \brief New group including all mesh elements present in initial groups is created.
1304 * \param theGroups list of groups
1305 * \param theName name of group to be created
1306 * \return pointer to the new group
1308 //=============================================================================
1310 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
1311 const char* theName )
1313 SMESH::SMESH_Group_var aResGrp;
1316 _preMeshInfo->FullLoadFromFile();
1319 return SMESH::SMESH_Group::_nil();
1324 SMESH::ElementType aType = SMESH::ALL;
1325 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1327 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1328 if ( CORBA::is_nil( aGrp ) )
1330 if ( aType == SMESH::ALL )
1331 aType = aGrp->GetType();
1332 else if ( aType != aGrp->GetType() )
1333 THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1336 if ( aType == SMESH::ALL )
1337 return SMESH::SMESH_Group::_nil();
1342 aResGrp = CreateGroup( aType, theName );
1343 if ( aResGrp->_is_nil() )
1344 return SMESH::SMESH_Group::_nil();
1346 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".UnionListOfGroups([ ";
1347 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1349 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1350 if ( !CORBA::is_nil( aGrp ) )
1352 aResGrp->AddFrom( aGrp );
1353 if ( g > 0 ) pyDump << ", ";
1357 pyDump << " ], '" << theName << "' )";
1359 SMESH_CATCH( SMESH::throwCorbaException );
1361 return aResGrp._retn();
1364 //=============================================================================
1366 * New group is created. All mesh elements that are
1367 * present in both initial groups are added to the new one.
1369 //=============================================================================
1371 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1372 SMESH::SMESH_GroupBase_ptr theGroup2,
1373 const char* theName )
1375 SMESH::SMESH_Group_var aResGrp;
1380 _preMeshInfo->FullLoadFromFile();
1382 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1383 THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): NULL Group",
1385 if ( theGroup1->GetType() != theGroup2->GetType() )
1386 THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): different group types",
1390 // Create Intersection
1391 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1392 if ( aResGrp->_is_nil() )
1393 return aResGrp._retn();
1395 SMESHDS_GroupBase* groupDS1 = 0;
1396 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1397 groupDS1 = grp_i->GetGroupDS();
1399 SMESHDS_GroupBase* groupDS2 = 0;
1400 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1401 groupDS2 = grp_i->GetGroupDS();
1403 SMESHDS_Group* resGroupDS = 0;
1404 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1405 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1407 if ( groupDS1 && groupDS2 && resGroupDS && !groupDS2->IsEmpty() )
1409 SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1410 while ( elemIt1->more() )
1412 const SMDS_MeshElement* e = elemIt1->next();
1413 if ( groupDS2->Contains( e ))
1414 resGroupDS->SMDSGroup().Add( e );
1417 // Update Python script
1418 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".IntersectGroups( "
1419 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1421 SMESH_CATCH( SMESH::throwCorbaException );
1423 return aResGrp._retn();
1426 //=============================================================================
1428 \brief Intersect list of groups. New group is created. All mesh elements that
1429 are present in all initial groups simultaneously are added to the new one.
1430 \param theGroups list of groups
1431 \param theName name of group to be created
1432 \return pointer on the group
1434 //=============================================================================
1436 SMESH::SMESH_Group_ptr
1437 SMESH_Mesh_i::IntersectListOfGroups(const SMESH::ListOfGroups& theGroups,
1438 const char* theName )
1440 SMESH::SMESH_Group_var aResGrp;
1445 _preMeshInfo->FullLoadFromFile();
1448 return SMESH::SMESH_Group::_nil();
1450 // check types and get SMESHDS_GroupBase's
1451 SMESH::ElementType aType = SMESH::ALL;
1452 vector< SMESHDS_GroupBase* > groupVec;
1453 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1455 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1456 if ( CORBA::is_nil( aGrp ) )
1458 if ( aType == SMESH::ALL )
1459 aType = aGrp->GetType();
1460 else if ( aType != aGrp->GetType() )
1461 THROW_SALOME_CORBA_EXCEPTION("IntersectListOfGroups(): different group types",
1464 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1465 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1467 if ( grpDS->IsEmpty() )
1472 groupVec.push_back( grpDS );
1475 if ( aType == SMESH::ALL ) // all groups are nil
1476 return SMESH::SMESH_Group::_nil();
1481 aResGrp = CreateGroup( aType, theName );
1483 SMESHDS_Group* resGroupDS = 0;
1484 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1485 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1486 if ( !resGroupDS || groupVec.empty() )
1487 return aResGrp._retn();
1490 size_t i, nb = groupVec.size();
1491 SMDS_ElemIteratorPtr elemIt1 = groupVec[0]->GetElements();
1492 while ( elemIt1->more() )
1494 const SMDS_MeshElement* e = elemIt1->next();
1496 for ( i = 1; ( i < nb && inAll ); ++i )
1497 inAll = groupVec[i]->Contains( e );
1500 resGroupDS->SMDSGroup().Add( e );
1503 // Update Python script
1504 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1505 << ".IntersectListOfGroups( " << theGroups << ", '" << theName << "' )";
1507 SMESH_CATCH( SMESH::throwCorbaException );
1509 return aResGrp._retn();
1512 //=============================================================================
1514 * New group is created. All mesh elements that are present in
1515 * a main group but is not present in a tool group are added to the new one
1517 //=============================================================================
1519 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1520 SMESH::SMESH_GroupBase_ptr theGroup2,
1521 const char* theName )
1523 SMESH::SMESH_Group_var aResGrp;
1528 _preMeshInfo->FullLoadFromFile();
1530 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1531 THROW_SALOME_CORBA_EXCEPTION("CutGroups(): NULL Group",
1533 if ( theGroup1->GetType() != theGroup2->GetType() )
1534 THROW_SALOME_CORBA_EXCEPTION("CutGroups(): different group types",
1538 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1539 if ( aResGrp->_is_nil() )
1540 return aResGrp._retn();
1542 SMESHDS_GroupBase* groupDS1 = 0;
1543 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1544 groupDS1 = grp_i->GetGroupDS();
1546 SMESHDS_GroupBase* groupDS2 = 0;
1547 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1548 groupDS2 = grp_i->GetGroupDS();
1550 SMESHDS_Group* resGroupDS = 0;
1551 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1552 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1554 if ( groupDS1 && groupDS2 && resGroupDS )
1556 SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1557 while ( elemIt1->more() )
1559 const SMDS_MeshElement* e = elemIt1->next();
1560 if ( !groupDS2->Contains( e ))
1561 resGroupDS->SMDSGroup().Add( e );
1564 // Update Python script
1565 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".CutGroups( "
1566 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1568 SMESH_CATCH( SMESH::throwCorbaException );
1570 return aResGrp._retn();
1573 //=============================================================================
1575 \brief Cut lists of groups. New group is created. All mesh elements that are
1576 present in main groups but do not present in tool groups are added to the new one
1577 \param theMainGroups list of main groups
1578 \param theToolGroups list of tool groups
1579 \param theName name of group to be created
1580 \return pointer on the group
1582 //=============================================================================
1584 SMESH::SMESH_Group_ptr
1585 SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
1586 const SMESH::ListOfGroups& theToolGroups,
1587 const char* theName )
1589 SMESH::SMESH_Group_var aResGrp;
1594 _preMeshInfo->FullLoadFromFile();
1597 return SMESH::SMESH_Group::_nil();
1599 // check types and get SMESHDS_GroupBase's
1600 SMESH::ElementType aType = SMESH::ALL;
1601 vector< SMESHDS_GroupBase* > toolGroupVec;
1602 vector< SMDS_ElemIteratorPtr > mainIterVec;
1604 for ( int g = 0, n = theMainGroups.length(); g < n; g++ )
1606 SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1607 if ( CORBA::is_nil( aGrp ) )
1609 if ( aType == SMESH::ALL )
1610 aType = aGrp->GetType();
1611 else if ( aType != aGrp->GetType() )
1612 THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1614 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1615 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1616 if ( !grpDS->IsEmpty() )
1617 mainIterVec.push_back( grpDS->GetElements() );
1619 if ( aType == SMESH::ALL ) // all main groups are nil
1620 return SMESH::SMESH_Group::_nil();
1621 if ( mainIterVec.empty() ) // all main groups are empty
1622 return aResGrp._retn();
1624 for ( int g = 0, n = theToolGroups.length(); g < n; g++ )
1626 SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1627 if ( CORBA::is_nil( aGrp ) )
1629 if ( aType != aGrp->GetType() )
1630 THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1632 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1633 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1634 toolGroupVec.push_back( grpDS );
1640 aResGrp = CreateGroup( aType, theName );
1642 SMESHDS_Group* resGroupDS = 0;
1643 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1644 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1646 return aResGrp._retn();
1649 size_t i, nb = toolGroupVec.size();
1650 SMDS_ElemIteratorPtr mainElemIt
1651 ( new SMDS_IteratorOnIterators
1652 < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > >( mainIterVec ));
1653 while ( mainElemIt->more() )
1655 const SMDS_MeshElement* e = mainElemIt->next();
1657 for ( i = 0; ( i < nb && !isIn ); ++i )
1658 isIn = toolGroupVec[i]->Contains( e );
1661 resGroupDS->SMDSGroup().Add( e );
1664 // Update Python script
1665 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1666 << ".CutListOfGroups( " << theMainGroups << ", "
1667 << theToolGroups << ", '" << theName << "' )";
1669 SMESH_CATCH( SMESH::throwCorbaException );
1671 return aResGrp._retn();
1674 namespace // functions making checks according to SMESH::NB_COMMON_NODES_ENUM
1676 bool isAllNodesCommon(int nbChecked, int nbCommon, int nbNodes, int /*nbCorners*/,
1677 bool & toStopChecking )
1679 toStopChecking = ( nbCommon < nbChecked );
1680 return nbCommon == nbNodes;
1682 bool isMainNodesCommon(int nbChecked, int nbCommon, int /*nbNodes*/, int nbCorners,
1683 bool & toStopChecking )
1685 toStopChecking = ( nbCommon < nbChecked || nbChecked >= nbCorners );
1686 return nbCommon == nbCorners;
1688 bool isAtLeastOneNodeCommon(int /*nbChecked*/, int nbCommon, int /*nbNodes*/, int /*nbCorners*/,
1689 bool & /*toStopChecking*/ )
1691 return nbCommon > 0;
1693 bool isMajorityOfNodesCommon(int /*nbChecked*/, int nbCommon, int nbNodes, int /*nbCorners*/,
1694 bool & /*toStopChecking*/ )
1696 return nbCommon >= (nbNodes+1) / 2;
1700 //=============================================================================
1702 * Create a group of entities basing on nodes of other groups.
1703 * \param [in] theGroups - list of either groups, sub-meshes or filters.
1704 * \param [in] anElemType - a type of elements to include to the new group.
1705 * \param [in] theName - a name of the new group.
1706 * \param [in] theNbCommonNodes - criterion of inclusion of an element to the new group.
1707 * \param [in] theUnderlyingOnly - if \c True, an element is included to the
1708 * new group provided that it is based on nodes of an element of \a aListOfGroups
1709 * \return SMESH_Group - the created group
1711 // IMP 19939, bug 22010, IMP 22635
1712 //=============================================================================
1714 SMESH::SMESH_Group_ptr
1715 SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfIDSources& theGroups,
1716 SMESH::ElementType theElemType,
1717 const char* theName,
1718 SMESH::NB_COMMON_NODES_ENUM theNbCommonNodes,
1719 CORBA::Boolean theUnderlyingOnly)
1721 SMESH::SMESH_Group_var aResGrp;
1725 _preMeshInfo->FullLoadFromFile();
1727 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1729 if ( !theName || !aMeshDS )
1730 return SMESH::SMESH_Group::_nil();
1732 SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1734 bool (*isToInclude)(int nbChecked, int nbCommon, int nbNodes, int nbCorners, bool & toStop);
1735 SMESH_Comment nbCoNoStr( "SMESH.");
1736 switch ( theNbCommonNodes ) {
1737 case SMESH::ALL_NODES : isToInclude = isAllNodesCommon; nbCoNoStr<<"ALL_NODES" ;break;
1738 case SMESH::MAIN : isToInclude = isMainNodesCommon; nbCoNoStr<<"MAIN" ;break;
1739 case SMESH::AT_LEAST_ONE: isToInclude = isAtLeastOneNodeCommon; nbCoNoStr<<"AT_LEAST_ONE";break;
1740 case SMESH::MAJORITY : isToInclude = isMajorityOfNodesCommon; nbCoNoStr<<"MAJORITY" ;break;
1741 default: return aResGrp._retn();
1743 int nbChecked, nbCommon, nbNodes, nbCorners;
1749 aResGrp = CreateGroup( theElemType, theName );
1750 if ( aResGrp->_is_nil() )
1751 return SMESH::SMESH_Group::_nil();
1753 SMESHDS_GroupBase* groupBaseDS =
1754 SMESH::DownCast<SMESH_GroupBase_i*>( aResGrp )->GetGroupDS();
1755 SMDS_MeshGroup& resGroupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1757 vector<bool> isNodeInGroups;
1759 for ( int g = 0, n = theGroups.length(); g < n; g++ ) // loop on theGroups
1761 SMESH::SMESH_IDSource_var aGrp = theGroups[ g ];
1762 if ( CORBA::is_nil( aGrp ) )
1764 SMESH::SMESH_Mesh_var mesh = aGrp->GetMesh();
1765 if ( mesh->_is_nil() || mesh->GetId() != this->GetId() )
1768 SMDS_ElemIteratorPtr elIt = GetElements( aGrp, SMESH::ALL );
1769 if ( !elIt ) continue;
1771 if ( theElemType == SMESH::NODE ) // get all nodes of elements
1773 while ( elIt->more() ) {
1774 const SMDS_MeshElement* el = elIt->next();
1775 SMDS_ElemIteratorPtr nIt = el->nodesIterator();
1776 while ( nIt->more() )
1777 resGroupCore.Add( nIt->next() );
1780 // get elements of theElemType based on nodes of every element of group
1781 else if ( theUnderlyingOnly )
1783 while ( elIt->more() )
1785 const SMDS_MeshElement* el = elIt->next(); // an element of ref group
1786 TIDSortedElemSet elNodes( el->begin_nodes(), el->end_nodes() );
1787 TIDSortedElemSet checkedElems;
1788 SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1789 while ( nIt->more() )
1791 const SMDS_MeshNode* n = nIt->next();
1792 SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1793 // check nodes of elements of theElemType around el
1794 while ( elOfTypeIt->more() )
1796 const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1797 if ( !checkedElems.insert( elOfType ).second ) continue;
1798 nbNodes = elOfType->NbNodes();
1799 nbCorners = elOfType->NbCornerNodes();
1801 bool toStopChecking = false;
1802 SMDS_ElemIteratorPtr nIt2 = elOfType->nodesIterator();
1803 for ( nbChecked = 1; nIt2->more() && !toStopChecking; ++nbChecked )
1804 if ( elNodes.count( nIt2->next() ) &&
1805 isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1807 resGroupCore.Add( elOfType );
1814 // get all nodes of elements of groups
1817 while ( elIt->more() )
1819 const SMDS_MeshElement* el = elIt->next(); // an element of group
1820 SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1821 while ( nIt->more() )
1823 const SMDS_MeshNode* n = nIt->next();
1824 if ( n->GetID() >= (int) isNodeInGroups.size() )
1825 isNodeInGroups.resize( n->GetID() + 1, false );
1826 isNodeInGroups[ n->GetID() ] = true;
1832 // Get elements of theElemType based on a certain number of nodes of elements of groups
1833 if ( !theUnderlyingOnly && !isNodeInGroups.empty() )
1835 const SMDS_MeshNode* n;
1836 vector<bool> isElemChecked( aMeshDS->MaxElementID() + 1 );
1837 const int isNodeInGroupsSize = isNodeInGroups.size();
1838 for ( int iN = 0; iN < isNodeInGroupsSize; ++iN )
1840 if ( !isNodeInGroups[ iN ] ||
1841 !( n = aMeshDS->FindNode( iN )))
1844 // check nodes of elements of theElemType around n
1845 SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1846 while ( elOfTypeIt->more() )
1848 const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1849 vector<bool>::reference isChecked = isElemChecked[ elOfType->GetID() ];
1854 nbNodes = elOfType->NbNodes();
1855 nbCorners = elOfType->NbCornerNodes();
1857 bool toStopChecking = false;
1858 SMDS_ElemIteratorPtr nIt = elOfType->nodesIterator();
1859 for ( nbChecked = 1; nIt->more() && !toStopChecking; ++nbChecked )
1861 const smIdType nID = nIt->next()->GetID();
1862 if ( nID < isNodeInGroupsSize && isNodeInGroups[ nID ] &&
1863 isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1865 resGroupCore.Add( elOfType );
1873 // Update Python script
1874 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this())
1875 << ".CreateDimGroup( "
1876 << theGroups << ", " << theElemType << ", '" << theName << "', "
1877 << nbCoNoStr << ", " << theUnderlyingOnly << ")";
1879 SMESH_CATCH( SMESH::throwCorbaException );
1881 return aResGrp._retn();
1884 //================================================================================
1886 * \brief Distribute all faces of the mesh between groups using sharp edges and optionally
1887 * existing 1D elements as group boundaries.
1888 * \param [in] theSharpAngle - edge is considered sharp if an angle between normals of
1889 * adjacent faces is more than \a sharpAngle in degrees.
1890 * \param [in] theCreateEdges - to create 1D elements for detected sharp edges.
1891 * \param [in] theUseExistingEdges - to use existing edges as group boundaries
1892 * \return ListOfGroups - the created groups
1894 //================================================================================
1896 SMESH::ListOfGroups*
1897 SMESH_Mesh_i::FaceGroupsSeparatedByEdges( CORBA::Double theSharpAngle,
1898 CORBA::Boolean theCreateEdges,
1899 CORBA::Boolean theUseExistingEdges )
1901 if ( theSharpAngle < 0 || theSharpAngle > 180 )
1902 THROW_SALOME_CORBA_EXCEPTION("Invalid sharp angle, it must be between 0 and 180 degrees",
1905 SMESH::ListOfGroups_var resultGroups = new SMESH::ListOfGroups;
1911 _preMeshInfo->FullLoadFromFile();
1913 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1915 std::vector< SMESH_MeshAlgos::Edge > edges =
1916 SMESH_MeshAlgos::FindSharpEdges( meshDS, theSharpAngle, theUseExistingEdges );
1918 if ( theCreateEdges )
1920 std::vector<const SMDS_MeshNode *> nodes(2);
1921 for ( size_t i = 0; i < edges.size(); ++i )
1923 nodes[0] = edges[i]._node1;
1924 nodes[1] = edges[i]._node2;
1925 if ( meshDS->FindElement( nodes, SMDSAbs_Edge ))
1927 if ( edges[i]._medium )
1928 meshDS->AddEdge( edges[i]._node1, edges[i]._node2, edges[i]._medium );
1930 meshDS->AddEdge( edges[i]._node1, edges[i]._node2 );
1934 std::vector< std::vector< const SMDS_MeshElement* > > faceGroups =
1935 SMESH_MeshAlgos::SeparateFacesByEdges( meshDS, edges );
1937 SMESH::SMESH_MeshEditor_var editor = GetMeshEditor(); // create _editor
1939 resultGroups->length( faceGroups.size() );
1940 for ( size_t iG = 0; iG < faceGroups.size(); ++iG )
1942 SMESH::SMESH_Group_var group = CreateGroup( SMESH::FACE,
1943 _editor->GenerateGroupName("Group").c_str());
1944 resultGroups[iG] = SMESH::SMESH_Group::_duplicate( group );
1946 SMESHDS_GroupBase* groupBaseDS =
1947 SMESH::DownCast<SMESH_GroupBase_i*>( group )->GetGroupDS();
1948 SMDS_MeshGroup& groupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1950 std::vector< const SMDS_MeshElement* >& faces = faceGroups[ iG ];
1951 for ( size_t i = 0; i < faces.size(); ++i )
1952 groupCore.Add( faces[i] );
1955 pyDump << resultGroups << " = " << SMESH::SMESH_Mesh_var(_this())
1956 << ".FaceGroupsSeparatedByEdges( "
1957 << TVar( theSharpAngle ) << ", "
1958 << theCreateEdges << ", "
1959 << theUseExistingEdges << " )";
1961 SMESH_CATCH( SMESH::throwCorbaException );
1962 return resultGroups._retn();
1966 //================================================================================
1968 * \brief Remember GEOM group data
1970 //================================================================================
1972 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1973 CORBA::Object_ptr theSmeshObj)
1975 if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1978 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( theGeomObj );
1979 if ( groupSO->_is_nil() )
1982 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( theGeomObj );
1983 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
1984 GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
1987 _geomGroupData.push_back( TGeomGroupData() );
1988 TGeomGroupData & groupData = _geomGroupData.back();
1990 CORBA::String_var entry = groupSO->GetID();
1991 groupData._groupEntry = entry.in();
1993 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
1994 groupData._indices.insert( ids[i] );
1996 groupData._smeshObject = CORBA::Object::_duplicate( theSmeshObj );
1997 // shape index in SMESHDS
1998 // TopoDS_Shape shape = _gen_i->GeomObjectToShape( theGeomObj );
1999 // groupData._dsID = shape.IsNull() ? 0 : _impl->GetSubMesh( shape )->GetId();
2002 //================================================================================
2004 * Remove GEOM group data relating to removed smesh object
2006 //================================================================================
2008 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
2010 list<TGeomGroupData>::iterator
2011 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2012 for ( ; data != dataEnd; ++data ) {
2013 if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
2014 _geomGroupData.erase( data );
2020 //================================================================================
2022 * \brief Replace a shape in the mesh upon Break Link
2024 //================================================================================
2026 void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom)
2028 // check if geometry changed
2029 bool geomChanged = true;
2030 GEOM::GEOM_Object_var oldGeom = GetShapeToMesh();
2031 if ( !theNewGeom->_is_nil() && !oldGeom->_is_nil() )
2032 geomChanged = ( oldGeom->GetTick() != theNewGeom->GetTick() );
2034 TopoDS_Shape S = _impl->GetShapeToMesh();
2035 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2036 TCollection_AsciiString aIOR;
2037 if ( geomClient->Find( S, aIOR ))
2038 geomClient->RemoveShapeFromBuffer( aIOR );
2040 // clear buffer also for sub-groups
2041 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2042 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2043 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2044 for (; g != groups.end(); ++g)
2045 if (const SMESHDS_GroupOnGeom* group = dynamic_cast<SMESHDS_GroupOnGeom*>(*g))
2047 const TopoDS_Shape& s = group->GetShape();
2048 if ( geomClient->Find( s, aIOR ))
2049 geomClient->RemoveShapeFromBuffer( aIOR );
2052 // clear buffer also for sub-meshes
2053 std::map<int, SMESH_subMesh_i*>::const_iterator aSubMeshIter = _mapSubMesh_i.cbegin();
2054 for(; aSubMeshIter != _mapSubMesh_i.cend(); aSubMeshIter++) {
2055 int aShapeID = aSubMeshIter->first;
2056 const TopoDS_Shape& aSubShape = meshDS->IndexToShape(aShapeID);
2057 TCollection_AsciiString aShapeIOR;
2058 if ( geomClient->Find( aSubShape, aShapeIOR ))
2059 geomClient->RemoveShapeFromBuffer( aShapeIOR );
2063 int shapeID; smIdType fromID, toID; // indices of elements of a sub-mesh
2065 std::vector< TRange > elemRanges, nodeRanges; // elements of sub-meshes
2066 std::vector< SMDS_PositionPtr > positions; // node positions
2069 // store positions of elements on geometry
2071 if ( meshDS->MaxNodeID() > meshDS->NbNodes() ||
2072 meshDS->MaxElementID() > meshDS->NbElements() )
2075 meshDS->CompactMesh();
2077 positions.resize( meshDS->NbNodes() + 1 );
2078 for ( SMDS_NodeIteratorPtr nodeIt = meshDS->nodesIterator(); nodeIt->more(); )
2080 const SMDS_MeshNode* n = nodeIt->next();
2081 positions[ n->GetID() ] = n->GetPosition();
2084 // remove elements from sub-meshes to avoid their removal at hypotheses addition
2085 for ( int isNode = 0; isNode < 2; ++isNode )
2087 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2088 ranges.reserve( meshDS->MaxShapeIndex() + 10 );
2089 ranges.push_back( TRange{ 0,0,0 });
2090 SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
2091 while ( elemIt->more() )
2093 const SMDS_MeshElement* e = elemIt->next();
2094 const smIdType elemID = e->GetID();
2095 const int shapeID = e->GetShapeID();
2096 TRange & lastRange = ranges.back();
2097 if ( lastRange.shapeID != shapeID ||
2098 lastRange.toID != elemID )
2099 ranges.push_back( TRange{ shapeID, elemID, elemID + 1 });
2101 lastRange.toID = elemID + 1;
2103 if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( shapeID ))
2105 if ( isNode ) sm->RemoveNode( static_cast< const SMDS_MeshNode *>( e ));
2106 else sm->RemoveElement( e );
2113 // update the reference to theNewGeom (needed for correct execution of a dumped python script)
2114 SMESH::SMESH_Mesh_var me = _this();
2115 SALOMEDS::SObject_wrap aSO = _gen_i->ObjectToSObject( me );
2116 CORBA::String_var entry = theNewGeom->GetStudyEntry();
2117 if ( !aSO->_is_nil() )
2119 SALOMEDS::SObject_wrap aShapeRefSO;
2120 if ( aSO->FindSubObject( _gen_i->GetRefOnShapeTag(), aShapeRefSO.inout() ))
2122 SALOMEDS::SObject_wrap aShapeSO = _gen_i->getStudyServant()->FindObjectID( entry );
2123 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2124 builder->Addreference( aShapeRefSO, aShapeSO );
2128 // re-assign global hypotheses to the new shape
2129 _mainShapeTick = geomChanged ? -1 : theNewGeom->GetTick();
2130 CheckGeomModif( true );
2134 // restore positions of elements on geometry
2135 for ( int isNode = 0; isNode < 2; ++isNode )
2137 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2138 for ( size_t i = 1; i < ranges.size(); ++i )
2140 int elemID = ranges[ i ].fromID;
2141 int toID = ranges[ i ].toID;
2142 SMESHDS_SubMesh * smDS = meshDS->NewSubMesh( ranges[ i ].shapeID );
2144 for ( ; elemID < toID; ++elemID )
2145 smDS->AddNode( meshDS->FindNode( elemID ));
2147 for ( ; elemID < toID; ++elemID )
2148 smDS->AddElement( meshDS->FindElement( elemID ));
2150 if ( SMESH_subMesh* sm = _impl->GetSubMeshContaining( ranges[ i ].shapeID ))
2151 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
2154 for ( unsigned int nodeID = 1; nodeID < positions.size(); ++nodeID )
2155 if ( positions[ nodeID ])
2156 if ( SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( meshDS->FindNode( nodeID )))
2157 n->SetPosition( positions[ nodeID ], n->GetShapeID() );
2160 _gen_i->UpdateIcons( SMESH::SMESH_Mesh_var( _this() ));
2163 TPythonDump() << "SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject("
2164 << me <<".GetMesh()), " << entry.in() << ")";
2166 TPythonDump() << me << ".ReplaceShape( " << entry.in() << " )";
2170 //================================================================================
2172 * \brief Return new group contents if it has been changed and update group data
2174 //================================================================================
2176 enum { ONLY_IF_CHANGED, IS_BREAK_LINK, MAIN_TRANSFORMED };
2178 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData, int how )
2180 TopoDS_Shape newShape;
2181 SALOMEDS::SObject_wrap groupSO;
2183 if ( how == IS_BREAK_LINK )
2185 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( groupData._smeshObject );
2186 SALOMEDS::SObject_wrap geomRefSO;
2187 if ( !meshSO->_is_nil() &&
2188 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ))
2190 geomRefSO->ReferencedObject( groupSO.inout() );
2196 groupSO = _gen_i->getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
2199 if ( groupSO->_is_nil() )
2202 CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
2203 GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
2204 if ( geomGroup->_is_nil() )
2207 // get indices of group items
2208 set<int> curIndices;
2209 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( geomGroup );
2210 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
2211 GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
2212 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2213 curIndices.insert( ids[i] );
2215 bool sameIndices = ( groupData._indices == curIndices );
2216 if ( how == ONLY_IF_CHANGED && sameIndices )
2217 return newShape; // group not changed
2220 CORBA::String_var entry = geomGroup->GetStudyEntry();
2221 groupData._groupEntry = entry.in();
2222 groupData._indices = curIndices;
2224 newShape = _gen_i->GeomObjectToShape( geomGroup );
2226 // check if newShape is up-to-date
2227 if ( !newShape.IsNull() && ids->length() > 0 )
2229 bool toUpdate = ! _impl->GetMeshDS()->IsGroupOfSubShapes( newShape );
2232 TopExp_Explorer exp( newShape, (TopAbs_ShapeEnum)( groupOp->GetType( geomGroup )));
2233 for ( ; exp.More() && !toUpdate; exp.Next() )
2235 int ind = _impl->GetMeshDS()->ShapeToIndex( exp.Current() );
2236 toUpdate = ( curIndices.erase( ind ) == 0 );
2238 if ( !curIndices.empty() )
2243 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2244 CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
2245 geomClient->RemoveShapeFromBuffer( groupIOR.in() );
2246 newShape = _gen_i->GeomObjectToShape( geomGroup );
2251 // geom group becomes empty - return empty compound
2252 TopoDS_Compound compound;
2253 BRep_Builder().MakeCompound(compound);
2254 newShape = compound;
2262 //-----------------------------------------------------------------------------
2264 * \brief Storage of shape and index used in CheckGeomGroupModif()
2266 struct TIndexedShape
2269 TopoDS_Shape _shape;
2270 TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
2272 //-----------------------------------------------------------------------------
2274 * \brief Data to re-create a group on geometry
2276 struct TGroupOnGeomData
2279 TopoDS_Shape _shape;
2280 SMDSAbs_ElementType _type;
2282 Quantity_Color _color;
2284 TGroupOnGeomData( const SMESHDS_GroupOnGeom* group )
2286 _oldID = group->GetID();
2287 _type = group->GetType();
2288 _name = group->GetStoreName();
2289 _color = group->GetColor();
2293 //-----------------------------------------------------------------------------
2295 * \brief Check if a filter is still valid after geometry removal
2297 bool isValidGeomFilter( SMESH::Filter_var theFilter )
2299 if ( theFilter->_is_nil() )
2301 SMESH::Filter::Criteria_var criteria;
2302 theFilter->GetCriteria( criteria.out() );
2304 for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
2306 const char* thresholdID = criteria[ iCr ].ThresholdID.in();
2308 switch ( criteria[ iCr ].Type )
2310 case SMESH::FT_BelongToGeom:
2311 case SMESH::FT_BelongToPlane:
2312 case SMESH::FT_BelongToCylinder:
2313 case SMESH::FT_BelongToGenSurface:
2314 case SMESH::FT_LyingOnGeom:
2315 entry = thresholdID;
2317 case SMESH::FT_ConnectedElements:
2320 entry = thresholdID;
2326 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
2327 SALOMEDS::SObject_wrap so = gen->getStudyServant()->FindObjectID( entry.c_str() );
2328 if ( so->_is_nil() )
2330 CORBA::Object_var obj = so->GetObject();
2331 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj );
2332 if ( gen->GeomObjectToShape( geom ).IsNull() )
2335 } // loop on criteria
2341 //=============================================================================
2343 * \brief Update data if geometry changes
2347 //=============================================================================
2349 void SMESH_Mesh_i::CheckGeomModif( bool theIsBreakLink )
2351 SMESH::SMESH_Mesh_var me = _this();
2352 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2354 TPythonDump dumpNothing; // prevent any dump
2356 //bool removedFromClient = false;
2358 if ( mainGO->_is_nil() ) // GEOM_Client cleared or geometry removed? (IPAL52735, PAL23636)
2360 //removedFromClient = _impl->HasShapeToMesh();
2362 // try to find geometry by study reference
2363 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2364 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2365 if ( !meshSO->_is_nil() &&
2366 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2367 geomRefSO->ReferencedObject( geomSO.inout() ))
2369 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2370 mainGO = GEOM::GEOM_Object::_narrow( geomObj );
2373 if ( mainGO->_is_nil() && // geometry removed ==>
2374 !geomRefSO->_is_nil() ) // remove geom dependent data: sub-meshes etc.
2376 // convert geom dependent groups into standalone ones
2377 CheckGeomGroupModif();
2379 _impl->ShapeToMesh( TopoDS_Shape() );
2381 // remove sub-meshes
2382 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2383 while ( i_sm != _mapSubMeshIor.end() )
2385 SMESH::SMESH_subMesh_ptr sm = i_sm->second;
2387 RemoveSubMesh( sm );
2389 // remove all children except groups in the study
2390 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2391 SALOMEDS::SObject_wrap so;
2392 for ( CORBA::Long tag = SMESH::Tag_RefOnShape; tag <= SMESH::Tag_LastSubMesh; ++tag )
2393 if ( meshSO->FindSubObject( tag, so.inout() ))
2394 builder->RemoveObjectWithChildren( so );
2396 _gen_i->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED" );
2402 if ( !_impl->HasShapeToMesh() ) return;
2405 // Update after group modification
2407 const bool geomChanged = ( mainGO->GetTick() != _mainShapeTick );
2408 if ( !theIsBreakLink )
2409 if ( mainGO->GetType() == GEOM_GROUP || !geomChanged ) // is group or not modified
2411 smIdType nb = NbNodes() + NbElements();
2412 CheckGeomGroupModif();
2413 bool updated = ( nb != NbNodes() + NbElements() );
2414 if ( updated ) // something removed due to hypotheses change
2415 _gen_i->UpdateIcons( me );
2416 if ( updated == geomChanged || nb == 0 )
2420 // Update after shape modification or breakLink w/o geometry change
2422 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2423 if ( !geomClient ) return;
2424 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( mainGO );
2425 if ( geomGen->_is_nil() ) return;
2426 CORBA::String_var geomComponentType = geomGen->ComponentDataType();
2427 bool isShaper = ( strcmp( geomComponentType.in(), "SHAPERSTUDY" ) == 0 );
2429 SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
2431 TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
2432 if ( meshDS->ShapeToIndex( newShape ) == 1 ) // not yet updated
2434 CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
2435 geomClient->RemoveShapeFromBuffer( ior.in() );
2436 newShape = _gen_i->GeomObjectToShape( mainGO );
2439 // Update data taking into account that if topology doesn't change
2440 // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
2443 _preMeshInfo->ForgetAllData();
2445 if ( geomChanged || !isShaper )
2447 if ( newShape.IsNull() )
2450 _mainShapeTick = mainGO->GetTick();
2452 // store data of groups on geometry including new TopoDS_Shape's
2453 std::vector< TGroupOnGeomData > groupsData;
2454 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2455 groupsData.reserve( groups.size() );
2456 TopTools_DataMapOfShapeShape old2newShapeMap;
2457 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2458 for ( ; g != groups.end(); ++g )
2460 if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
2462 groupsData.push_back( TGroupOnGeomData( group ));
2465 SMESH::SMESH_GroupOnGeom_var gog;
2466 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.find( group->GetID() );
2467 if ( i_grp != _mapGroups.end() )
2468 gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second );
2470 GEOM::GEOM_Object_var geom;
2471 if ( !gog->_is_nil() )
2473 if ( !theIsBreakLink )
2474 geom = gog->GetShape();
2476 if ( theIsBreakLink || geom->_is_nil() )
2478 SALOMEDS::SObject_wrap grpSO = _gen_i->ObjectToSObject( gog );
2479 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2480 if ( !grpSO->_is_nil() &&
2481 grpSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2482 geomRefSO->ReferencedObject( geomSO.inout() ))
2484 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2485 geom = GEOM::GEOM_Object::_narrow( geomObj );
2489 if ( old2newShapeMap.IsBound( group->GetShape() ))
2491 groupsData.back()._shape = old2newShapeMap( group->GetShape() );
2493 else if ( !geom->_is_nil() )
2495 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2496 if ( meshDS->IsGroupOfSubShapes( groupsData.back()._shape ))
2498 CORBA::String_var ior = geomGen->GetStringFromIOR( geom );
2499 geomClient->RemoveShapeFromBuffer( ior.in() );
2500 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2502 old2newShapeMap.Bind( group->GetShape(), groupsData.back()._shape );
2507 // store assigned hypotheses
2508 std::vector< pair< int, THypList > > ids2Hyps;
2509 const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
2510 for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
2512 const TopoDS_Shape& s = s2hyps.Key();
2513 const THypList& hyps = s2hyps.ChangeValue();
2514 ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
2517 std::multimap< std::set<int>, int > ii2iMap; // group sub-ids to group id in SMESHDS
2519 // count shapes excluding compounds corresponding to geom groups
2520 int oldNbSubShapes = meshDS->MaxShapeIndex();
2521 for ( ; oldNbSubShapes > 0; --oldNbSubShapes )
2523 const TopoDS_Shape& s = meshDS->IndexToShape( oldNbSubShapes );
2524 if ( s.IsNull() || s.ShapeType() != TopAbs_COMPOUND )
2527 std::set<int> subIds;
2528 for ( TopoDS_Iterator it( s ); it.More(); it.Next() )
2529 subIds.insert( meshDS->ShapeToIndex( it.Value() ));
2530 ii2iMap.insert( std::make_pair( subIds, oldNbSubShapes ));
2533 // check if shape topology changes - save shape type per shape ID
2534 std::vector< TopAbs_ShapeEnum > shapeTypes( Max( oldNbSubShapes + 1, 1 ));
2535 for ( int shapeID = oldNbSubShapes; shapeID > 0; --shapeID )
2536 shapeTypes[ shapeID ] = meshDS->IndexToShape( shapeID ).ShapeType();
2538 // change shape to mesh
2539 _impl->ShapeToMesh( TopoDS_Shape() );
2540 _impl->ShapeToMesh( newShape );
2542 // check if shape topology changes - check new shape types
2543 bool sameTopology = ( oldNbSubShapes == meshDS->MaxShapeIndex() );
2544 for ( int shapeID = oldNbSubShapes; shapeID > 0 && sameTopology; --shapeID )
2546 const TopoDS_Shape& s = meshDS->IndexToShape( shapeID );
2547 sameTopology = ( !s.IsNull() && s.ShapeType() == shapeTypes[ shapeID ]);
2550 // re-add shapes (compounds) of geom groups
2551 typedef std::map< std::vector< int >, TGeomGroupData* > TIndices2GroupData;
2552 TIndices2GroupData ii2grData;
2553 std::vector< int > ii;
2554 std::map< int, int > old2newIDs; // group IDs
2555 std::list<TGeomGroupData>::iterator dataIt = _geomGroupData.begin();
2556 for ( ; dataIt != _geomGroupData.end(); ++dataIt )
2558 TGeomGroupData* data = &(*dataIt);
2559 ii.reserve( data->_indices.size() );
2560 ii.assign( data->_indices.begin(), data->_indices.end() );
2561 TIndices2GroupData::iterator ii2gd = ii2grData.insert( std::make_pair( ii, data )).first;
2562 if ( ii2gd->second != data )
2564 data->_groupEntry = ii2gd->second->_groupEntry;
2565 data->_indices = ii2gd->second->_indices;
2568 const int oldNbSub = data->_indices.size();
2569 const int soleOldID = oldNbSub == 1 ? *data->_indices.begin() : 0;
2571 std::multimap< std::set<int>, int >::iterator ii2i = ii2iMap.find( data->_indices );
2572 if ( ii2i != ii2iMap.end() )
2574 oldID = ii2i->second;
2575 ii2iMap.erase( ii2i );
2577 if ( !oldID && oldNbSub == 1 )
2579 if ( old2newIDs.count( oldID ))
2582 int how = ( theIsBreakLink || !sameTopology ) ? IS_BREAK_LINK : MAIN_TRANSFORMED;
2583 newShape = newGroupShape( *data, how );
2585 if ( !newShape.IsNull() )
2587 if ( oldNbSub > 1 && meshDS->ShapeToIndex( newShape ) > 0 ) // group reduced to one sub-shape
2589 TopoDS_Compound compound;
2590 BRep_Builder().MakeCompound( compound );
2591 BRep_Builder().Add( compound, newShape );
2592 newShape = compound;
2594 int newID = _impl->GetSubMesh( newShape )->GetId();
2595 if ( oldID /*&& oldID != newID*/ )
2596 old2newIDs.insert( std::make_pair( oldID, newID ));
2597 if ( oldNbSub == 1 )
2598 old2newIDs.insert( std::make_pair( soleOldID, newID ));
2602 // re-assign hypotheses
2603 for ( size_t i = 0; i < ids2Hyps.size(); ++i )
2605 int sID = ids2Hyps[i].first;
2608 std::map< int, int >::iterator o2n = old2newIDs.find( sID );
2609 if ( o2n != old2newIDs.end() )
2611 else if ( !sameTopology )
2614 const TopoDS_Shape& s = meshDS->IndexToShape( sID );
2617 const THypList& hyps = ids2Hyps[i].second;
2618 THypList::const_iterator h = hyps.begin();
2619 for ( ; h != hyps.end(); ++h )
2620 _impl->AddHypothesis( s, (*h)->GetID() );
2624 // restore groups on geometry
2625 for ( size_t i = 0; i < groupsData.size(); ++i )
2627 const TGroupOnGeomData& data = groupsData[i];
2628 if ( data._shape.IsNull() )
2631 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
2632 if ( i2g == _mapGroups.end() ) continue;
2634 SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
2635 if ( !gr_i ) continue;
2637 SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape );
2639 _mapGroups.erase( i2g );
2641 g->GetGroupDS()->SetColor( data._color );
2644 if ( !sameTopology )
2646 std::map< int, int >::iterator o2n = old2newIDs.begin();
2647 for ( ; o2n != old2newIDs.end(); ++o2n )
2649 int newID = o2n->second, oldID = o2n->first;
2650 if ( newID == oldID || !_mapSubMesh.count( oldID ))
2654 _mapSubMesh [ newID ] = _impl->GetSubMeshContaining( newID );
2655 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2656 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2658 _mapSubMesh. erase(oldID);
2659 _mapSubMesh_i. erase(oldID);
2660 _mapSubMeshIor.erase(oldID);
2662 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2666 // update _mapSubMesh
2667 std::map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
2668 for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
2669 i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
2672 if ( !sameTopology )
2674 // remove invalid study sub-objects
2675 CheckGeomGroupModif();
2678 _gen_i->UpdateIcons( me );
2680 if ( !theIsBreakLink && isShaper )
2682 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2683 if ( !meshSO->_is_nil() )
2684 _gen_i->SetPixMap(meshSO, "ICON_SMESH_TREE_GEOM_MODIF");
2688 //=============================================================================
2690 * \brief Update objects depending on changed geom groups
2692 * NPAL16168: geometrical group edition from a submesh don't modify mesh computation
2693 * issue 0020210: Update of a smesh group after modification of the associated geom group
2695 //=============================================================================
2697 void SMESH_Mesh_i::CheckGeomGroupModif()
2699 // remove sub-meshes referring a removed sub-shapes (if main shape still exists)
2700 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2701 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2702 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() ));
2703 if ( !mainGO->_is_nil() && !meshSO->_is_nil() )
2705 SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO;
2706 for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag )
2707 if ( meshSO->FindSubObject( tag, rootSO.inout() ))
2709 int nbValid = 0, nbRemoved = 0;
2710 SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO );
2711 for ( ; chItr->More(); chItr->Next() )
2713 SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO
2714 if ( !smSO->_is_nil() &&
2715 smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2716 geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference
2718 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2719 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj );
2720 if ( !geom->_non_existent() )
2723 continue; // keep the sub-mesh
2726 CORBA::Object_var smObj = _gen_i->SObjectToObject( smSO );
2727 SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj );
2728 if ( !sm->_is_nil() && !sm->_non_existent() )
2730 GEOM::GEOM_Object_var smGeom = sm->GetSubShape();
2731 if ( smGeom->_is_nil() )
2733 RemoveSubMesh( sm );
2740 _preMeshInfo->ForgetAllData(); // unknown hypothesis modified
2741 builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH
2745 if ( /*nbRemoved > 0 &&*/ nbValid == 0 )
2746 builder->RemoveObjectWithChildren( rootSO );
2750 // check for removed sub-shapes and convert geom dependent groups into standalone ones
2751 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2752 while ( i_gr != _mapGroups.end())
2754 SMESH::SMESH_GroupBase_ptr group = i_gr->second;
2756 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( group ), refSO, geomSO;
2757 SMESH::SMESH_GroupOnGeom_var onGeom = SMESH::SMESH_GroupOnGeom::_narrow ( group );
2758 SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group );
2759 bool isValidGeom = false;
2760 if ( !onGeom->_is_nil() )
2762 isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() ); // check TopoDS
2763 if ( !isValidGeom ) // check reference
2765 isValidGeom = ( ! groupSO->_is_nil() &&
2766 groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ) &&
2767 refSO->ReferencedObject( geomSO.inout() ) &&
2768 ! geomSO->_is_nil() &&
2769 !CORBA::is_nil( CORBA::Object_var( geomSO->GetObject() )));
2772 else if ( !onFilt->_is_nil() )
2774 isValidGeom = isValidGeomFilter( onFilt->GetFilter() );
2778 isValidGeom = ( !groupSO->_is_nil() &&
2779 !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ));
2783 if ( !IsLoaded() || group->IsEmpty() )
2785 RemoveGroup( group );
2787 else if ( !onGeom->_is_nil() || !onFilt->_is_nil() )
2789 SMESH::SMESH_Group_var ( ConvertToStandalone( group ));
2791 else // is it possible?
2793 builder->RemoveObjectWithChildren( refSO );
2799 if ( !_impl->HasShapeToMesh() ) return;
2801 SMESH::smIdType nbEntities = NbNodes() + NbElements();
2803 // Check if group contents changed
2805 typedef map< string, TopoDS_Shape > TEntry2Geom;
2806 TEntry2Geom newGroupContents;
2808 list<TGeomGroupData>::iterator
2809 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2810 for ( ; data != dataEnd; ++data )
2812 pair< TEntry2Geom::iterator, bool > it_new =
2813 newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
2814 bool processedGroup = !it_new.second;
2815 TopoDS_Shape& newShape = it_new.first->second;
2816 if ( !processedGroup )
2817 newShape = newGroupShape( *data, ONLY_IF_CHANGED );
2818 if ( newShape.IsNull() )
2819 continue; // no changes
2822 _preMeshInfo->ForgetOrLoad();
2824 if ( processedGroup ) { // update group indices
2825 list<TGeomGroupData>::iterator data2 = data;
2826 for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
2827 data->_indices = data2->_indices;
2830 // Update SMESH objects according to new GEOM group contents
2832 SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2833 if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2835 int oldID = submesh->GetId();
2836 if ( !_mapSubMeshIor.count( oldID ))
2838 TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2840 // update hypotheses
2841 list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2842 list <const SMESHDS_Hypothesis * >::iterator hypIt;
2843 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2845 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2846 _impl->AddHypothesis ( newShape, (*hypIt)->GetID());
2848 // care of submeshes
2849 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2850 int newID = newSubmesh->GetId();
2851 if ( newID != oldID ) {
2852 _mapSubMesh [ newID ] = newSubmesh;
2853 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2854 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2855 _mapSubMesh. erase(oldID);
2856 _mapSubMesh_i. erase(oldID);
2857 _mapSubMeshIor.erase(oldID);
2858 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2863 SMESH::SMESH_GroupOnGeom_var smeshGroup =
2864 SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2865 if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2867 SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2869 ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2870 SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2871 ds->SetShape( newShape );
2876 SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2877 if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2879 // Remove groups and submeshes basing on removed sub-shapes
2881 TopTools_MapOfShape newShapeMap;
2882 TopoDS_Iterator shapeIt( newShape );
2883 for ( ; shapeIt.More(); shapeIt.Next() )
2884 newShapeMap.Add( shapeIt.Value() );
2886 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2887 for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2889 if ( newShapeMap.Contains( shapeIt.Value() ))
2891 TopTools_IndexedMapOfShape oldShapeMap;
2892 TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2893 for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2895 const TopoDS_Shape& oldShape = oldShapeMap(i);
2896 int oldInd = meshDS->ShapeToIndex( oldShape );
2898 map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2899 if ( i_smIor != _mapSubMeshIor.end() ) {
2900 RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2903 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2904 for ( ; i_grp != _mapGroups.end(); ++i_grp )
2906 // check if a group bases on oldInd shape
2907 SMESHDS_GroupOnGeom* grpOnGeom = 0;
2908 if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2909 grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2910 if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2912 RemoveGroup( i_grp->second ); // several groups can base on same shape
2913 i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2918 // Reassign hypotheses and update groups after setting the new shape to mesh
2920 // collect anassigned hypotheses
2921 typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2922 list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2923 TShapeHypList assignedHyps;
2924 for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2926 const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2927 list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2928 if ( !hyps.empty() ) {
2929 assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2930 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2931 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2934 // collect shapes supporting groups
2935 typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2936 TShapeTypeList groupData;
2937 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2938 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2939 for ( ; grIt != groups.end(); ++grIt )
2941 if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2943 ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2945 // set new shape to mesh -> DS of sub-meshes and geom groups is deleted
2947 _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
2948 _impl->ShapeToMesh( newShape );
2950 // reassign hypotheses
2951 TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2952 for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2954 TIndexedShape& geom = indS_hyps->first;
2955 list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2956 int oldID = geom._index;
2957 int newID = meshDS->ShapeToIndex( geom._shape );
2958 if ( oldID == 1 ) { // main shape
2960 geom._shape = newShape;
2964 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2965 _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2966 // care of sub-meshes
2967 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2968 if ( newID != oldID ) {
2969 _mapSubMesh [ newID ] = newSubmesh;
2970 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2971 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2972 _mapSubMesh. erase(oldID);
2973 _mapSubMesh_i. erase(oldID);
2974 _mapSubMeshIor.erase(oldID);
2975 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2979 TShapeTypeList::iterator geomType = groupData.begin();
2980 for ( ; geomType != groupData.end(); ++geomType )
2982 const TIndexedShape& geom = geomType->first;
2983 int oldID = geom._index;
2984 if ( _mapGroups.find( oldID ) == _mapGroups.end() )
2987 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( _mapGroups[oldID] );
2988 CORBA::String_var name = groupSO->GetName();
2990 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID]))
2991 if ( SMESH_Group* group = _impl->AddGroup( geomType->second, name.in(),
2992 /*id=*/-1, geom._shape ))
2993 group_i->changeLocalId( group->GetID() );
2996 break; // everything has been updated
2999 } // loop on group data
3003 SMESH::smIdType newNbEntities = NbNodes() + NbElements();
3004 list< SALOMEDS::SObject_wrap > soToUpdateIcons;
3005 if ( newNbEntities != nbEntities )
3007 // Add all SObjects with icons to soToUpdateIcons
3008 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( _this() )); // mesh
3010 for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
3011 i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
3012 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_sm->second ));
3014 for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
3015 i_gr != _mapGroups.end(); ++i_gr ) // groups
3016 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_gr->second ));
3019 list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
3020 for ( ; so != soToUpdateIcons.end(); ++so )
3021 _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
3024 //=============================================================================
3026 * \brief Create standalone group from a group on geometry or filter
3028 //=============================================================================
3030 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
3032 SMESH::SMESH_Group_var aGroup;
3037 _preMeshInfo->FullLoadFromFile();
3039 if ( theGroup->_is_nil() )
3040 return aGroup._retn();
3042 SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
3044 return aGroup._retn();
3046 const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
3048 const int anId = aGroupToRem->GetLocalID();
3049 if ( !_impl->ConvertToStandalone( anId ) )
3050 return aGroup._retn();
3051 removeGeomGroupData( theGroup );
3053 SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3055 // remove old instance of group from own map
3056 { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
3057 _mapGroups.erase( anId );
3059 SALOMEDS::StudyBuilder_var builder;
3060 SALOMEDS::SObject_wrap aGroupSO;
3061 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3062 if ( !aStudy->_is_nil() ) {
3063 builder = aStudy->NewBuilder();
3064 aGroupSO = _gen_i->ObjectToSObject( theGroup );
3065 if ( !aGroupSO->_is_nil() )
3067 // remove reference to geometry
3068 SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
3069 for ( ; chItr->More(); chItr->Next() )
3071 // Remove group's child SObject
3072 SALOMEDS::SObject_wrap so = chItr->Value();
3073 builder->RemoveObject( so );
3075 // Update Python script
3076 TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
3077 << ".ConvertToStandalone( " << aGroupSO << " )";
3079 // change icon of Group on Filter
3082 // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
3083 // const int isEmpty = ( elemTypes->length() == 0 );
3086 SALOMEDS::GenericAttribute_wrap anAttr =
3087 builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
3088 SALOMEDS::AttributePixMap_wrap pm = anAttr;
3089 pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
3095 // remember new group in own map
3096 aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
3097 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3099 // register CORBA object for persistence
3100 _gen_i->RegisterObject( aGroup );
3102 CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
3103 builder->SetIOR( aGroupSO, ior.in() ); // == aGroup->Register();
3104 //aGroup->Register();
3105 aGroupToRem->UnRegister();
3107 SMESH_CATCH( SMESH::throwCorbaException );
3109 return aGroup._retn();
3112 //================================================================================
3114 * \brief Create a sub-mesh on a given sub-shape
3116 //================================================================================
3118 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
3120 MESSAGE( "createSubMesh" );
3121 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
3122 ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
3125 SMESH_subMesh_i * subMeshServant;
3128 subMeshId = mySubMesh->GetId();
3129 subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
3131 else // "invalid sub-mesh"
3133 // The invalid sub-mesh is created for the case where a valid sub-shape not found
3134 // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0.
3135 if ( _mapSubMesh.empty() )
3138 subMeshId = _mapSubMesh.begin()->first - 1;
3139 subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject);
3142 SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
3144 _mapSubMesh [subMeshId] = mySubMesh;
3145 _mapSubMesh_i [subMeshId] = subMeshServant;
3146 _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
3148 subMeshServant->Register();
3150 // register CORBA object for persistence
3151 int nextId = _gen_i->RegisterObject( subMesh );
3152 MESSAGE( "Add submesh to map with id = "<< nextId);
3154 // to track changes of GEOM groups
3155 if ( subMeshId > 0 )
3156 addGeomGroupData( theSubShapeObject, subMesh );
3158 return subMesh._retn();
3161 //================================================================================
3163 * \brief Return an existing sub-mesh based on a sub-shape with the given ID
3165 //================================================================================
3167 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
3169 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
3170 if ( it == _mapSubMeshIor.end() )
3171 return SMESH::SMESH_subMesh::_nil();
3173 return SMESH::SMESH_subMesh::_duplicate( (*it).second );
3176 //================================================================================
3178 * \brief Remove a sub-mesh based on the given sub-shape
3180 //================================================================================
3182 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
3183 GEOM::GEOM_Object_ptr theSubShapeObject )
3185 bool isHypChanged = false;
3186 if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
3187 return isHypChanged;
3189 const int subMeshId = theSubMesh->GetId();
3191 if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
3194 if (( _mapSubMesh.count( subMeshId )) &&
3195 ( sm = _impl->GetSubMeshContaining( subMeshId )))
3197 TopoDS_Shape S = sm->GetSubShape();
3200 list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
3201 isHypChanged = !hyps.empty();
3202 if ( isHypChanged && _preMeshInfo )
3203 _preMeshInfo->ForgetOrLoad();
3204 list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
3205 for ( ; hyp != hyps.end(); ++hyp )
3206 _impl->RemoveHypothesis(S, (*hyp)->GetID());
3213 SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
3214 isHypChanged = ( aHypList->length() > 0 );
3215 for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
3216 removeHypothesis( theSubShapeObject, aHypList[i] );
3219 catch( const SALOME::SALOME_Exception& ) {
3220 INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
3222 removeGeomGroupData( theSubShapeObject );
3226 std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
3227 if ( id_smi != _mapSubMesh_i.end() )
3228 id_smi->second->UnRegister();
3230 // remove a CORBA object
3231 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
3232 if ( id_smptr != _mapSubMeshIor.end() )
3233 SMESH::SMESH_subMesh_var( id_smptr->second );
3235 _mapSubMesh.erase(subMeshId);
3236 _mapSubMesh_i.erase(subMeshId);
3237 _mapSubMeshIor.erase(subMeshId);
3239 return isHypChanged;
3242 //================================================================================
3244 * \brief Create a group. Group type depends on given arguments
3246 //================================================================================
3248 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
3249 const char* theName,
3251 const TopoDS_Shape& theShape,
3252 const SMESH_PredicatePtr& thePredicate )
3254 std::string newName;
3255 if ( !theName || !theName[0] )
3257 std::set< std::string > presentNames;
3258 std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
3259 for ( ; i_gr != _mapGroups.end(); ++i_gr )
3261 CORBA::String_var name = i_gr->second->GetName();
3262 presentNames.insert( name.in() );
3265 newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
3266 } while ( !presentNames.insert( newName ).second );
3267 theName = newName.c_str();
3269 SMESH::SMESH_GroupBase_var aGroup;
3270 if ( SMESH_Group* g = _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName,
3271 theID, theShape, thePredicate ))
3273 int anId = g->GetID();
3274 SMESH_GroupBase_i* aGroupImpl;
3275 if ( !theShape.IsNull() )
3276 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3277 else if ( thePredicate )
3278 aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
3280 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3282 aGroup = aGroupImpl->_this();
3283 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3284 aGroupImpl->Register();
3286 // register CORBA object for persistence
3287 int nextId = _gen_i->RegisterObject( aGroup );
3288 MESSAGE( "Add group to map with id = "<< nextId);
3290 // to track changes of GEOM groups
3291 if ( !theShape.IsNull() ) {
3292 GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
3293 addGeomGroupData( geom, aGroup );
3296 return aGroup._retn();
3299 //=============================================================================
3301 * SMESH_Mesh_i::removeGroup
3303 * Should be called by ~SMESH_Group_i()
3305 //=============================================================================
3307 void SMESH_Mesh_i::removeGroup( const int theId )
3309 MESSAGE("SMESH_Mesh_i::removeGroup()");
3310 if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
3311 SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
3312 _mapGroups.erase( theId );
3313 removeGeomGroupData( group );
3314 if ( !_impl->RemoveGroup( theId ))
3316 // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
3317 RemoveGroup( group );
3319 group->UnRegister();
3323 //================================================================================
3325 * \brief Return a log that can be used to move another mesh to the same state as this one
3327 //================================================================================
3329 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
3331 SMESH::log_array_var aLog;
3335 _preMeshInfo->FullLoadFromFile();
3337 list < SMESHDS_Command * >logDS = _impl->GetLog();
3338 aLog = new SMESH::log_array;
3340 int lg = logDS.size();
3342 list < SMESHDS_Command * >::iterator its = logDS.begin();
3343 while(its != logDS.end()){
3344 SMESHDS_Command *com = *its;
3345 int comType = com->GetType();
3346 smIdType lgcom = com->GetNumber();
3347 const list < smIdType >&intList = com->GetIndexes();
3348 int inum = intList.size();
3349 list < smIdType >::const_iterator ii = intList.begin();
3350 const list < double >&coordList = com->GetCoords();
3351 int rnum = coordList.size();
3352 list < double >::const_iterator ir = coordList.begin();
3353 aLog[indexLog].commandType = comType;
3354 aLog[indexLog].number = lgcom;
3355 aLog[indexLog].coords.length(rnum);
3356 aLog[indexLog].indexes.length(inum);
3357 for(int i = 0; i < rnum; i++){
3358 aLog[indexLog].coords[i] = *ir;
3361 for(int i = 0; i < inum; i++){
3362 aLog[indexLog].indexes[i] = *ii;
3371 SMESH_CATCH( SMESH::throwCorbaException );
3373 return aLog._retn();
3376 //================================================================================
3378 * \brief Remove the log of commands
3380 //================================================================================
3382 void SMESH_Mesh_i::ClearLog()
3386 SMESH_CATCH( SMESH::throwCorbaException );
3389 //================================================================================
3391 * \brief Return a mesh ID
3393 //================================================================================
3395 CORBA::Long SMESH_Mesh_i::GetId()
3400 //=============================================================================
3403 //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
3404 // issue 0020918: groups removal is caused by hyp modification
3405 // issue 0021208: to forget not loaded mesh data at hyp modification
3406 struct TCallUp_i : public SMESH_Mesh::TCallUp
3408 SMESH_Mesh_i* _mesh;
3409 TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
3410 void RemoveGroup (const int theGroupID) override { _mesh->removeGroup( theGroupID ); }
3411 void HypothesisModified( int hypID,
3412 bool updIcons) override { _mesh->onHypothesisModified( hypID,
3414 void Load () override { _mesh->Load(); }
3415 bool IsLoaded() override { return _mesh->IsLoaded(); }
3416 TopoDS_Shape GetShapeByEntry(const std::string& entry) override
3418 GEOM::GEOM_Object_var go = SMESH_Gen_i::GetGeomObjectByEntry( entry );
3419 return SMESH_Gen_i::GeomObjectToShape( go );
3424 //================================================================================
3426 * \brief callback from _impl to
3427 * 1) forget not loaded mesh data (issue 0021208)
3428 * 2) mark hypothesis as valid
3430 //================================================================================
3432 void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons)
3435 _preMeshInfo->ForgetOrLoad();
3437 if ( theUpdateIcons )
3439 SMESH::SMESH_Mesh_var mesh = _this();
3440 _gen_i->UpdateIcons( mesh );
3443 if ( _nbInvalidHypos != 0 )
3445 // mark a hypothesis as valid after edition
3447 SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
3448 SALOMEDS::SObject_wrap hypRoot;
3449 if ( !smeshComp->_is_nil() &&
3450 smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
3452 SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
3453 for ( ; anIter->More(); anIter->Next() )
3455 SALOMEDS::SObject_wrap hypSO = anIter->Value();
3456 CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO );
3457 SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
3458 if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
3459 _gen_i->HighLightInvalid( hyp, false );
3461 nbInvalid += _gen_i->IsInvalid( hypSO );
3464 _nbInvalidHypos = nbInvalid;
3468 //================================================================================
3470 * \brief Set mesh implementation
3472 //================================================================================
3474 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
3476 MESSAGE("SMESH_Mesh_i::SetImpl");
3479 _impl->SetCallUp( new TCallUp_i(this));
3482 //=============================================================================
3484 * Return a mesh implementation
3486 //=============================================================================
3488 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
3490 MESSAGE("SMESH_Mesh_i::GetImpl()");
3494 //=============================================================================
3496 * Return mesh editor
3498 //=============================================================================
3500 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
3502 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3506 _preMeshInfo->FullLoadFromFile();
3508 // Create MeshEditor
3510 _editor = new SMESH_MeshEditor_i( this, false );
3511 aMeshEdVar = _editor->_this();
3513 // Update Python script
3514 TPythonDump() << _editor << " = "
3515 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
3517 SMESH_CATCH( SMESH::throwCorbaException );
3519 return aMeshEdVar._retn();
3522 //=============================================================================
3524 * Return mesh edition previewer
3526 //=============================================================================
3528 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
3530 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3534 _preMeshInfo->FullLoadFromFile();
3536 if ( !_previewEditor )
3537 _previewEditor = new SMESH_MeshEditor_i( this, true );
3538 aMeshEdVar = _previewEditor->_this();
3540 SMESH_CATCH( SMESH::throwCorbaException );
3542 return aMeshEdVar._retn();
3545 //================================================================================
3547 * \brief Return true if the mesh has been edited since a last total re-compute
3548 * and those modifications may prevent successful partial re-compute
3550 //================================================================================
3552 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard()
3554 Unexpect aCatch(SALOME_SalomeException);
3555 return _impl->HasModificationsToDiscard();
3558 //================================================================================
3560 * \brief Return a random unique color
3562 //================================================================================
3564 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
3566 const int MAX_ATTEMPTS = 100;
3568 double tolerance = 0.5;
3569 SALOMEDS::Color col;
3573 // generate random color
3574 double red = (double)rand() / RAND_MAX;
3575 double green = (double)rand() / RAND_MAX;
3576 double blue = (double)rand() / RAND_MAX;
3577 // check existence in the list of the existing colors
3578 bool matched = false;
3579 std::list<SALOMEDS::Color>::const_iterator it;
3580 for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
3581 SALOMEDS::Color color = *it;
3582 double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B - blue );
3583 matched = tol < tolerance;
3585 if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
3586 ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
3594 //=============================================================================
3596 * Set auto-color mode. If it is on, groups get unique random colors
3598 //=============================================================================
3600 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor)
3602 Unexpect aCatch(SALOME_SalomeException);
3603 _impl->SetAutoColor(theAutoColor);
3605 TPythonDump pyDump; // not to dump group->SetColor() from below code
3606 pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
3608 std::list<SALOMEDS::Color> aReservedColors;
3609 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
3610 for ( ; it != _mapGroups.end(); it++ ) {
3611 if ( CORBA::is_nil( it->second )) continue;
3612 SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
3613 it->second->SetColor( aColor );
3614 aReservedColors.push_back( aColor );
3618 //=============================================================================
3620 * Return true if auto-color mode is on
3622 //=============================================================================
3624 CORBA::Boolean SMESH_Mesh_i::GetAutoColor()
3626 Unexpect aCatch(SALOME_SalomeException);
3627 return _impl->GetAutoColor();
3630 //=============================================================================
3632 * Check if there are groups with equal names
3634 //=============================================================================
3636 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
3638 return _impl->HasDuplicatedGroupNamesMED();
3641 //================================================================================
3643 * \brief Care of a file before exporting mesh into it
3645 //================================================================================
3647 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
3649 SMESH_File aFile( file, false );
3651 if ( aFile.exists() ) {
3652 // existing filesystem node
3653 if ( !aFile.isDirectory() ) {
3654 if ( aFile.openForWriting() ) {
3655 if ( overwrite && ! aFile.remove()) {
3656 msg << "Can't replace " << aFile.getName();
3659 msg << "Can't write into " << aFile.getName();
3662 msg << "Location " << aFile.getName() << " is not a file";
3666 // nonexisting file; check if it can be created
3667 if ( !aFile.openForWriting() ) {
3668 msg << "You cannot create the file "
3670 << ". Check the directory existence and access rights";
3678 THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
3685 std::string SMESH_Mesh_i::generateMeshName()
3687 string aMeshName = "Mesh";
3688 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3689 if ( !aStudy->_is_nil() )
3691 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3692 if ( !aMeshSO->_is_nil() )
3694 CORBA::String_var name = aMeshSO->GetName();
3701 //================================================================================
3703 * \brief Prepare a file for export and pass names of mesh groups from study to mesh DS
3704 * \param file - file name
3705 * \param overwrite - to erase the file or not
3706 * \retval string - mesh name
3708 //================================================================================
3710 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char* file,
3711 CORBA::Boolean overwrite)
3714 PrepareForWriting(file, overwrite);
3715 string aMeshName(this->generateMeshName());
3716 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3717 if ( !aStudy->_is_nil() ) {
3718 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3719 if ( !aMeshSO->_is_nil() ) {
3720 // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
3721 if ( !aStudy->GetProperties()->IsLocked() )
3723 SALOMEDS::GenericAttribute_wrap anAttr;
3724 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3725 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
3726 SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
3727 ASSERT(!aFileName->_is_nil());
3728 aFileName->SetValue(file);
3729 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
3730 SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
3731 ASSERT(!aFileType->_is_nil());
3732 aFileType->SetValue("FICHIERMED");
3736 // Update Python script
3737 // set name of mesh before export
3738 TPythonDump() << _gen_i << ".SetName("
3739 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
3741 // check names of groups
3747 //================================================================================
3749 * \brief Export to MED file
3751 //================================================================================
3753 void SMESH_Mesh_i::ExportMED(const char* file,
3754 CORBA::Boolean auto_groups,
3755 CORBA::Long version,
3756 CORBA::Boolean overwrite,
3757 CORBA::Boolean autoDimension)
3759 //MESSAGE("MED minor version: "<< minor);
3762 _preMeshInfo->FullLoadFromFile();
3764 string aMeshName = prepareMeshNameAndGroups(file, overwrite);
3765 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, 0, autoDimension );
3767 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportMED( r'"
3769 << "auto_groups=" <<auto_groups << ", "
3770 << "version=" << version << ", "
3771 << "overwrite=" << overwrite << ", "
3772 << "meshPart=None, "
3773 << "autoDimension=" << autoDimension << " )";
3775 SMESH_CATCH( SMESH::throwCorbaException );
3778 CORBA::LongLong SMESH_Mesh_i::ExportMEDCoupling(CORBA::Boolean auto_groups, CORBA::Boolean autoDimension)
3780 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> data;
3782 // TODO : Fix me ! 2 next lines are required
3783 if( !this->_gen_i->isSSLMode() )
3784 SMESH::throwCorbaException("SMESH_Mesh_i::ExportMEDCoupling : only for embedded mode !");
3786 _preMeshInfo->FullLoadFromFile();
3788 string aMeshName = this->generateMeshName();
3789 data = _impl->ExportMEDCoupling( aMeshName.c_str(), auto_groups, 0, autoDimension );
3790 SMESH_CATCH( SMESH::throwCorbaException );
3791 MEDCoupling::DataArrayByte *ret(data.retn());
3792 return reinterpret_cast<CORBA::LongLong>(ret);
3795 //================================================================================
3797 * \brief Export a mesh to a DAT file
3799 //================================================================================
3801 void SMESH_Mesh_i::ExportDAT (const char *file, CORBA::Boolean renumber )
3805 _preMeshInfo->FullLoadFromFile();
3807 // check names of groups
3809 // Update Python script
3810 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3811 << ".ExportDAT( r'" << file<< ", " << renumber << "' )";
3814 PrepareForWriting( file );
3815 _impl->ExportDAT( file, /*part=*/nullptr, renumber );
3817 SMESH_CATCH( SMESH::throwCorbaException );
3820 //================================================================================
3822 * \brief Export a mesh to an UNV file
3824 //================================================================================
3826 void SMESH_Mesh_i::ExportUNV (const char *file, CORBA::Boolean renumber)
3830 _preMeshInfo->FullLoadFromFile();
3832 // check names of groups
3834 // Update Python script
3835 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3836 << ".ExportUNV( r'" << file << "', " << renumber << " )";
3839 PrepareForWriting( file );
3840 _impl->ExportUNV( file, /*part=*/nullptr, renumber );
3842 SMESH_CATCH( SMESH::throwCorbaException );
3845 //================================================================================
3847 * \brief Export a mesh to an STL file
3849 //================================================================================
3851 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3855 _preMeshInfo->FullLoadFromFile();
3857 // check names of groups
3859 // Update Python script
3860 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3861 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3863 CORBA::String_var name;
3864 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( _this() );
3865 if ( !so->_is_nil() )
3866 name = so->GetName();
3869 PrepareForWriting( file );
3870 _impl->ExportSTL( file, isascii, name.in() );
3872 SMESH_CATCH( SMESH::throwCorbaException );
3875 //================================================================================
3880 MEDFileSpeCls(const char * file,
3881 CORBA::Boolean overwrite,
3882 CORBA::Long version)
3883 :_file(file), _overwrite(overwrite), _version(version)
3885 std::string prepareMeshNameAndGroups(SMESH_Mesh_i& self)
3887 return self.prepareMeshNameAndGroups(_file.c_str(),_overwrite);
3890 void exportTo(SMESH_Mesh *mesh, const std::string& aMeshName, CORBA::Boolean auto_groups,
3891 SMESH_MeshPartDS* partDS, CORBA::Boolean autoDimension, bool have0dField,
3892 CORBA::Double ZTolerance, CORBA::Boolean saveNumbers )
3894 mesh->ExportMED( _file.c_str(), aMeshName.c_str(), auto_groups, _version,
3895 partDS, autoDimension, have0dField, ZTolerance, saveNumbers );
3898 void exportField(SMESH_Mesh_i& self, const std::string& aMeshName, bool have0dField,
3899 SMESHDS_Mesh *meshDS, const GEOM::ListOfFields& fields,
3900 const char*geomAssocFields)
3902 DriverMED_W_Field fieldWriter;
3903 fieldWriter.SetFile( _file.c_str() );
3904 fieldWriter.SetMeshName( aMeshName );
3905 fieldWriter.AddODOnVertices( have0dField );
3906 self.exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3909 void prepareForWriting(SMESH_Mesh_i& self) { self.PrepareForWriting(_file.c_str(), _overwrite); }
3913 CORBA::Boolean _overwrite;
3914 CORBA::Long _version;
3917 //================================================================================
3919 * \brief Export a part of mesh to a med file
3921 //================================================================================
3923 template<class SPECLS>
3924 void SMESH_Mesh_i::ExportPartToMEDCommon(SPECLS& speCls,
3925 SMESH::SMESH_IDSource_ptr meshPart,
3926 CORBA::Boolean auto_groups,
3927 CORBA::Boolean autoDimension,
3928 const GEOM::ListOfFields& fields,
3929 const char* geomAssocFields,
3930 CORBA::Double ZTolerance,
3931 CORBA::Boolean saveNumbers)
3935 _preMeshInfo->FullLoadFromFile();
3938 bool have0dField = false;
3939 if ( fields.length() > 0 )
3941 GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3942 if ( shapeToMesh->_is_nil() )
3943 THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3945 for ( size_t i = 0; i < fields.length(); ++i )
3947 if ( fields[i]->GetDataType() == GEOM::FDT_String )
3948 THROW_SALOME_CORBA_EXCEPTION
3949 ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3950 GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3951 if ( fieldShape->_is_nil() )
3952 THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3953 if ( !fieldShape->IsSame( shapeToMesh ) )
3954 THROW_SALOME_CORBA_EXCEPTION( "Field defined not on shape", SALOME::BAD_PARAM);
3955 if ( fields[i]->GetDimension() == 0 )
3958 if ( geomAssocFields )
3959 for ( int i = 0; geomAssocFields[i]; ++i )
3960 switch ( geomAssocFields[i] ) {
3961 case 'v':case 'e':case 'f':case 's': break;
3962 case 'V':case 'E':case 'F':case 'S': break;
3963 default: THROW_SALOME_CORBA_EXCEPTION
3964 ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3968 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3972 string aMeshName = "Mesh";
3973 SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3974 if ( CORBA::is_nil( meshPart ) ||
3975 SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3977 aMeshName = speCls.prepareMeshNameAndGroups(*this);
3978 speCls.exportTo(_impl, aMeshName, auto_groups, nullptr, autoDimension,
3979 have0dField, ZTolerance, saveNumbers );
3980 meshDS = _impl->GetMeshDS();
3985 _preMeshInfo->FullLoadFromFile();
3987 speCls.prepareForWriting(*this);
3989 SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( meshPart );
3990 if ( !SO->_is_nil() ) {
3991 CORBA::String_var name = SO->GetName();
3995 SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
3996 speCls.exportTo(_impl, aMeshName, auto_groups, partDS, autoDimension,
3997 have0dField, ZTolerance, saveNumbers);
3998 meshDS = tmpDSDeleter._obj = partDS;
4003 if ( _impl->HasShapeToMesh() )
4005 speCls.exportField( *this, aMeshName, have0dField, meshDS, fields, geomAssocFields);
4007 SMESH_CATCH( SMESH::throwCorbaException );
4010 //================================================================================
4012 * \brief Export a part of mesh to a med file
4014 //================================================================================
4016 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
4018 CORBA::Boolean auto_groups,
4019 CORBA::Long version,
4020 CORBA::Boolean overwrite,
4021 CORBA::Boolean autoDimension,
4022 const GEOM::ListOfFields& fields,
4023 const char* geomAssocFields,
4024 CORBA::Double ZTolerance,
4025 CORBA::Boolean saveNumbers)
4027 MESSAGE("MED version: "<< version);
4029 MEDFileSpeCls spe( file, overwrite, version );
4030 this->ExportPartToMEDCommon( spe, meshPart, auto_groups, autoDimension, fields,
4031 geomAssocFields, ZTolerance, saveNumbers );
4034 GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
4035 goList->length( fields.length() );
4036 for ( size_t i = 0; i < fields.length(); ++i )
4038 GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
4041 TPythonDump() << _this() << ".ExportPartToMED( "
4042 << meshPart << ", r'"
4044 << auto_groups << ", "
4046 << overwrite << ", "
4047 << autoDimension << ", "
4049 << ( geomAssocFields ? geomAssocFields : "" ) << "',"
4050 << TVar( ZTolerance ) << ", "
4053 SMESH_CATCH( SMESH::throwCorbaException );
4056 //================================================================================
4058 * \brief Export a part of mesh to a file with meshio library
4060 //================================================================================
4062 void SMESH_Mesh_i::ExportPartToMESHIO(SMESH::SMESH_IDSource_ptr meshPart,
4064 const char* selectedFilter)
4066 // Get default MED version
4067 SMESH::long_array_var medVersions = GetMEDVersionsCompatibleForAppend();
4068 const CORBA::Long version = medVersions[0];
4069 MESSAGE("Export part with meshio through MED version: " << version);
4071 // Default values are the same as for MED export
4072 const bool auto_groups = false;
4073 const bool overwrite = true;
4074 const bool autoDimension = true;
4075 const GEOM::ListOfFields fields;
4076 const char* geomAssocFields = "";
4077 const double ZTolerance = -1.0;
4078 const bool saveNumbers = true;
4080 // Create an object that holds a temp file name and
4081 // removes the file when goes out of scope.
4082 SMESH_Meshio meshio(selectedFilter);
4083 const QString tempFileName = meshio.CreateTempFileName(file);
4085 // Export a given mesh into the temp file
4086 MEDFileSpeCls spe(tempFileName.toUtf8().data(), overwrite, version);
4087 this->ExportPartToMEDCommon(spe, meshPart, auto_groups, autoDimension, fields,
4088 geomAssocFields, ZTolerance, saveNumbers);
4090 // Convert temp file into a target one with meshio command
4091 meshio.Convert(tempFileName, file);
4093 // Prepare python dump
4096 TPythonDump() << _this() << ".ExportPartToMESHIO("
4097 << meshPart << ", r'"
4099 << selectedFilter << "'"
4102 SMESH_CATCH(SMESH::throwCorbaException);
4105 //================================================================================
4107 class MEDFileMemSpeCls
4110 std::string prepareMeshNameAndGroups(SMESH_Mesh_i& self) { return self.generateMeshName(); }
4112 void exportTo(SMESH_Mesh *mesh, const std::string& aMeshName, CORBA::Boolean auto_groups,
4113 SMESH_MeshPartDS* partDS, CORBA::Boolean autoDimension, bool have0dField,
4114 CORBA::Double ZTolerance, CORBA::Boolean saveNumbers )
4116 _res = mesh->ExportMEDCoupling(aMeshName.c_str(), auto_groups, partDS,
4117 autoDimension, have0dField, ZTolerance, saveNumbers );
4119 void prepareForWriting(SMESH_Mesh_i& /*self*/) { /* nothing here */ }
4121 void exportField(SMESH_Mesh_i& self, const std::string& aMeshName, bool have0dField,
4122 SMESHDS_Mesh *meshDS, const GEOM::ListOfFields& fields,
4123 const char*geomAssocFields)
4125 DriverMED_W_Field_Mem fieldWriter(_res);
4126 fieldWriter.SetMeshName( aMeshName );
4127 fieldWriter.AddODOnVertices( have0dField );
4128 self.exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
4129 _res = fieldWriter.getData();
4132 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> getData() { return _res; }
4135 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> _res;
4138 //================================================================================
4140 * \brief Export a part of mesh to a MEDCoupling DS
4142 //================================================================================
4144 CORBA::LongLong SMESH_Mesh_i::ExportPartToMEDCoupling(SMESH::SMESH_IDSource_ptr meshPart,
4145 CORBA::Boolean auto_groups,
4146 CORBA::Boolean autoDimension,
4147 const GEOM::ListOfFields& fields,
4148 const char* geomAssocFields,
4149 CORBA::Double ZTolerance,
4150 CORBA::Boolean saveNumbers)
4152 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> data;
4155 if( !this->_gen_i->isSSLMode() )
4156 SMESH::throwCorbaException("SMESH_Mesh_i::ExportPartToMEDCoupling : only for embedded mode !");
4158 MEDFileMemSpeCls spe;
4159 this->ExportPartToMEDCommon( spe, meshPart, auto_groups, autoDimension, fields, geomAssocFields,
4160 ZTolerance, saveNumbers );
4161 data = spe.getData();
4163 SMESH_CATCH( SMESH::throwCorbaException );
4165 MEDCoupling::DataArrayByte *ret(data.retn());
4166 return reinterpret_cast<CORBA::LongLong>(ret);
4169 //================================================================================
4171 * Write GEOM fields to MED file
4173 //================================================================================
4175 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field& fieldWriter,
4176 SMESHDS_Mesh* meshDS,
4177 const GEOM::ListOfFields& fields,
4178 const char* geomAssocFields)
4180 #define METH "SMESH_Mesh_i::exportMEDFields() "
4182 if (( fields.length() < 1 ) &&
4183 ( !geomAssocFields || !geomAssocFields[0] ))
4186 std::vector< std::vector< double > > dblVals;
4187 std::vector< std::vector< int > > intVals;
4188 std::vector< int > subIdsByDim[ 4 ];
4189 const double noneDblValue = 0.;
4190 const double noneIntValue = 0;
4192 for ( size_t iF = 0; iF < fields.length(); ++iF )
4196 int dim = fields[ iF ]->GetDimension();
4197 SMDSAbs_ElementType elemType;
4198 TopAbs_ShapeEnum shapeType;
4200 case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
4201 case 1: elemType = SMDSAbs_Edge; shapeType = TopAbs_EDGE; break;
4202 case 2: elemType = SMDSAbs_Face; shapeType = TopAbs_FACE; break;
4203 case 3: elemType = SMDSAbs_Volume; shapeType = TopAbs_SOLID; break;
4205 continue; // skip fields on whole shape
4207 GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
4208 if ( dataType == GEOM::FDT_String )
4210 GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
4211 if ( stepIDs->length() < 1 )
4213 GEOM::string_array_var comps = fields[ iF ]->GetComponents();
4214 if ( comps->length() < 1 )
4216 CORBA::String_var name = fields[ iF ]->GetName();
4218 if ( !fieldWriter.Set( meshDS,
4222 /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
4225 for ( size_t iC = 0; iC < comps->length(); ++iC )
4226 fieldWriter.SetCompName( iC, comps[ iC ].in() );
4228 dblVals.resize( comps->length() );
4229 intVals.resize( comps->length() );
4231 // find sub-shape IDs
4233 std::vector< int >& subIds = subIdsByDim[ dim ];
4234 if ( subIds.empty() )
4235 for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
4236 if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
4237 subIds.push_back( id );
4241 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4245 for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
4247 GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
4248 if ( step->_is_nil() )
4251 CORBA::Long stamp = step->GetStamp();
4252 CORBA::Long id = step->GetID();
4253 fieldWriter.SetDtIt( int( stamp ), int( id ));
4255 // fill dblVals or intVals
4256 for ( size_t iC = 0; iC < comps->length(); ++iC )
4257 if ( dataType == GEOM::FDT_Double )
4259 dblVals[ iC ].clear();
4260 dblVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4264 intVals[ iC ].clear();
4265 intVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4269 case GEOM::FDT_Double:
4271 GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
4272 if ( dblStep->_is_nil() ) continue;
4273 GEOM::ListOfDouble_var vv = dblStep->GetValues();
4274 if ( vv->length() != subIds.size() * comps->length() )
4275 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4276 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4277 for ( size_t iC = 0; iC < comps->length(); ++iC )
4278 dblVals[ iC ][ subIds[ iS ]] = vv[ iV++ ];
4283 GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
4284 if ( intStep->_is_nil() ) continue;
4285 GEOM::ListOfLong_var vv = intStep->GetValues();
4286 if ( vv->length() != subIds.size() * comps->length() )
4287 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4288 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4289 for ( size_t iC = 0; iC < comps->length(); ++iC )
4290 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4293 case GEOM::FDT_Bool:
4295 GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
4296 if ( boolStep->_is_nil() ) continue;
4297 GEOM::short_array_var vv = boolStep->GetValues();
4298 if ( vv->length() != subIds.size() * comps->length() )
4299 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4300 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4301 for ( size_t iC = 0; iC < comps->length(); ++iC )
4302 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4308 // pass values to fieldWriter
4309 elemIt = fieldWriter.GetOrderedElems();
4310 if ( dataType == GEOM::FDT_Double )
4311 while ( elemIt->more() )
4313 const SMDS_MeshElement* e = elemIt->next();
4314 const int shapeID = e->getshapeId();
4315 if ( shapeID < 1 || shapeID >= (int) dblVals[0].size() )
4316 for ( size_t iC = 0; iC < comps->length(); ++iC )
4317 fieldWriter.AddValue( noneDblValue );
4319 for ( size_t iC = 0; iC < comps->length(); ++iC )
4320 fieldWriter.AddValue( dblVals[ iC ][ shapeID ]);
4323 while ( elemIt->more() )
4325 const SMDS_MeshElement* e = elemIt->next();
4326 const int shapeID = e->getshapeId();
4327 if ( shapeID < 1 || shapeID >= (int) intVals[0].size() )
4328 for ( size_t iC = 0; iC < comps->length(); ++iC )
4329 fieldWriter.AddValue( (double) noneIntValue );
4331 for ( size_t iC = 0; iC < comps->length(); ++iC )
4332 fieldWriter.AddValue( (double) intVals[ iC ][ shapeID ]);
4336 fieldWriter.Perform();
4337 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4338 if ( res && res->IsKO() )
4340 if ( res->myComment.empty() )
4341 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4343 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4349 if ( !geomAssocFields || !geomAssocFields[0] )
4352 // write geomAssocFields
4354 std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
4355 shapeDim[ TopAbs_COMPOUND ] = 3;
4356 shapeDim[ TopAbs_COMPSOLID ] = 3;
4357 shapeDim[ TopAbs_SOLID ] = 3;
4358 shapeDim[ TopAbs_SHELL ] = 2;
4359 shapeDim[ TopAbs_FACE ] = 2;
4360 shapeDim[ TopAbs_WIRE ] = 1;
4361 shapeDim[ TopAbs_EDGE ] = 1;
4362 shapeDim[ TopAbs_VERTEX ] = 0;
4363 shapeDim[ TopAbs_SHAPE ] = 3;
4365 for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
4367 std::vector< std::string > compNames;
4368 switch ( geomAssocFields[ iF ]) {
4370 fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
4371 compNames.push_back( "dim" );
4374 fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
4377 fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
4380 fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
4384 compNames.push_back( "id" );
4385 for ( size_t iC = 0; iC < compNames.size(); ++iC )
4386 fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
4388 fieldWriter.SetDtIt( -1, -1 );
4390 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4394 if ( compNames.size() == 2 ) // _vertices_
4395 while ( elemIt->more() )
4397 const SMDS_MeshElement* e = elemIt->next();
4398 const int shapeID = e->getshapeId();
4401 fieldWriter.AddValue( (double) -1 );
4402 fieldWriter.AddValue( (double) -1 );
4406 const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
4407 fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
4408 fieldWriter.AddValue( (double) shapeID );
4412 while ( elemIt->more() )
4414 const SMDS_MeshElement* e = elemIt->next();
4415 const int shapeID = e->getshapeId();
4417 fieldWriter.AddValue( (double) -1 );
4419 fieldWriter.AddValue( (double) shapeID );
4423 fieldWriter.Perform();
4424 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4425 if ( res && res->IsKO() )
4427 if ( res->myComment.empty() )
4428 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4430 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4433 } // loop on geomAssocFields
4438 //================================================================================
4440 * \brief Export a part of mesh to a DAT file
4442 //================================================================================
4444 void SMESH_Mesh_i::ExportPartToDAT(SMESH::SMESH_IDSource_ptr meshPart,
4446 CORBA::Boolean renumber )
4450 SMESH_MeshPartDS partDS( meshPart );
4451 _impl->ExportDAT( file, &partDS, renumber );
4453 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4454 << ".ExportPartToDAT( " << meshPart << ", r'" << file << ", " << renumber << "' )";
4456 SMESH_CATCH( SMESH::throwCorbaException );
4458 //================================================================================
4460 * \brief Export a part of mesh to an UNV file
4462 //================================================================================
4464 void SMESH_Mesh_i::ExportPartToUNV(SMESH::SMESH_IDSource_ptr meshPart,
4466 CORBA::Boolean renumber)
4470 _preMeshInfo->FullLoadFromFile();
4472 PrepareForWriting(file);
4474 SMESH_MeshPartDS partDS( meshPart );
4475 _impl->ExportUNV(file, &partDS, renumber );
4477 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4478 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << ", " << renumber << "' )";
4480 SMESH_CATCH( SMESH::throwCorbaException );
4482 //================================================================================
4484 * \brief Export a part of mesh to an STL file
4486 //================================================================================
4488 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
4490 ::CORBA::Boolean isascii)
4494 _preMeshInfo->FullLoadFromFile();
4496 PrepareForWriting(file);
4498 CORBA::String_var name;
4499 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4500 if ( !so->_is_nil() )
4501 name = so->GetName();
4503 SMESH_MeshPartDS partDS( meshPart );
4504 _impl->ExportSTL( file, isascii, name.in(), &partDS );
4506 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
4507 << meshPart<< ", r'" << file << "', " << isascii << ")";
4509 SMESH_CATCH( SMESH::throwCorbaException );
4512 //================================================================================
4514 * \brief Export a part of mesh to an STL file
4516 //================================================================================
4518 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
4520 CORBA::Boolean overwrite,
4521 CORBA::Boolean groupElemsByType)
4526 _preMeshInfo->FullLoadFromFile();
4528 PrepareForWriting(file,overwrite);
4530 std::string meshName("");
4531 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4532 if ( !so->_is_nil() )
4534 CORBA::String_var name = so->GetName();
4535 meshName = name.in();
4539 SMESH_MeshPartDS partDS( meshPart );
4540 _impl->ExportCGNS(file, &partDS, meshName.c_str(), groupElemsByType );
4542 SMESH_CATCH( SMESH::throwCorbaException );
4544 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
4545 << meshPart<< ", r'" << file << "', " << overwrite << ")";
4547 SMESH_CATCH( SMESH::throwCorbaException );
4550 THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
4554 //================================================================================
4556 * \brief Export a part of mesh to a GMF file
4558 //================================================================================
4560 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
4562 bool withRequiredGroups)
4566 _preMeshInfo->FullLoadFromFile();
4568 PrepareForWriting(file,/*overwrite=*/true);
4570 SMESH_MeshPartDS partDS( meshPart );
4571 _impl->ExportGMF(file, &partDS, withRequiredGroups);
4573 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
4574 << meshPart<< ", r'"
4576 << withRequiredGroups << ")";
4578 SMESH_CATCH( SMESH::throwCorbaException );
4581 //=============================================================================
4583 * Return computation progress [0.,1]
4585 //=============================================================================
4587 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
4591 return _impl->GetComputeProgress();
4593 SMESH_CATCH( SMESH::doNothing );
4597 //================================================================================
4599 * \brief Return nb of nodes
4601 //================================================================================
4603 SMESH::smIdType SMESH_Mesh_i::NbNodes()
4605 Unexpect aCatch(SALOME_SalomeException);
4607 return _preMeshInfo->NbNodes();
4609 return _impl->NbNodes();
4612 //================================================================================
4614 * \brief Return nb of elements
4616 //================================================================================
4618 SMESH::smIdType SMESH_Mesh_i::NbElements()
4620 Unexpect aCatch(SALOME_SalomeException);
4622 return _preMeshInfo->NbElements();
4624 return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
4627 //================================================================================
4629 * \brief Return nb of 0D elements
4631 //================================================================================
4633 SMESH::smIdType SMESH_Mesh_i::Nb0DElements()
4635 Unexpect aCatch(SALOME_SalomeException);
4637 return _preMeshInfo->Nb0DElements();
4639 return _impl->Nb0DElements();
4642 //================================================================================
4644 * \brief Return nb of BALL elements
4646 //================================================================================
4648 SMESH::smIdType SMESH_Mesh_i::NbBalls()
4650 Unexpect aCatch(SALOME_SalomeException);
4652 return _preMeshInfo->NbBalls();
4654 return _impl->NbBalls();
4657 //================================================================================
4659 * \brief Return nb of 1D elements
4661 //================================================================================
4663 SMESH::smIdType SMESH_Mesh_i::NbEdges()
4665 Unexpect aCatch(SALOME_SalomeException);
4667 return _preMeshInfo->NbEdges();
4669 return _impl->NbEdges();
4672 //================================================================================
4674 * \brief Return nb of edges
4676 //================================================================================
4678 SMESH::smIdType SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
4680 Unexpect aCatch(SALOME_SalomeException);
4682 return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
4684 return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
4687 //================================================================================
4689 * \brief Return nb of faces
4691 //================================================================================
4693 SMESH::smIdType SMESH_Mesh_i::NbFaces()
4695 Unexpect aCatch(SALOME_SalomeException);
4697 return _preMeshInfo->NbFaces();
4699 return _impl->NbFaces();
4702 //================================================================================
4704 * \brief Return nb of tringles
4706 //================================================================================
4708 SMESH::smIdType SMESH_Mesh_i::NbTriangles()
4710 Unexpect aCatch(SALOME_SalomeException);
4712 return _preMeshInfo->NbTriangles();
4714 return _impl->NbTriangles();
4717 //================================================================================
4719 * \brief Return nb of bi-quadratic triangles
4721 //================================================================================
4723 SMESH::smIdType SMESH_Mesh_i::NbBiQuadTriangles()
4725 Unexpect aCatch(SALOME_SalomeException);
4727 return _preMeshInfo->NbBiQuadTriangles();
4729 return _impl->NbBiQuadTriangles();
4732 SMESH::smIdType SMESH_Mesh_i::NbQuadrangles()
4734 Unexpect aCatch(SALOME_SalomeException);
4736 return _preMeshInfo->NbQuadrangles();
4738 return _impl->NbQuadrangles();
4741 SMESH::smIdType SMESH_Mesh_i::NbBiQuadQuadrangles()
4743 Unexpect aCatch(SALOME_SalomeException);
4745 return _preMeshInfo->NbBiQuadQuadrangles();
4747 return _impl->NbBiQuadQuadrangles();
4750 SMESH::smIdType SMESH_Mesh_i::NbPolygons()
4752 Unexpect aCatch(SALOME_SalomeException);
4754 return _preMeshInfo->NbPolygons();
4756 return _impl->NbPolygons();
4759 SMESH::smIdType SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order)
4761 Unexpect aCatch(SALOME_SalomeException);
4763 return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
4765 return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
4768 SMESH::smIdType SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
4770 Unexpect aCatch(SALOME_SalomeException);
4772 return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
4774 return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
4777 SMESH::smIdType SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
4779 Unexpect aCatch(SALOME_SalomeException);
4781 return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
4783 return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
4786 SMESH::smIdType SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
4788 Unexpect aCatch(SALOME_SalomeException);
4790 return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
4792 return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
4795 //=============================================================================
4797 SMESH::smIdType SMESH_Mesh_i::NbVolumes()
4799 Unexpect aCatch(SALOME_SalomeException);
4801 return _preMeshInfo->NbVolumes();
4803 return _impl->NbVolumes();
4806 SMESH::smIdType SMESH_Mesh_i::NbTetras()
4808 Unexpect aCatch(SALOME_SalomeException);
4810 return _preMeshInfo->NbTetras();
4812 return _impl->NbTetras();
4815 SMESH::smIdType SMESH_Mesh_i::NbHexas()
4817 Unexpect aCatch(SALOME_SalomeException);
4819 return _preMeshInfo->NbHexas();
4821 return _impl->NbHexas();
4824 SMESH::smIdType SMESH_Mesh_i::NbTriQuadraticHexas()
4826 Unexpect aCatch(SALOME_SalomeException);
4828 return _preMeshInfo->NbTriQuadHexas();
4830 return _impl->NbTriQuadraticHexas();
4833 SMESH::smIdType SMESH_Mesh_i::NbPyramids()
4835 Unexpect aCatch(SALOME_SalomeException);
4837 return _preMeshInfo->NbPyramids();
4839 return _impl->NbPyramids();
4842 SMESH::smIdType SMESH_Mesh_i::NbPrisms()
4844 Unexpect aCatch(SALOME_SalomeException);
4846 return _preMeshInfo->NbPrisms();
4848 return _impl->NbPrisms();
4851 SMESH::smIdType SMESH_Mesh_i::NbHexagonalPrisms()
4853 Unexpect aCatch(SALOME_SalomeException);
4855 return _preMeshInfo->NbHexPrisms();
4857 return _impl->NbHexagonalPrisms();
4860 SMESH::smIdType SMESH_Mesh_i::NbPolyhedrons()
4862 Unexpect aCatch(SALOME_SalomeException);
4864 return _preMeshInfo->NbPolyhedrons();
4866 return _impl->NbPolyhedrons();
4869 SMESH::smIdType SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
4871 Unexpect aCatch(SALOME_SalomeException);
4873 return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
4875 return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
4878 SMESH::smIdType SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
4880 Unexpect aCatch(SALOME_SalomeException);
4882 return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
4884 return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
4887 SMESH::smIdType SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
4889 Unexpect aCatch(SALOME_SalomeException);
4891 return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
4893 return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
4896 SMESH::smIdType SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
4898 Unexpect aCatch(SALOME_SalomeException);
4900 return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
4902 return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
4905 SMESH::smIdType SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
4907 Unexpect aCatch(SALOME_SalomeException);
4909 return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
4911 return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
4914 //=============================================================================
4916 * Return nb of published sub-meshes
4918 //=============================================================================
4920 SMESH::smIdType SMESH_Mesh_i::NbSubMesh()
4922 Unexpect aCatch(SALOME_SalomeException);
4923 return _mapSubMesh_i.size();
4926 //=============================================================================
4928 * Dumps mesh into a string
4930 //=============================================================================
4932 char* SMESH_Mesh_i::Dump()
4936 return CORBA::string_dup( os.str().c_str() );
4939 //=============================================================================
4941 * Method of SMESH_IDSource interface
4943 //=============================================================================
4945 SMESH::smIdType_array* SMESH_Mesh_i::GetIDs()
4947 return GetElementsId();
4950 //=============================================================================
4952 * Return ids of all elements
4954 //=============================================================================
4956 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsId()
4958 Unexpect aCatch(SALOME_SalomeException);
4960 _preMeshInfo->FullLoadFromFile();
4962 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
4963 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4965 if ( aSMESHDS_Mesh == NULL )
4966 return aResult._retn();
4968 smIdType nbElements = NbElements();
4969 aResult->length( nbElements );
4970 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
4971 for ( smIdType i = 0, n = nbElements; i < n && anIt->more(); i++ )
4972 aResult[i] = anIt->next()->GetID();
4974 return aResult._retn();
4978 //=============================================================================
4980 * Return ids of all elements of given type
4982 //=============================================================================
4984 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
4986 Unexpect aCatch(SALOME_SalomeException);
4988 _preMeshInfo->FullLoadFromFile();
4990 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
4991 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4993 if ( aSMESHDS_Mesh == NULL )
4994 return aResult._retn();
4996 smIdType nbElements = NbElements();
4998 // No sense in returning ids of elements along with ids of nodes:
4999 // when theElemType == SMESH::ALL, return node ids only if
5000 // there are no elements
5001 if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
5002 return GetNodesId();
5004 aResult->length( nbElements );
5008 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
5009 while ( i < nbElements && anIt->more() )
5010 aResult[i++] = anIt->next()->GetID();
5012 aResult->length( i );
5014 return aResult._retn();
5017 //=============================================================================
5019 * Return ids of all nodes
5021 //=============================================================================
5023 SMESH::smIdType_array* SMESH_Mesh_i::GetNodesId()
5025 Unexpect aCatch(SALOME_SalomeException);
5027 _preMeshInfo->FullLoadFromFile();
5029 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5030 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5032 if ( aMeshDS == NULL )
5033 return aResult._retn();
5035 smIdType nbNodes = NbNodes();
5036 aResult->length( nbNodes );
5037 SMDS_NodeIteratorPtr anIt = aMeshDS->nodesIterator();
5038 for ( smIdType i = 0, n = nbNodes; i < n && anIt->more(); i++ )
5039 aResult[i] = anIt->next()->GetID();
5041 return aResult._retn();
5044 //=============================================================================
5046 * Return type of the given element
5048 //=============================================================================
5050 SMESH::ElementType SMESH_Mesh_i::GetElementType( const SMESH::smIdType id, const bool iselem )
5052 SMESH::ElementType type = SMESH::ALL;
5056 _preMeshInfo->FullLoadFromFile();
5058 type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
5060 SMESH_CATCH( SMESH::throwCorbaException );
5065 //=============================================================================
5067 * Return geometric type of the given element
5069 //=============================================================================
5071 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const SMESH::smIdType id )
5074 _preMeshInfo->FullLoadFromFile();
5076 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
5078 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
5080 return ( SMESH::EntityType ) e->GetEntityType();
5083 //=============================================================================
5085 * Return type of the given element
5087 //=============================================================================
5089 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const SMESH::smIdType id )
5092 _preMeshInfo->FullLoadFromFile();
5094 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
5096 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
5098 return ( SMESH::GeometryType ) e->GetGeomType();
5101 //=============================================================================
5103 * Return ID of elements for given submesh
5105 //=============================================================================
5107 SMESH::smIdType_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
5109 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5113 _preMeshInfo->FullLoadFromFile();
5115 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5116 if(!SM) return aResult._retn();
5118 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5119 if(!SDSM) return aResult._retn();
5121 aResult->length(SDSM->NbElements());
5123 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5125 while ( eIt->more() ) {
5126 aResult[i++] = eIt->next()->GetID();
5129 SMESH_CATCH( SMESH::throwCorbaException );
5131 return aResult._retn();
5134 //=============================================================================
5136 * Return ID of nodes for given sub-mesh
5137 * If param all==true - return all nodes, else -
5138 * Return only nodes on shapes.
5140 //=============================================================================
5142 SMESH::smIdType_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
5145 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5149 _preMeshInfo->FullLoadFromFile();
5151 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5152 if(!SM) return aResult._retn();
5154 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5155 if(!SDSM) return aResult._retn();
5157 set<smIdType> theElems;
5158 if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
5159 SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
5160 while ( nIt->more() ) {
5161 const SMDS_MeshNode* elem = nIt->next();
5162 theElems.insert( elem->GetID() );
5165 else { // all nodes of submesh elements
5166 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5167 while ( eIt->more() ) {
5168 const SMDS_MeshElement* anElem = eIt->next();
5169 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
5170 while ( nIt->more() ) {
5171 const SMDS_MeshElement* elem = nIt->next();
5172 theElems.insert( elem->GetID() );
5177 aResult->length(theElems.size());
5178 set<smIdType>::iterator itElem;
5180 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
5181 aResult[i++] = *itElem;
5183 SMESH_CATCH( SMESH::throwCorbaException );
5185 return aResult._retn();
5188 //=============================================================================
5190 * Return type of elements for given sub-mesh
5192 //=============================================================================
5194 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
5196 SMESH::ElementType type = SMESH::ALL;
5200 _preMeshInfo->FullLoadFromFile();
5202 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5203 if(!SM) return SMESH::ALL;
5205 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5206 if(!SDSM) return SMESH::ALL;
5208 if(SDSM->NbElements()==0)
5209 return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
5211 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5212 const SMDS_MeshElement* anElem = eIt->next();
5214 type = ( SMESH::ElementType ) anElem->GetType();
5216 SMESH_CATCH( SMESH::throwCorbaException );
5222 //=============================================================================
5224 * Return pointer to _impl as an integer value. Is called from constructor of SMESH_Client
5226 //=============================================================================
5228 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
5231 _preMeshInfo->FullLoadFromFile();
5233 CORBA::LongLong pointeur = CORBA::LongLong(_impl);
5234 MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
5239 //=============================================================================
5241 * Get XYZ coordinates of node as list of double
5242 * If there is not node for given ID - return empty list
5244 //=============================================================================
5246 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const SMESH::smIdType id)
5249 _preMeshInfo->FullLoadFromFile();
5251 SMESH::double_array_var aResult = new SMESH::double_array();
5252 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5253 if ( aMeshDS == NULL )
5254 return aResult._retn();
5257 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5259 return aResult._retn();
5263 aResult[0] = aNode->X();
5264 aResult[1] = aNode->Y();
5265 aResult[2] = aNode->Z();
5266 return aResult._retn();
5270 //=============================================================================
5272 * For given node return list of IDs of inverse elements
5273 * If there is not node for given ID - return empty list
5275 //=============================================================================
5277 SMESH::smIdType_array* SMESH_Mesh_i::GetNodeInverseElements(const SMESH::smIdType id,
5278 SMESH::ElementType elemType)
5281 _preMeshInfo->FullLoadFromFile();
5283 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5284 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5285 if ( aMeshDS == NULL )
5286 return aResult._retn();
5289 const SMDS_MeshNode* aNode = aMeshDS->FindNode( id );
5291 return aResult._retn();
5293 // find inverse elements
5294 SMDSAbs_ElementType type = SMDSAbs_ElementType( elemType );
5295 SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator( type );
5296 aResult->length( aNode->NbInverseElements( type ));
5297 for( smIdType i = 0; eIt->more(); ++i )
5299 const SMDS_MeshElement* elem = eIt->next();
5300 aResult[ i ] = elem->GetID();
5302 return aResult._retn();
5305 //=============================================================================
5307 * \brief Return position of a node on shape
5309 //=============================================================================
5311 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(SMESH::smIdType NodeID)
5314 _preMeshInfo->FullLoadFromFile();
5316 SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
5317 aNodePosition->shapeID = 0;
5318 aNodePosition->shapeType = GEOM::SHAPE;
5320 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5321 if ( !mesh ) return aNodePosition;
5323 if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
5325 if ( SMDS_PositionPtr pos = aNode->GetPosition() )
5327 aNodePosition->shapeID = aNode->getshapeId();
5328 switch ( pos->GetTypeOfPosition() ) {
5330 aNodePosition->shapeType = GEOM::EDGE;
5331 aNodePosition->params.length(1);
5332 aNodePosition->params[0] = SMDS_EdgePositionPtr( pos )->GetUParameter();
5334 case SMDS_TOP_FACE: {
5335 SMDS_FacePositionPtr fPos = pos;
5336 aNodePosition->shapeType = GEOM::FACE;
5337 aNodePosition->params.length(2);
5338 aNodePosition->params[0] = fPos->GetUParameter();
5339 aNodePosition->params[1] = fPos->GetVParameter();
5342 case SMDS_TOP_VERTEX:
5343 aNodePosition->shapeType = GEOM::VERTEX;
5345 case SMDS_TOP_3DSPACE:
5346 if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
5347 aNodePosition->shapeType = GEOM::SOLID;
5348 else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
5349 aNodePosition->shapeType = GEOM::SHELL;
5355 return aNodePosition;
5358 //=============================================================================
5360 * \brief Return position of an element on shape
5362 //=============================================================================
5364 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(SMESH::smIdType ElemID)
5367 _preMeshInfo->FullLoadFromFile();
5369 SMESH::ElementPosition anElementPosition;
5370 anElementPosition.shapeID = 0;
5371 anElementPosition.shapeType = GEOM::SHAPE;
5373 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5374 if ( !mesh ) return anElementPosition;
5376 if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
5378 anElementPosition.shapeID = anElem->getshapeId();
5379 const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
5380 if ( !aSp.IsNull() ) {
5381 switch ( aSp.ShapeType() ) {
5383 anElementPosition.shapeType = GEOM::EDGE;
5386 anElementPosition.shapeType = GEOM::FACE;
5389 anElementPosition.shapeType = GEOM::VERTEX;
5392 anElementPosition.shapeType = GEOM::SOLID;
5395 anElementPosition.shapeType = GEOM::SHELL;
5401 return anElementPosition;
5404 //=============================================================================
5406 * If given element is node return IDs of shape from position
5407 * If there is not node for given ID - return -1
5409 //=============================================================================
5411 CORBA::Long SMESH_Mesh_i::GetShapeID(const SMESH::smIdType id)
5414 _preMeshInfo->FullLoadFromFile();
5416 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5417 if ( aMeshDS == NULL )
5421 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5423 return aNode->getshapeId();
5430 //=============================================================================
5432 * For given element return ID of result shape after
5433 * ::FindShape() from SMESH_MeshEditor
5434 * If there is not element for given ID - return -1
5436 //=============================================================================
5438 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const SMESH::smIdType id)
5441 _preMeshInfo->FullLoadFromFile();
5443 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5444 if ( aMeshDS == NULL )
5447 // try to find element
5448 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5452 ::SMESH_MeshEditor aMeshEditor(_impl);
5453 int index = aMeshEditor.FindShape( elem );
5461 //=============================================================================
5463 * Return number of nodes for given element
5464 * If there is not element for given ID - return -1
5466 //=============================================================================
5468 CORBA::Short SMESH_Mesh_i::GetElemNbNodes(const SMESH::smIdType id)
5471 _preMeshInfo->FullLoadFromFile();
5473 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5474 if ( aMeshDS == NULL ) return -1;
5475 // try to find element
5476 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5477 if(!elem) return -1;
5478 return elem->NbNodes();
5482 //=============================================================================
5484 * Return ID of node by given index for given element
5485 * If there is not element for given ID - return -1
5486 * If there is not node for given index - return -2
5488 //=============================================================================
5490 SMESH::smIdType SMESH_Mesh_i::GetElemNode(const SMESH::smIdType id, const CORBA::Short index)
5493 _preMeshInfo->FullLoadFromFile();
5495 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5496 if ( aMeshDS == NULL ) return -1;
5497 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5498 if(!elem) return -1;
5499 if( index>=elem->NbNodes() || index<0 ) return -1;
5500 return elem->GetNode(index)->GetID();
5503 //=============================================================================
5505 * Return IDs of nodes of given element
5507 //=============================================================================
5509 SMESH::smIdType_array* SMESH_Mesh_i::GetElemNodes(const SMESH::smIdType id)
5512 _preMeshInfo->FullLoadFromFile();
5514 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5515 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5517 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(id) )
5519 aResult->length( elem->NbNodes() );
5520 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5521 if ( const SMDS_MeshNode* n = elem->GetNode( i ))
5522 aResult[ i ] = n->GetID();
5525 return aResult._retn();
5528 //=============================================================================
5530 * Return true if given node is medium node
5531 * in given quadratic element
5533 //=============================================================================
5535 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const SMESH::smIdType ide, const SMESH::smIdType idn)
5538 _preMeshInfo->FullLoadFromFile();
5540 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5541 if ( aMeshDS == NULL ) return false;
5543 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5544 if(!aNode) return false;
5545 // try to find element
5546 const SMDS_MeshElement* elem = aMeshDS->FindElement(ide);
5547 if(!elem) return false;
5549 return elem->IsMediumNode(aNode);
5553 //=============================================================================
5555 * Return true if given node is medium node
5556 * in one of quadratic elements
5558 //=============================================================================
5560 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const SMESH::smIdType idn,
5561 SMESH::ElementType theElemType)
5564 _preMeshInfo->FullLoadFromFile();
5566 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5567 if ( aMeshDS == NULL ) return false;
5570 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5571 if(!aNode) return false;
5573 SMESH_MesherHelper aHelper( *(_impl) );
5575 SMDSAbs_ElementType aType;
5576 if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
5577 else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
5578 else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
5579 else aType = SMDSAbs_All;
5581 return aHelper.IsMedium(aNode,aType);
5585 //=============================================================================
5587 * Return number of edges for given element
5589 //=============================================================================
5591 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const SMESH::smIdType id)
5594 _preMeshInfo->FullLoadFromFile();
5596 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5597 if ( aMeshDS == NULL ) return -1;
5598 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5599 if(!elem) return -1;
5600 return elem->NbEdges();
5604 //=============================================================================
5606 * Return number of faces for given element
5608 //=============================================================================
5610 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const SMESH::smIdType id)
5613 _preMeshInfo->FullLoadFromFile();
5615 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5616 if ( aMeshDS == NULL ) return -1;
5617 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5618 if(!elem) return -1;
5619 return elem->NbFaces();
5622 //================================================================================
5624 * \brief Return nodes of given face (counted from zero) for given element.
5626 //================================================================================
5628 SMESH::smIdType_array* SMESH_Mesh_i::GetElemFaceNodes(SMESH::smIdType elemId,
5629 CORBA::Short faceIndex)
5632 _preMeshInfo->FullLoadFromFile();
5634 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5635 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5637 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) )
5639 SMDS_VolumeTool vtool( elem, /*skipCentralNodes = */false );
5640 if ( faceIndex < vtool.NbFaces() )
5642 aResult->length( vtool.NbFaceNodes( faceIndex ));
5643 const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
5644 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5645 aResult[ i ] = nn[ i ]->GetID();
5649 return aResult._retn();
5652 //================================================================================
5654 * \brief Return three components of normal of given mesh face.
5656 //================================================================================
5658 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long elemId,
5659 CORBA::Boolean normalized)
5662 _preMeshInfo->FullLoadFromFile();
5664 SMESH::double_array_var aResult = new SMESH::double_array();
5666 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5669 if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
5671 aResult->length( 3 );
5672 aResult[ 0 ] = normal.X();
5673 aResult[ 1 ] = normal.Y();
5674 aResult[ 2 ] = normal.Z();
5677 return aResult._retn();
5680 //================================================================================
5682 * \brief Return an element based on all given nodes.
5684 //================================================================================
5686 SMESH::smIdType SMESH_Mesh_i::FindElementByNodes(const SMESH::smIdType_array& nodes)
5689 _preMeshInfo->FullLoadFromFile();
5691 CORBA::Long elemID(0);
5692 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5694 vector< const SMDS_MeshNode * > nn( nodes.length() );
5695 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5696 if ( !( nn[i] = mesh->FindNode( nodes[i] )))
5699 const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
5700 if ( !elem && ( _impl->NbEdges ( ORDER_QUADRATIC ) ||
5701 _impl->NbFaces ( ORDER_QUADRATIC ) ||
5702 _impl->NbVolumes( ORDER_QUADRATIC )))
5703 elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
5705 if ( elem ) elemID = CORBA::Long( elem->GetID() );
5710 //================================================================================
5712 * \brief Return elements including all given nodes.
5714 //================================================================================
5716 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsByNodes(const SMESH::smIdType_array& nodes,
5717 SMESH::ElementType elemType)
5720 _preMeshInfo->FullLoadFromFile();
5722 SMESH::smIdType_array_var result = new SMESH::smIdType_array();
5724 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5726 vector< const SMDS_MeshNode * > nn( nodes.length() );
5727 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5728 nn[i] = mesh->FindNode( nodes[i] );
5730 std::vector<const SMDS_MeshElement *> elems;
5731 mesh->GetElementsByNodes( nn, elems, (SMDSAbs_ElementType) elemType );
5732 result->length( elems.size() );
5733 for ( size_t i = 0; i < elems.size(); ++i )
5734 result[i] = elems[i]->GetID();
5736 return result._retn();
5739 //=============================================================================
5741 * Return true if given element is polygon
5743 //=============================================================================
5745 CORBA::Boolean SMESH_Mesh_i::IsPoly(const SMESH::smIdType id)
5748 _preMeshInfo->FullLoadFromFile();
5750 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5751 if ( aMeshDS == NULL ) return false;
5752 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5753 if(!elem) return false;
5754 return elem->IsPoly();
5758 //=============================================================================
5760 * Return true if given element is quadratic
5762 //=============================================================================
5764 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const SMESH::smIdType id)
5767 _preMeshInfo->FullLoadFromFile();
5769 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5770 if ( aMeshDS == NULL ) return false;
5771 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5772 if(!elem) return false;
5773 return elem->IsQuadratic();
5776 //=============================================================================
5778 * Return diameter of ball discrete element or zero in case of an invalid \a id
5780 //=============================================================================
5782 CORBA::Double SMESH_Mesh_i::GetBallDiameter(SMESH::smIdType id)
5785 _preMeshInfo->FullLoadFromFile();
5787 if ( const SMDS_BallElement* ball =
5788 SMDS_Mesh::DownCast<SMDS_BallElement>( _impl->GetMeshDS()->FindElement( id )))
5789 return ball->GetDiameter();
5794 //=============================================================================
5796 * Return bary center for given element
5798 //=============================================================================
5800 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const SMESH::smIdType id)
5803 _preMeshInfo->FullLoadFromFile();
5805 SMESH::double_array_var aResult = new SMESH::double_array();
5806 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5807 if ( aMeshDS == NULL )
5808 return aResult._retn();
5810 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5812 return aResult._retn();
5814 if(elem->GetType()==SMDSAbs_Volume) {
5815 SMDS_VolumeTool aTool;
5816 if(aTool.Set(elem)) {
5818 if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
5823 SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
5825 double x=0., y=0., z=0.;
5826 for(; anIt->more(); ) {
5828 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
5842 return aResult._retn();
5845 //================================================================================
5847 * \brief Create a group of elements preventing computation of a sub-shape
5849 //================================================================================
5851 SMESH::ListOfGroups*
5852 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int theSubShapeID,
5853 const char* theGroupName )
5855 Unexpect aCatch(SALOME_SalomeException);
5857 if ( !theGroupName || strlen( theGroupName) == 0 )
5858 THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
5860 SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
5861 ::SMESH_MeshEditor::ElemFeatures elemType;
5863 // submesh by subshape id
5864 if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
5865 if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
5868 SMESH_ComputeErrorPtr error = sm->GetComputeError();
5869 if ( error && error->HasBadElems() )
5871 // sort bad elements by type
5872 vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
5873 const list<const SMDS_MeshElement*>& badElems =
5874 static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
5875 list<const SMDS_MeshElement*>::const_iterator elemIt = badElems.begin();
5876 list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
5877 for ( ; elemIt != elemEnd; ++elemIt )
5879 const SMDS_MeshElement* elem = *elemIt;
5880 if ( !elem ) continue;
5882 if ( elem->GetID() < 1 )
5884 // elem is a temporary element, make a real element
5885 vector< const SMDS_MeshNode* > nodes;
5886 SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
5887 while ( nIt->more() && elem )
5889 nodes.push_back( nIt->next() );
5890 if ( nodes.back()->GetID() < 1 )
5891 elem = 0; // a temporary element on temporary nodes
5895 ::SMESH_MeshEditor editor( _impl );
5896 elem = editor.AddElement( nodes, elemType.Init( elem ));
5900 elemsByType[ elem->GetType() ].push_back( elem );
5903 // how many groups to create?
5905 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5906 nbTypes += int( !elemsByType[ i ].empty() );
5907 groups->length( nbTypes );
5910 for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
5912 vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
5913 if ( elems.empty() ) continue;
5915 groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
5916 if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
5918 SMESH::SMESH_Mesh_var mesh = _this();
5919 SALOMEDS::SObject_wrap aSO =
5920 _gen_i->PublishGroup( mesh, groups[ iG ],
5921 GEOM::GEOM_Object::_nil(), theGroupName);
5923 SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
5924 if ( !grp_i ) continue;
5926 if ( SMESHDS_Group* grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
5927 for ( size_t iE = 0; iE < elems.size(); ++iE )
5928 grpDS->SMDSGroup().Add( elems[ iE ]);
5933 return groups._retn();
5936 //=============================================================================
5938 * Create and publish group servants if any groups were imported or created anyhow
5940 //=============================================================================
5942 void SMESH_Mesh_i::CreateGroupServants()
5944 SMESH::SMESH_Mesh_var aMesh = _this();
5947 ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
5948 while ( groupIt->more() )
5950 ::SMESH_Group* group = groupIt->next();
5951 int anId = group->GetID();
5953 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
5954 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5956 addedIDs.insert( anId );
5958 SMESH_GroupBase_i* aGroupImpl;
5960 if ( SMESHDS_GroupOnGeom* groupOnGeom =
5961 dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
5963 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
5964 shape = groupOnGeom->GetShape();
5967 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
5970 SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
5971 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
5972 aGroupImpl->Register();
5974 // register CORBA object for persistence
5975 int nextId = _gen_i->RegisterObject( groupVar );
5976 MESSAGE( "Add group to map with id = "<< nextId);
5978 // publishing the groups in the study
5979 GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
5980 _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName());
5983 if ( !addedIDs.empty() )
5986 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
5987 for ( int index = 0; i_grp != _mapGroups.end(); ++index, ++i_grp )
5989 set<int>::iterator it = addedIDs.find( i_grp->first );
5990 if ( it != addedIDs.end() )
5992 TPythonDump() << i_grp->second << " = " << aMesh << ".GetGroups()[ "<< index << " ]";
5993 addedIDs.erase( it );
5994 if ( addedIDs.empty() )
6001 //=============================================================================
6003 * \brief Return true if all sub-meshes are computed OK - to update an icon
6005 //=============================================================================
6007 CORBA::Boolean SMESH_Mesh_i::IsComputedOK()
6009 return _impl->IsComputedOK();
6012 //=============================================================================
6014 * \brief Return groups cantained in _mapGroups by their IDs
6016 //=============================================================================
6018 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
6020 int nbGroups = groupIDs.size();
6021 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
6022 aList->length( nbGroups );
6024 list<int>::const_iterator ids = groupIDs.begin();
6025 for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
6027 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
6028 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
6029 aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
6031 aList->length( nbGroups );
6032 return aList._retn();
6035 //=============================================================================
6037 * \brief Return information about imported file
6039 //=============================================================================
6041 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
6043 SMESH::MedFileInfo_var res( _medFileInfo );
6044 if ( !res.operator->() ) {
6045 res = new SMESH::MedFileInfo;
6047 res->fileSize = res->major = res->minor = res->release = -1;
6052 //=======================================================================
6053 //function : FileInfoToString
6054 //purpose : Persistence of file info
6055 //=======================================================================
6057 std::string SMESH_Mesh_i::FileInfoToString()
6060 if ( &_medFileInfo.in() && _medFileInfo->fileName[0] )
6062 s = SMESH_Comment( _medFileInfo->fileSize )
6063 << " " << _medFileInfo->major
6064 << " " << _medFileInfo->minor
6065 << " " << _medFileInfo->release
6066 << " " << _medFileInfo->fileName;
6071 //=======================================================================
6072 //function : FileInfoFromString
6073 //purpose : Persistence of file info
6074 //=======================================================================
6076 void SMESH_Mesh_i::FileInfoFromString(const std::string& info)
6078 std::string size, major, minor, release, fileName;
6079 std::istringstream is(info);
6080 is >> size >> major >> minor >> release;
6081 fileName = info.data() + ( size.size() + 1 +
6084 release.size()+ 1 );
6086 _medFileInfo = new SMESH::MedFileInfo();
6087 _medFileInfo->fileName = fileName.c_str();
6088 _medFileInfo->fileSize = atoi( size.c_str() );
6089 _medFileInfo->major = atoi( major.c_str() );
6090 _medFileInfo->minor = atoi( minor.c_str() );
6091 _medFileInfo->release = atoi( release.c_str() );
6094 //=============================================================================
6096 * \brief Pass names of mesh groups from study to mesh DS
6098 //=============================================================================
6100 void SMESH_Mesh_i::checkGroupNames()
6102 int nbGrp = NbGroups();
6106 SMESH::ListOfGroups* grpList = 0;
6107 // avoid dump of "GetGroups"
6109 // store python dump into a local variable inside local scope
6110 SMESH::TPythonDump pDump; // do not delete this line of code
6111 grpList = GetGroups();
6114 for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
6115 SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
6118 SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aGrp );
6119 if ( aGrpSO->_is_nil() )
6121 // correct name of the mesh group if necessary
6122 const char* guiName = aGrpSO->GetName();
6123 if ( strcmp(guiName, aGrp->GetName()) )
6124 aGrp->SetName( guiName );
6128 //=============================================================================
6130 * \brief Set list of notebook variables used for Mesh operations separated by ":" symbol
6132 //=============================================================================
6133 void SMESH_Mesh_i::SetParameters(const char* theParameters)
6135 SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
6139 //=============================================================================
6141 * \brief Return list of notebook variables used for Mesh operations separated by ":" symbol
6143 //=============================================================================
6145 char* SMESH_Mesh_i::GetParameters()
6147 return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
6150 //=============================================================================
6152 * \brief Return list of notebook variables used for last Mesh operation
6154 //=============================================================================
6155 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
6157 SMESH::string_array_var aResult = new SMESH::string_array();
6158 SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
6160 CORBA::String_var aParameters = GetParameters();
6161 SALOMEDS::ListOfListOfStrings_var aSections = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->ParseVariables(aParameters);
6162 if ( aSections->length() > 0 ) {
6163 SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
6164 aResult->length( aVars.length() );
6165 for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
6166 aResult[i] = CORBA::string_dup( aVars[i] );
6169 return aResult._retn();
6172 //================================================================================
6174 * \brief Return types of elements it contains
6176 //================================================================================
6178 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
6181 return _preMeshInfo->GetTypes();
6183 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
6187 if (_impl->NbEdges()) types[nbTypes++] = SMESH::EDGE;
6188 if (_impl->NbFaces()) types[nbTypes++] = SMESH::FACE;
6189 if (_impl->NbVolumes()) types[nbTypes++] = SMESH::VOLUME;
6190 if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
6191 if (_impl->NbBalls()) types[nbTypes++] = SMESH::BALL;
6192 if (_impl->NbNodes() &&
6193 nbTypes == 0 ) types[nbTypes++] = SMESH::NODE;
6194 types->length( nbTypes );
6196 return types._retn();
6199 //================================================================================
6201 * \brief Return self
6203 //================================================================================
6205 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
6207 return SMESH::SMESH_Mesh::_duplicate( _this() );
6210 //================================================================================
6212 * \brief Return false if GetMeshInfo() return incorrect information that may
6213 * happen if mesh data is not yet fully loaded from the file of study.
6217 //================================================================================
6219 bool SMESH_Mesh_i::IsMeshInfoCorrect()
6221 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
6224 //=============================================================================
6226 * \brief Return number of mesh elements per each \a EntityType
6228 //=============================================================================
6230 SMESH::smIdType_array* SMESH_Mesh_i::GetMeshInfo()
6233 return _preMeshInfo->GetMeshInfo();
6235 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
6236 aRes->length(SMESH::Entity_Last);
6237 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6239 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6241 return aRes._retn();
6242 const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
6243 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6244 aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
6245 return aRes._retn();
6248 //=============================================================================
6250 * \brief Return number of mesh elements per each \a ElementType
6252 //=============================================================================
6254 SMESH::smIdType_array* SMESH_Mesh_i::GetNbElementsByType()
6256 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
6257 aRes->length(SMESH::NB_ELEMENT_TYPES);
6258 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6261 const SMDS_MeshInfo* meshInfo = 0;
6263 meshInfo = _preMeshInfo;
6264 else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
6265 meshInfo = & meshDS->GetMeshInfo();
6268 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6269 aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
6271 return aRes._retn();
6274 //=============================================================================
6276 * Collect statistic of mesh elements given by iterator
6278 //=============================================================================
6280 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
6281 SMESH::smIdType_array& theInfo)
6283 if (!theItr) return;
6284 while (theItr->more())
6285 theInfo[ theItr->next()->GetEntityType() ]++;
6287 //=============================================================================
6289 * Return mesh unstructed grid information.
6291 //=============================================================================
6293 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
6295 SALOMEDS::TMPFile_var SeqFile;
6296 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
6297 SMDS_UnstructuredGrid* aGrid = aMeshDS->GetGrid();
6299 vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
6300 aWriter->WriteToOutputStringOn();
6301 aWriter->SetInputData(aGrid);
6302 aWriter->SetFileTypeToBinary();
6304 char* str = aWriter->GetOutputString();
6305 int size = aWriter->GetOutputStringLength();
6307 //Allocate octet buffer of required size
6308 CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
6309 //Copy ostrstream content to the octet buffer
6310 memcpy(OctetBuf, str, size);
6311 //Create and return TMPFile
6312 SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
6316 return SeqFile._retn();
6319 //=============================================================================
6320 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
6321 * SMESH::ElementType type) */
6323 using namespace SMESH::Controls;
6324 //-----------------------------------------------------------------------------
6325 struct PredicateIterator : public SMDS_ElemIterator
6327 SMDS_ElemIteratorPtr _elemIter;
6328 PredicatePtr _predicate;
6329 const SMDS_MeshElement* _elem;
6330 SMDSAbs_ElementType _type;
6332 PredicateIterator( SMDS_ElemIteratorPtr iterator,
6333 PredicatePtr predicate,
6334 SMDSAbs_ElementType type):
6335 _elemIter(iterator), _predicate(predicate), _type(type)
6343 virtual const SMDS_MeshElement* next()
6345 const SMDS_MeshElement* res = _elem;
6347 while ( _elemIter->more() && !_elem )
6349 if ((_elem = _elemIter->next()) &&
6350 (( _type != SMDSAbs_All && _type != _elem->GetType() ) ||
6351 ( !_predicate->IsSatisfy( _elem->GetID() ))))
6358 //-----------------------------------------------------------------------------
6359 struct IDSourceIterator : public SMDS_ElemIterator
6361 const SMESH::smIdType* _idPtr;
6362 const SMESH::smIdType* _idEndPtr;
6363 SMESH::smIdType_array_var _idArray;
6364 const SMDS_Mesh* _mesh;
6365 const SMDSAbs_ElementType _type;
6366 const SMDS_MeshElement* _elem;
6368 IDSourceIterator( const SMDS_Mesh* mesh,
6369 const SMESH::smIdType* ids,
6370 const smIdType nbIds,
6371 SMDSAbs_ElementType type):
6372 _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
6374 if ( _idPtr && nbIds && _mesh )
6377 IDSourceIterator( const SMDS_Mesh* mesh,
6378 SMESH::smIdType_array* idArray,
6379 SMDSAbs_ElementType type):
6380 _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
6382 if ( idArray && _mesh )
6384 _idPtr = &_idArray[0];
6385 _idEndPtr = _idPtr + _idArray->length();
6393 virtual const SMDS_MeshElement* next()
6395 const SMDS_MeshElement* res = _elem;
6397 while ( _idPtr < _idEndPtr && !_elem )
6399 if ( _type == SMDSAbs_Node )
6401 _elem = _mesh->FindNode( *_idPtr++ );
6403 else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
6404 (_elem->GetType() != _type && _type != SMDSAbs_All ))
6412 //-----------------------------------------------------------------------------
6414 struct NodeOfElemIterator : public SMDS_ElemIterator
6416 TColStd_MapOfInteger _checkedNodeIDs;
6417 SMDS_ElemIteratorPtr _elemIter;
6418 SMDS_ElemIteratorPtr _nodeIter;
6419 const SMDS_MeshElement* _node;
6421 NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
6423 if ( _elemIter && _elemIter->more() )
6425 _nodeIter = _elemIter->next()->nodesIterator();
6433 virtual const SMDS_MeshElement* next()
6435 const SMDS_MeshElement* res = _node;
6437 while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
6439 if ( _nodeIter->more() )
6441 _node = _nodeIter->next();
6442 if ( !_checkedNodeIDs.Add( _node->GetID() ))
6447 _nodeIter = _elemIter->next()->nodesIterator();
6455 //=============================================================================
6457 * Return iterator on elements of given type in given object
6459 //=============================================================================
6461 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
6462 SMESH::ElementType theType)
6464 SMDS_ElemIteratorPtr elemIt;
6465 bool typeOK = ( theType == SMESH::ALL );
6466 SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
6468 SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
6469 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
6470 if ( !mesh_i ) return elemIt;
6471 SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
6473 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
6475 elemIt = meshDS->elementsIterator( elemType );
6478 else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
6480 SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
6483 elemIt = sm->GetElements();
6484 if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6486 typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
6487 elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
6491 else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
6493 SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
6494 if ( groupDS && ( elemType == groupDS->GetType() ||
6495 elemType == SMDSAbs_Node ||
6496 elemType == SMDSAbs_All ))
6498 elemIt = groupDS->GetElements();
6499 typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
6502 else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
6504 if ( filter_i->GetElementType() == theType ||
6505 filter_i->GetElementType() == SMESH::ALL ||
6506 elemType == SMDSAbs_Node ||
6507 elemType == SMDSAbs_All)
6509 SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
6510 if ( pred_i && pred_i->GetPredicate() )
6512 SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
6513 SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
6514 SMDSAbs_ElementType iterType = elemType == SMDSAbs_Node ? filterType : elemType;
6515 elemIt = SMDS_ElemIteratorPtr
6516 ( new PredicateIterator( allElemIt, pred_i->GetPredicate(), iterType ));
6517 typeOK = ( elemType == SMDSAbs_Node ? filterType == SMDSAbs_Node : elemIt->more() );
6523 SMESH::array_of_ElementType_var types = theObject->GetTypes();
6524 const bool isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
6525 if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6527 SMDSAbs_ElementType iterType = isNodes ? SMDSAbs_Node : elemType;
6528 if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
6530 SMESH::smIdType nbIds;
6531 if ( SMESH::smIdType* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
6532 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, iterType ));
6536 SMESH::smIdType_array_var ids = theObject->GetIDs();
6537 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), iterType ));
6539 typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
6542 if ( elemIt && elemIt->more() && !typeOK )
6544 if ( elemType == SMDSAbs_Node )
6546 elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
6550 elemIt = SMDS_ElemIteratorPtr();
6556 //=============================================================================
6557 namespace // Finding concurrent hypotheses
6558 //=============================================================================
6562 * \brief mapping of mesh dimension into shape type
6564 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
6566 TopAbs_ShapeEnum aType = TopAbs_SOLID;
6568 case 0: aType = TopAbs_VERTEX; break;
6569 case 1: aType = TopAbs_EDGE; break;
6570 case 2: aType = TopAbs_FACE; break;
6572 default:aType = TopAbs_SOLID; break;
6577 //-----------------------------------------------------------------------------
6579 * \brief Internal structure used to find concurrent submeshes
6581 * It represents a pair < submesh, concurrent dimension >, where
6582 * 'concurrent dimension' is dimension of shape where the submesh can concurrent
6583 * with another submesh. In other words, it is dimension of a hypothesis assigned
6590 int _dim; //!< a dimension the algo can build (concurrent dimension)
6591 int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
6592 TopTools_MapOfShape _shapeMap; //!< [sub-]shapes of dimension == _dim
6593 const SMESH_subMesh* _subMesh;
6594 list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
6596 //-----------------------------------------------------------------------------
6597 // Return the algorithm
6598 const SMESH_Algo* GetAlgo() const
6599 { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
6601 //-----------------------------------------------------------------------------
6603 SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
6605 const TopoDS_Shape& theShape)
6607 _subMesh = theSubMesh;
6608 SetShape( theDim, theShape );
6611 //-----------------------------------------------------------------------------
6613 void SetShape(const int theDim,
6614 const TopoDS_Shape& theShape)
6617 _ownDim = SMESH_Gen::GetShapeDim(theShape);
6618 if (_dim >= _ownDim)
6619 _shapeMap.Add( theShape );
6621 TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
6622 for( ; anExp.More(); anExp.Next() )
6623 _shapeMap.Add( anExp.Current() );
6627 //-----------------------------------------------------------------------------
6628 //! Check sharing of sub-shapes
6629 static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
6630 const TopTools_MapOfShape& theToFind,
6631 const TopAbs_ShapeEnum theType)
6633 bool isShared = false;
6634 TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
6635 for (; !isShared && anItr.More(); anItr.Next() )
6637 const TopoDS_Shape& aSubSh = anItr.Key();
6638 // check for case when concurrent dimensions are same
6639 isShared = theToFind.Contains( aSubSh );
6640 // check for sub-shape with concurrent dimension
6641 TopExp_Explorer anExp( aSubSh, theType );
6642 for ( ; !isShared && anExp.More(); anExp.Next() )
6643 isShared = theToFind.Contains( anExp.Current() );
6648 //-----------------------------------------------------------------------------
6649 //! check algorithms
6650 static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
6651 const SMESHDS_Hypothesis* theA2)
6653 if ( !theA1 || !theA2 ||
6654 theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
6655 theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
6656 return false; // one of the hypothesis is not algorithm
6657 // check algorithm names (should be equal)
6658 return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
6662 //-----------------------------------------------------------------------------
6663 //! Check if sub-shape hypotheses are concurrent
6664 bool IsConcurrent(const SMESH_DimHyp* theOther) const
6666 if ( _subMesh == theOther->_subMesh )
6667 return false; // same sub-shape - should not be
6669 // if ( <own dim of either of submeshes> == <concurrent dim> &&
6670 // any of the two submeshes is not on COMPOUND shape )
6671 // -> no concurrency
6672 bool meIsCompound = (_subMesh->GetSubMeshDS() &&
6673 _subMesh->GetSubMeshDS()->IsComplexSubmesh());
6674 bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
6675 theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
6676 if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
6679 bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
6680 if ( !checkSubShape )
6683 // check algorithms to be same
6684 const SMESH_Algo* a1 = this->GetAlgo();
6685 const SMESH_Algo* a2 = theOther->GetAlgo();
6686 bool isSame = checkAlgo( a1, a2 );
6690 // commented off for IPAL54678
6691 // if ( !a1 || !a2 )
6692 // return false; // pb?
6693 // return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency !
6696 // check hypothesises for concurrence (skip first as algorithm)
6698 // pointers should be same, because it is referened from mesh hypothesis partition
6699 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
6700 list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
6701 for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
6702 if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
6704 // the submeshes are concurrent if their algorithms has different parameters
6705 return nbSame != theOther->_hypotheses.size() - 1;
6708 // Return true if algorithm of this SMESH_DimHyp is used if no
6709 // sub-mesh order is imposed by the user
6710 bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
6712 // NeedDiscreteBoundary() algo has a higher priority
6713 if ( this ->GetAlgo()->NeedDiscreteBoundary() !=
6714 theOther->GetAlgo()->NeedDiscreteBoundary() )
6715 return !this->GetAlgo()->NeedDiscreteBoundary();
6717 return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
6720 }; // end of SMESH_DimHyp
6721 //-----------------------------------------------------------------------------
6723 typedef list<const SMESH_DimHyp*> TDimHypList;
6725 //-----------------------------------------------------------------------------
6727 void addDimHypInstance(const int theDim,
6728 const TopoDS_Shape& theShape,
6729 const SMESH_Algo* theAlgo,
6730 const SMESH_subMesh* theSubMesh,
6731 const list <const SMESHDS_Hypothesis*>& theHypList,
6732 TDimHypList* theDimHypListArr )
6734 if ( !theAlgo->NeedDiscreteBoundary() &&
6735 theAlgo->NeedLowerHyps( theDim )) // IPAL54678
6737 TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
6738 if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh )
6740 SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
6741 dimHyp->_hypotheses.push_front(theAlgo);
6742 listOfdimHyp.push_back( dimHyp );
6745 SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
6746 dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
6747 theHypList.begin(), theHypList.end() );
6750 //-----------------------------------------------------------------------------
6751 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
6752 TDimHypList& theListOfConcurr)
6754 if ( theListOfConcurr.empty() )
6756 theListOfConcurr.push_back( theDimHyp );
6760 TDimHypList::iterator hypIt = theListOfConcurr.begin();
6761 while ( hypIt != theListOfConcurr.end() &&
6762 !theDimHyp->IsHigherPriorityThan( *hypIt ))
6764 theListOfConcurr.insert( hypIt, theDimHyp );
6768 //-----------------------------------------------------------------------------
6769 void findConcurrents(const SMESH_DimHyp* theDimHyp,
6770 const TDimHypList& theListOfDimHyp,
6771 TDimHypList& theListOfConcurrHyp,
6772 set<int>& theSetOfConcurrId )
6774 TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
6775 for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
6777 const SMESH_DimHyp* curDimHyp = *rIt;
6778 if ( curDimHyp == theDimHyp )
6779 break; // meet own dimHyp pointer in same dimension
6781 if ( theDimHyp->IsConcurrent( curDimHyp ) &&
6782 theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
6784 addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
6789 //-----------------------------------------------------------------------------
6790 bool unionLists(TListOfInt& theListOfId,
6791 TListOfListOfInt& theListOfListOfId,
6794 bool changed = false;
6795 if ( theListOfId.empty() )
6797 TListOfListOfInt::iterator it = theListOfListOfId.begin();
6798 for ( int i = 0; it != theListOfListOfId.end(); it++, i++ )
6801 continue; //skip already treated lists
6802 // check if other list has any same submesh object
6803 TListOfInt& otherListOfId = *it;
6804 if ( find_first_of( theListOfId.begin(), theListOfId.end(),
6805 otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
6808 // union two lists (from source into target)
6809 TListOfInt::iterator it2 = otherListOfId.begin();
6810 for ( ; it2 != otherListOfId.end(); it2++ ) {
6811 if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
6813 theListOfId.push_back(*it2);
6817 // clear source list
6818 otherListOfId.clear();
6822 //-----------------------------------------------------------------------------
6824 //! free memory allocated for dimension-hypothesis objects
6825 void removeDimHyps( TDimHypList* theArrOfList )
6827 for (int i = 0; i < 4; i++ ) {
6828 TDimHypList& listOfdimHyp = theArrOfList[i];
6829 TDimHypList::const_iterator it = listOfdimHyp.begin();
6830 for ( ; it != listOfdimHyp.end(); it++ )
6835 //-----------------------------------------------------------------------------
6837 * \brief find common submeshes with given submesh
6838 * \param theSubMeshList list of already collected submesh to check
6839 * \param theSubMesh given submesh to intersect with other
6840 * \param theCommonSubMeshes collected common submeshes
6842 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
6843 const SMESH_subMesh* theSubMesh,
6844 set<const SMESH_subMesh*>& theCommon )
6848 list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
6849 for ( ; it != theSubMeshList.end(); it++ )
6850 theSubMesh->FindIntersection( *it, theCommon );
6851 theSubMeshList.push_back( theSubMesh );
6852 //theCommon.insert( theSubMesh );
6855 //-----------------------------------------------------------------------------
6856 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
6858 TListOfListOfInt::const_iterator listsIt = smLists.begin();
6859 for ( ; listsIt != smLists.end(); ++listsIt )
6861 const TListOfInt& smIDs = *listsIt;
6862 if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
6870 //=============================================================================
6872 * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
6874 //=============================================================================
6876 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
6878 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6879 if ( isSubMeshInList( submeshID, anOrder ))
6882 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6883 return isSubMeshInList( submeshID, allConurrent );
6886 //=============================================================================
6888 * \brief Return sub-mesh objects list in meshing order
6890 //=============================================================================
6892 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
6894 SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
6896 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6898 return aResult._retn();
6900 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6901 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6902 anOrder.splice( anOrder.end(), allConurrent );
6907 TListOfListOfInt::iterator listIt = anOrder.begin();
6908 for ( int listIndx = 1; listIt != anOrder.end(); listIt++, listIndx++ )
6909 if ( unionLists( *listIt, anOrder, listIndx ))
6914 // convert submesh ids into interface instances
6915 // and dump command into python
6916 convertMeshOrder( anOrder, aResult, false );
6918 return aResult._retn();
6921 //=============================================================================
6923 * \brief Finds concurrent sub-meshes
6925 //=============================================================================
6927 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
6929 TListOfListOfInt anOrder;
6930 ::SMESH_Mesh& mesh = GetImpl();
6932 // collect submeshes and detect concurrent algorithms and hypothesises
6933 TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
6935 map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
6936 for ( ; i_sm != _mapSubMesh.end(); i_sm++ )
6938 ::SMESH_subMesh* sm = (*i_sm).second;
6940 const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
6942 // list of assigned hypothesises
6943 const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
6944 // Find out dimensions where the submesh can be concurrent.
6945 // We define the dimensions by algo of each of hypotheses in hypList
6946 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
6947 for( ; hypIt != hypList.end(); hypIt++ )
6949 SMESH_Algo* anAlgo = 0;
6950 const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
6951 if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
6952 // hyp it-self is algo
6953 anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
6955 // try to find algorithm with help of sub-shapes
6956 TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
6957 for ( ; !anAlgo && anExp.More(); anExp.Next() )
6958 anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
6961 continue; // no algorithm assigned to a current submesh
6963 int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
6964 // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary()
6965 // and !anAlgo->NeedLowerHyps( dim ))
6967 // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
6968 for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
6969 addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
6971 } // end iterations on submesh
6973 // iterate on created dimension-hypotheses and check for concurrents
6974 for ( int i = 0; i < 4; i++ )
6976 const TDimHypList& listOfDimHyp = dimHypListArr[i];
6977 // check for concurrents in own and other dimensions (step-by-step)
6978 TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
6979 for ( ; dhIt != listOfDimHyp.end(); dhIt++ )
6981 const SMESH_DimHyp* dimHyp = *dhIt;
6982 TDimHypList listOfConcurr;
6983 set<int> setOfConcurrIds;
6984 // looking for concurrents and collect into own list
6985 for ( int j = i; j < 4; j++ )
6986 findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
6987 // check if any concurrents found
6988 if ( listOfConcurr.size() > 0 )
6990 // add own submesh to list of concurrent
6991 addInOrderOfPriority( dimHyp, listOfConcurr );
6992 list<int> listOfConcurrIds;
6993 TDimHypList::iterator hypIt = listOfConcurr.begin();
6994 for ( ; hypIt != listOfConcurr.end(); ++hypIt )
6995 listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
6996 anOrder.push_back( listOfConcurrIds );
7001 removeDimHyps(dimHypListArr);
7003 // now, minimize the number of concurrent groups
7004 // Here we assume that lists of submeshes can have same submesh
7005 // in case of multi-dimension algorithms, as result
7006 // list with common submesh has to be united into one list
7008 TListOfListOfInt::iterator listIt = anOrder.begin();
7009 for(; listIt != anOrder.end(); listIt++, listIndx++ )
7010 unionLists( *listIt, anOrder, listIndx + 1 );
7015 //=============================================================================
7017 * \brief Set submesh object order
7018 * \param theSubMeshArray submesh array order
7020 //=============================================================================
7022 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
7025 _preMeshInfo->ForgetOrLoad();
7028 ::SMESH_Mesh& mesh = GetImpl();
7030 TPythonDump aPythonDump; // prevent dump of called methods
7031 aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
7033 TListOfListOfInt subMeshOrder;
7034 for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
7036 const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
7037 TListOfInt subMeshIds;
7039 aPythonDump << ", ";
7040 aPythonDump << "[ ";
7041 // Collect subMeshes which should be clear
7042 // do it list-by-list, because modification of submesh order
7043 // take effect between concurrent submeshes only
7044 set<const SMESH_subMesh*> subMeshToClear;
7045 list<const SMESH_subMesh*> subMeshList;
7046 for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
7048 const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
7050 aPythonDump << ", ";
7051 aPythonDump << subMesh;
7052 subMeshIds.push_back( subMesh->GetId() );
7053 // detect common parts of submeshes
7054 if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
7055 findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
7057 aPythonDump << " ]";
7058 subMeshOrder.push_back( subMeshIds );
7060 // clear collected sub-meshes
7061 set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
7062 for ( ; clrIt != subMeshToClear.end(); clrIt++ )
7063 if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
7065 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
7066 if ( SMESH_Algo* algo = sm->GetAlgo() ) // #16748
7067 sm->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, algo ); // to clear a cached algo
7070 aPythonDump << " ])";
7072 mesh.SetMeshOrder( subMeshOrder );
7075 SMESH::SMESH_Mesh_var me = _this();
7076 _gen_i->UpdateIcons( me );
7082 //=============================================================================
7084 * \brief Convert submesh ids into submesh interfaces
7086 //=============================================================================
7088 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt& theIdsOrder,
7089 SMESH::submesh_array_array& theResOrder,
7090 const bool theIsDump)
7092 int nbSet = theIdsOrder.size();
7093 TPythonDump aPythonDump; // prevent dump of called methods
7095 aPythonDump << "[ ";
7096 theResOrder.length(nbSet);
7097 TListOfListOfInt::const_iterator it = theIdsOrder.begin();
7099 for( ; it != theIdsOrder.end(); it++ )
7101 // translate submesh identificators into submesh objects
7102 // takeing into account real number of concurrent lists
7103 const TListOfInt& aSubOrder = (*it);
7104 if (!aSubOrder.size())
7107 aPythonDump << "[ ";
7108 // convert shape indices into interfaces
7109 SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
7110 aResSubSet->length(aSubOrder.size());
7111 TListOfInt::const_iterator subIt = aSubOrder.begin();
7113 for( j = 0; subIt != aSubOrder.end(); subIt++ )
7115 if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
7117 SMESH::SMESH_subMesh_var subMesh =
7118 SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
7121 aPythonDump << ", ";
7122 aPythonDump << subMesh;
7124 aResSubSet[ j++ ] = subMesh;
7127 aPythonDump << " ]";
7129 theResOrder[ listIndx++ ] = aResSubSet;
7131 // correct number of lists
7132 theResOrder.length( listIndx );
7135 // finilise python dump
7136 aPythonDump << " ]";
7137 aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
7141 namespace // utils used by SMESH_MeshPartDS
7144 * \brief Class used to access to protected data of SMDS_MeshInfo
7146 struct TMeshInfo : public SMDS_MeshInfo
7148 void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
7151 * \brief Element holing its ID only
7153 struct TElemID : public SMDS_LinearEdge
7155 TElemID(int ID) : SMDS_LinearEdge(0,0) { setID( ID ); }
7159 //================================================================================
7161 // Implementation of SMESH_MeshPartDS
7163 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
7164 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
7166 SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
7167 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
7170 _meshDS = mesh_i->GetImpl().GetMeshDS();
7172 SetPersistentId( _meshDS->GetPersistentId() );
7174 if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
7176 // <meshPart> is the whole mesh
7177 myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
7179 set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
7180 myGroupSet = _meshDS->GetGroups();
7185 SMESH::smIdType_array_var anIDs = meshPart->GetIDs();
7186 SMESH::array_of_ElementType_var types = meshPart->GetTypes();
7187 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
7189 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7190 if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
7191 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7196 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7197 if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
7198 if ( _elements[ e->GetType() ].insert( e ).second )
7201 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7202 while ( nIt->more() )
7204 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7205 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7212 ShapeToMesh( _meshDS->ShapeToMesh() );
7214 _meshDS = 0; // to enforce iteration on _elements and _nodes
7217 // -------------------------------------------------------------------------------------
7218 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
7219 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
7222 list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
7223 for ( ; partIt != meshPart.end(); ++partIt )
7224 if ( const SMDS_MeshElement * e = *partIt )
7225 if ( _elements[ e->GetType() ].insert( e ).second )
7228 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7229 while ( nIt->more() )
7231 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7232 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7238 // -------------------------------------------------------------------------------------
7239 const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const
7241 if ( _meshDS ) return _meshDS->FindElement( IDelem );
7243 TElemID elem( IDelem );
7244 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7245 if ( !_elements[ iType ].empty() )
7247 TIDSortedElemSet::const_iterator it = _elements[ iType ].find( &elem );
7248 if ( it != _elements[ iType ].end() )
7253 // -------------------------------------------------------------------------------------
7254 bool SMESH_MeshPartDS::HasNumerationHoles()
7256 if ( _meshDS ) return _meshDS->HasNumerationHoles();
7258 return ( MinNodeID() != 1 ||
7259 MaxNodeID() != NbNodes() ||
7260 MinElementID() != 1 ||
7261 MaxElementID() != NbElements() );
7263 // -------------------------------------------------------------------------------------
7264 smIdType SMESH_MeshPartDS::MaxNodeID() const
7266 if ( _meshDS ) return _meshDS->MaxNodeID();
7267 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].rbegin())->GetID();
7269 // -------------------------------------------------------------------------------------
7270 smIdType SMESH_MeshPartDS::MinNodeID() const
7272 if ( _meshDS ) return _meshDS->MinNodeID();
7273 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].begin())->GetID();
7275 // -------------------------------------------------------------------------------------
7276 smIdType SMESH_MeshPartDS::MaxElementID() const
7278 if ( _meshDS ) return _meshDS->MaxElementID();
7280 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7281 if ( !_elements[ iType ].empty() )
7282 maxID = std::max( maxID, (*_elements[ iType ].rbegin())->GetID() );
7285 // -------------------------------------------------------------------------------------
7286 smIdType SMESH_MeshPartDS::MinElementID() const
7288 if ( _meshDS ) return _meshDS->MinElementID();
7290 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7291 if ( !_elements[ iType ].empty() )
7292 minID = std::min( minID, (*_elements[ iType ].begin())->GetID() );
7295 // -------------------------------------------------------------------------------------
7296 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
7298 if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
7300 typedef SMDS_SetIterator
7301 <const SMDS_MeshElement*,
7302 TIDSortedElemSet::const_iterator,
7303 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7304 SMDS_MeshElement::GeomFilter
7307 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( geomType );
7309 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7310 _elements[type].end(),
7311 SMDS_MeshElement::GeomFilter( geomType )));
7313 // -------------------------------------------------------------------------------------
7314 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
7316 if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
7318 typedef SMDS_SetIterator
7319 <const SMDS_MeshElement*,
7320 TIDSortedElemSet::const_iterator,
7321 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7322 SMDS_MeshElement::EntityFilter
7325 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( entity );
7327 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7328 _elements[type].end(),
7329 SMDS_MeshElement::EntityFilter( entity )));
7331 // -------------------------------------------------------------------------------------
7332 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
7334 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
7335 if ( type == SMDSAbs_All && !_meshDS )
7337 typedef vector< SMDS_ElemIteratorPtr > TIterVec;
7339 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
7340 if ( !_elements[i].empty() && i != SMDSAbs_Node )
7342 ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
7344 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
7345 return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
7347 return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
7348 ( new TIter( _elements[type].begin(), _elements[type].end() ));
7350 // -------------------------------------------------------------------------------------
7351 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType) \
7352 iterType SMESH_MeshPartDS::methName() const \
7354 typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
7355 return _meshDS ? _meshDS->methName() : iterType \
7356 ( new TIter( _elements[elemType].begin(), _elements[elemType].end() )); \
7358 // -------------------------------------------------------------------------------------
7359 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
7360 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
7361 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
7362 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
7363 #undef _GET_ITER_DEFINE
7365 // END Implementation of SMESH_MeshPartDS
7367 //================================================================================