1 // Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
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"
61 #include <SALOMEDS_Attributes_wrap.hxx>
62 #include <SALOMEDS_wrap.hxx>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <utilities.h>
66 #include <GEOMImpl_Types.hxx>
67 #include <GEOM_wrap.hxx>
70 #include <BRep_Builder.hxx>
71 #include <Standard_ErrorHandler.hxx>
72 #include <TColStd_MapOfInteger.hxx>
74 #include <TopExp_Explorer.hxx>
75 #include <TopTools_DataMapOfShapeShape.hxx>
76 #include <TopTools_MapIteratorOfMapOfShape.hxx>
77 #include <TopTools_MapOfShape.hxx>
78 #include <TopoDS_Compound.hxx>
85 #include <vtkUnstructuredGridWriter.h>
87 // to pass CORBA exception through SMESH_TRY
88 #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
90 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
93 static int MYDEBUG = 0;
95 static int MYDEBUG = 0;
99 using SMESH::TPythonDump;
102 int SMESH_Mesh_i::_idGenerator = 0;
104 //=============================================================================
108 //=============================================================================
110 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
112 : SALOME::GenericObj_i( thePOA )
116 _id = _idGenerator++;
119 _previewEditor = NULL;
124 //=============================================================================
128 //=============================================================================
130 SMESH_Mesh_i::~SMESH_Mesh_i()
133 map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
134 for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
135 if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
137 aGroup->UnRegister();
138 SMESH::SMESH_GroupBase_var( itGr->second );
143 map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
144 for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
145 if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
147 aSubMesh->UnRegister();
148 SMESH::SMESH_subMesh_var( itSM->second );
150 _mapSubMeshIor.clear();
152 // destroy hypotheses. _mapHypo contains all hyps ever been assigned
153 map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
154 for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
155 if ( SMESH_Hypothesis_i* hyp_i = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
156 if ( SMESH_Hypothesis * smHyp = _impl->GetHypothesis( itH->first ))
157 if ( _impl->GetMeshDS()->IsUsedHypothesis( smHyp ))
160 SMESH::SMESH_Hypothesis_var( itH->second ); // decref CORBA object
164 // clear cached shapes if no more meshes remain; (the cache is blame,
165 // together with publishing, of spent time increasing in issue 22874)
166 if ( _impl->NbMeshes() == 1 )
167 _gen_i->GetShapeReader()->ClearClientBuffer();
169 delete _editor; _editor = NULL;
170 delete _previewEditor; _previewEditor = NULL;
171 delete _impl; _impl = NULL;
172 delete _preMeshInfo; _preMeshInfo = NULL;
175 //=============================================================================
179 * Associate <this> mesh with <theShape> and put a reference
180 * to <theShape> into the current study;
181 * the previous shape is substituted by the new one.
183 //=============================================================================
185 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
186 throw (SALOME::SALOME_Exception)
188 Unexpect aCatch(SALOME_SalomeException);
190 _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
192 catch(SALOME_Exception & S_ex) {
193 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
195 // to track changes of GEOM groups
196 SMESH::SMESH_Mesh_var mesh = _this();
197 addGeomGroupData( theShapeObject, mesh );
198 if ( !CORBA::is_nil( theShapeObject ))
199 _mainShapeTick = theShapeObject->GetTick();
202 //================================================================================
204 * \brief Return true if mesh has a shape to build a shape on
206 //================================================================================
208 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
209 throw (SALOME::SALOME_Exception)
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()
229 throw (SALOME::SALOME_Exception)
231 Unexpect aCatch(SALOME_SalomeException);
232 GEOM::GEOM_Object_var aShapeObj;
234 TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
237 aShapeObj = _gen_i->ShapeToGeomObject( S );
238 if ( aShapeObj->_is_nil() )
240 // S was removed from GEOM_Client by newGroupShape() called by other mesh;
241 // find GEOM_Object by entry (IPAL52735)
242 list<TGeomGroupData>::iterator data = _geomGroupData.begin();
243 for ( ; data != _geomGroupData.end(); ++data )
244 if ( data->_smeshObject->_is_equivalent( _this() ))
246 SALOMEDS::SObject_wrap so = _gen_i->getStudyServant()->FindObjectID( data->_groupEntry.c_str() );
247 CORBA::Object_var obj = _gen_i->SObjectToObject( so );
248 aShapeObj = GEOM::GEOM_Object::_narrow( obj );
254 catch(SALOME_Exception & S_ex) {
255 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
257 return aShapeObj._retn();
260 //================================================================================
262 * \brief Return false if the mesh is not yet fully loaded from the study file
264 //================================================================================
266 CORBA::Boolean SMESH_Mesh_i::IsLoaded() throw (SALOME::SALOME_Exception)
268 Unexpect aCatch(SALOME_SalomeException);
269 return !_preMeshInfo;
272 //================================================================================
274 * \brief Load full mesh data from the study file
276 //================================================================================
278 void SMESH_Mesh_i::Load() throw (SALOME::SALOME_Exception)
280 Unexpect aCatch(SALOME_SalomeException);
282 _preMeshInfo->FullLoadFromFile();
285 //================================================================================
287 * \brief Remove all nodes and elements
289 //================================================================================
291 void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
293 Unexpect aCatch(SALOME_SalomeException);
295 _preMeshInfo->ForgetOrLoad(); // load in case if !HasShapeToMesh()
299 //CheckGeomGroupModif(); // issue 20145
301 catch(SALOME_Exception & S_ex) {
302 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
305 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".Clear()";
307 SMESH::SMESH_Mesh_var mesh = _this();
308 _gen_i->UpdateIcons( mesh );
311 //================================================================================
313 * \brief Remove all nodes and elements for indicated shape
315 //================================================================================
317 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
318 throw (SALOME::SALOME_Exception)
320 Unexpect aCatch(SALOME_SalomeException);
322 _preMeshInfo->FullLoadFromFile();
325 _impl->ClearSubMesh( ShapeID );
327 catch(SALOME_Exception & S_ex) {
328 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
330 _impl->GetMeshDS()->Modified();
332 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ClearSubMesh( " << ShapeID << " )";
335 //=============================================================================
337 * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
339 //=============================================================================
341 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
343 SMESH::DriverMED_ReadStatus res;
346 case DriverMED_R_SMESHDS_Mesh::DRS_OK:
347 res = SMESH::DRS_OK; break;
348 case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
349 res = SMESH::DRS_EMPTY; break;
350 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
351 res = SMESH::DRS_WARN_RENUMBER; break;
352 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
353 res = SMESH::DRS_WARN_SKIP_ELEM; break;
354 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_DESCENDING:
355 res = SMESH::DRS_WARN_DESCENDING; break;
356 case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
358 res = SMESH::DRS_FAIL; break;
363 //=============================================================================
365 * Convert ::SMESH_ComputeError to SMESH::ComputeError
367 //=============================================================================
369 static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr )
371 SMESH::ComputeError_var errVar = new SMESH::ComputeError();
372 errVar->subShapeID = -1;
373 errVar->hasBadMesh = false;
375 if ( !errorPtr || errorPtr->IsOK() )
377 errVar->code = SMESH::COMPERR_OK;
381 errVar->code = ConvertDriverMEDReadStatus( errorPtr->myName );
382 errVar->comment = errorPtr->myComment.c_str();
384 return errVar._retn();
387 //=============================================================================
391 * Import mesh data from MED file
393 //=============================================================================
395 SMESH::DriverMED_ReadStatus
396 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
397 throw ( SALOME::SALOME_Exception )
399 Unexpect aCatch(SALOME_SalomeException);
402 status = _impl->MEDToMesh( theFileName, theMeshName );
404 catch( SALOME_Exception& S_ex ) {
405 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
408 THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
411 CreateGroupServants();
413 int major, minor, release;
414 major = minor = release = 0;
415 MED::GetMEDVersion(theFileName, major, minor, release);
416 _medFileInfo = new SMESH::MedFileInfo();
417 _medFileInfo->fileName = theFileName;
418 _medFileInfo->fileSize = 0;
419 _medFileInfo->major = major;
420 _medFileInfo->minor = minor;
421 _medFileInfo->release = release;
422 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
424 return ConvertDriverMEDReadStatus(status);
427 //================================================================================
429 * \brief Import mesh data from the CGNS file
431 //================================================================================
433 SMESH::DriverMED_ReadStatus SMESH_Mesh_i::ImportCGNSFile( const char* theFileName,
434 const int theMeshIndex,
435 std::string& theMeshName )
436 throw ( SALOME::SALOME_Exception )
438 Unexpect aCatch(SALOME_SalomeException);
441 status = _impl->CGNSToMesh( theFileName, theMeshIndex, theMeshName );
443 catch( SALOME_Exception& S_ex ) {
444 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
447 THROW_SALOME_CORBA_EXCEPTION("ImportCGNSFile(): unknown exception", SALOME::BAD_PARAM);
450 CreateGroupServants();
452 _medFileInfo = new SMESH::MedFileInfo();
453 _medFileInfo->fileName = theFileName;
454 _medFileInfo->major = 0;
455 _medFileInfo->minor = 0;
456 _medFileInfo->release = 0;
457 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
459 return ConvertDriverMEDReadStatus(status);
462 //================================================================================
464 * \brief Return string representation of a MED file version comprising nbDigits
466 //================================================================================
468 char* SMESH_Mesh_i::GetVersionString(CORBA::Long minor, CORBA::Short nbDigits)
470 string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(minor,
472 return CORBA::string_dup( ver.c_str() );
475 //================================================================================
477 * Return the list of med versions compatibles for write/append,
478 * encoded in 10*major+minor (for instance, code for med 3.2.1 is 32)
480 //================================================================================
482 SMESH::long_array* SMESH_Mesh_i::GetMEDVersionsCompatibleForAppend()
484 SMESH::long_array_var aResult = new SMESH::long_array();
485 std::vector<int> mvok = MED::GetMEDVersionsAppendCompatible();
486 long nbver = mvok.size();
487 aResult->length( nbver );
488 for ( int i = 0; i < nbver; i++ )
489 aResult[i] = mvok[i];
490 return aResult._retn();
493 //=============================================================================
497 * Import mesh data from MED file
499 //=============================================================================
501 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
502 throw ( SALOME::SALOME_Exception )
506 // Read mesh with name = <theMeshName> into SMESH_Mesh
507 _impl->UNVToMesh( theFileName );
509 CreateGroupServants();
511 _medFileInfo = new SMESH::MedFileInfo();
512 _medFileInfo->fileName = theFileName;
513 _medFileInfo->major = 0;
514 _medFileInfo->minor = 0;
515 _medFileInfo->release = 0;
516 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
518 SMESH_CATCH( SMESH::throwCorbaException );
523 //=============================================================================
527 * Import mesh data from STL file
529 //=============================================================================
531 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
532 throw ( SALOME::SALOME_Exception )
536 // Read mesh with name = <theMeshName> into SMESH_Mesh
537 std::string name = _impl->STLToMesh( theFileName );
540 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( _this() );
541 _gen_i->SetName( meshSO, name.c_str() );
543 _medFileInfo = new SMESH::MedFileInfo();
544 _medFileInfo->fileName = theFileName;
545 _medFileInfo->major = 0;
546 _medFileInfo->minor = 0;
547 _medFileInfo->release = 0;
548 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
550 SMESH_CATCH( SMESH::throwCorbaException );
555 //================================================================================
557 * \brief Function used in SMESH_CATCH by ImportGMFFile()
559 //================================================================================
563 SMESH_ComputeErrorPtr exceptionToComputeError(const char* excText)
565 return SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, excText );
569 //================================================================================
571 * \brief Import data from a GMF file and return an error description
573 //================================================================================
575 SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName,
576 bool theMakeRequiredGroups )
577 throw (SALOME::SALOME_Exception)
579 SMESH_ComputeErrorPtr error;
582 #define SMESH_CAUGHT error =
585 error = _impl->GMFToMesh( theFileName, theMakeRequiredGroups );
587 _medFileInfo = new SMESH::MedFileInfo();
588 _medFileInfo->fileName = theFileName;
589 _medFileInfo->major = 0;
590 _medFileInfo->minor = 0;
591 _medFileInfo->release = 0;
592 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
594 SMESH_CATCH( exceptionToComputeError );
598 CreateGroupServants();
600 return ConvertComputeError( error );
603 //=============================================================================
605 * \brief Convert SMESH_Hypothesis::Hypothesis_Status into SMESH::Hypothesis_Status
607 //=============================================================================
609 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
611 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
612 (SMESH_Hypothesis::Hypothesis_Status theStatus)
615 RETURNCASE( HYP_OK );
616 RETURNCASE( HYP_MISSING );
617 RETURNCASE( HYP_CONCURRENT );
618 RETURNCASE( HYP_BAD_PARAMETER );
619 RETURNCASE( HYP_HIDDEN_ALGO );
620 RETURNCASE( HYP_HIDING_ALGO );
621 RETURNCASE( HYP_UNKNOWN_FATAL );
622 RETURNCASE( HYP_INCOMPATIBLE );
623 RETURNCASE( HYP_NOTCONFORM );
624 RETURNCASE( HYP_ALREADY_EXIST );
625 RETURNCASE( HYP_BAD_DIM );
626 RETURNCASE( HYP_BAD_SUBSHAPE );
627 RETURNCASE( HYP_BAD_GEOMETRY );
628 RETURNCASE( HYP_NEED_SHAPE );
629 RETURNCASE( HYP_INCOMPAT_HYPS );
632 return SMESH::HYP_UNKNOWN_FATAL;
635 //=============================================================================
639 * Call internal addHypothesis() and then add a reference to <anHyp> under
640 * the SObject actually having a reference to <aSubShape>.
641 * NB: For this method to work, it is necessary to add a reference to sub-shape first.
643 //=============================================================================
645 SMESH::Hypothesis_Status
646 SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShape,
647 SMESH::SMESH_Hypothesis_ptr anHyp,
648 CORBA::String_out anErrorText)
649 throw(SALOME::SALOME_Exception)
651 Unexpect aCatch(SALOME_SalomeException);
653 _preMeshInfo->ForgetOrLoad();
655 const int prevNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements();
658 SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
659 anErrorText = error.c_str();
661 SMESH::SMESH_Mesh_var mesh( _this() );
662 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
664 _gen_i->AddHypothesisToShape( mesh, aSubShape, anHyp );
666 //int newNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements();
667 if ( prevNbMeshEnt > 0 /*newNbMeshEnt != prevNbMeshEnt*/ )
668 _gen_i->UpdateIcons( mesh );
670 if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
672 // Update Python script
673 TPythonDump() << "status = " << mesh << ".AddHypothesis( "
674 << aSubShape << ", " << anHyp << " )";
676 return ConvertHypothesisStatus(status);
679 //================================================================================
681 * \brief Create a sub-mesh and add a hypothesis to it
683 //================================================================================
685 SMESH_Hypothesis::Hypothesis_Status
686 SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShape,
687 SMESH::SMESH_Hypothesis_ptr anHyp,
688 std::string* anErrorText)
690 if(MYDEBUG) MESSAGE("addHypothesis");
692 if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
693 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
695 if (CORBA::is_nil( anHyp ))
696 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",SALOME::BAD_PARAM);
698 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
701 TopoDS_Shape myLocSubShape;
702 //use PseudoShape in case if mesh has no shape
704 myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
706 myLocSubShape = _impl->GetShapeToMesh();
708 const int hypId = anHyp->GetId();
710 status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
711 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
713 _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
715 // assure there is a corresponding submesh
716 if ( !_impl->IsMainShape( myLocSubShape )) {
717 int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
718 if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
719 SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
722 else if ( anErrorText )
724 *anErrorText = error;
727 catch(SALOME_Exception & S_ex)
729 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
734 //================================================================================
736 * \brief Un-assign a hypothesis from a sub-mesh dedicate to the given sub-shape
738 //================================================================================
740 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
741 SMESH::SMESH_Hypothesis_ptr anHyp)
742 throw(SALOME::SALOME_Exception)
744 Unexpect aCatch(SALOME_SalomeException);
746 _preMeshInfo->ForgetOrLoad();
748 SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
749 SMESH::SMESH_Mesh_var mesh = _this();
751 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
753 _gen_i->RemoveHypothesisFromShape( mesh, aSubShape, anHyp );
754 _gen_i->UpdateIcons( mesh );
756 // Update Python script
757 if(_impl->HasShapeToMesh())
758 TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
759 << aSubShape << ", " << anHyp << " )";
761 TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
764 return ConvertHypothesisStatus(status);
767 //=============================================================================
769 * \brief Un-assign a hypothesis from a sub-mesh dedicate to the given sub-shape
771 //=============================================================================
773 SMESH_Hypothesis::Hypothesis_Status
774 SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShape,
775 SMESH::SMESH_Hypothesis_ptr anHyp)
777 if(MYDEBUG) MESSAGE("removeHypothesis()");
779 if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
780 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
782 if (CORBA::is_nil( anHyp ))
783 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
786 _preMeshInfo->ForgetOrLoad();
788 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
791 TopoDS_Shape myLocSubShape;
792 //use PseudoShape in case if mesh has no shape
793 if( _impl->HasShapeToMesh() )
794 myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
796 myLocSubShape = _impl->GetShapeToMesh();
798 const int hypId = anHyp->GetId();
799 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
800 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
802 // _mapHypo.erase( hypId ); EAP: hyp can be used on many sub-shapes
806 catch(SALOME_Exception & S_ex)
808 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
813 //================================================================================
815 * \brief Return hypotheses assigned to a given sub-shape
817 //================================================================================
819 SMESH::ListOfHypothesis *
820 SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
821 throw(SALOME::SALOME_Exception)
823 Unexpect aCatch(SALOME_SalomeException);
824 if (MYDEBUG) MESSAGE("GetHypothesisList");
825 if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
826 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
828 SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
831 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
832 if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
833 myLocSubShape = _impl->GetShapeToMesh();
834 const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
835 int i = 0, n = aLocalList.size();
838 list<const SMESHDS_Hypothesis*>::const_iterator aHyp = aLocalList.begin();
839 std::map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id_hypptr;
840 for ( ; i < n && aHyp != aLocalList.end(); aHyp++ )
842 id_hypptr = _mapHypo.find( (*aHyp)->GetID() );
843 if ( id_hypptr != _mapHypo.end() )
844 aList[i++] = SMESH::SMESH_Hypothesis::_narrow( id_hypptr->second );
848 catch(SALOME_Exception & S_ex) {
849 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
852 return aList._retn();
855 //================================================================================
857 * \brief Return sub-meshes
859 //================================================================================
861 SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes() throw (SALOME::SALOME_Exception)
863 Unexpect aCatch(SALOME_SalomeException);
864 if (MYDEBUG) MESSAGE("GetSubMeshes");
866 SMESH::submesh_array_var aList = new SMESH::submesh_array();
869 TPythonDump aPythonDump;
870 if ( !_mapSubMeshIor.empty() )
874 aList->length( _mapSubMeshIor.size() );
876 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.begin();
877 for ( ; it != _mapSubMeshIor.end(); it++ ) {
878 if ( CORBA::is_nil( it->second )) continue;
879 aList[i++] = SMESH::SMESH_subMesh::_duplicate( it->second );
881 if (i > 1) aPythonDump << ", ";
882 aPythonDump << it->second;
886 catch(SALOME_Exception & S_ex) {
887 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
890 // Update Python script
891 if ( !_mapSubMeshIor.empty() )
892 aPythonDump << " ] = " << SMESH::SMESH_Mesh_var( _this() ) << ".GetSubMeshes()";
894 return aList._retn();
897 //================================================================================
899 * \brief Create and return a sub-mesh on the given sub-shape
901 //================================================================================
903 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
904 const char* theName )
905 throw(SALOME::SALOME_Exception)
907 Unexpect aCatch(SALOME_SalomeException);
908 if (CORBA::is_nil(aSubShape))
909 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
911 SMESH::SMESH_subMesh_var subMesh;
912 SMESH::SMESH_Mesh_var aMesh = _this();
914 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
916 //Get or Create the SMESH_subMesh object implementation
918 TopoDS_Iterator it( myLocSubShape );
919 int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
920 bool isValidSub = ( subMeshId || _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape ));
921 if ( isValidSub && myLocSubShape.ShapeType() == TopAbs_COMPOUND )
922 isValidSub = !it.Value().IsSame( _impl->GetShapeToMesh() );
926 THROW_SALOME_CORBA_EXCEPTION("Not a sub-shape of the main shape", SALOME::BAD_PARAM);
928 subMesh = getSubMesh( subMeshId );
930 // create a new subMesh object servant if there is none for the shape
931 if ( subMesh->_is_nil() )
932 subMesh = createSubMesh( aSubShape );
933 if ( _gen_i->CanPublishInStudy( subMesh ))
935 SALOMEDS::SObject_wrap aSO =
936 _gen_i->PublishSubMesh( aMesh, subMesh, aSubShape, theName );
937 if ( !aSO->_is_nil()) {
938 // Update Python script
939 TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
940 << aSubShape << ", '" << theName << "' )";
944 catch(SALOME_Exception & S_ex) {
945 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
947 return subMesh._retn();
950 //================================================================================
952 * \brief Remove a sub-mesh
954 //================================================================================
956 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
957 throw (SALOME::SALOME_Exception)
961 if ( theSubMesh->_is_nil() )
964 GEOM::GEOM_Object_var aSubShape;
965 // Remove submesh's SObject
966 SALOMEDS::SObject_wrap anSO = _gen_i->ObjectToSObject( theSubMesh );
967 if ( !anSO->_is_nil() ) {
968 long aTag = SMESH_Gen_i::GetRefOnShapeTag();
969 SALOMEDS::SObject_wrap anObj, aRef;
970 if ( anSO->FindSubObject( aTag, anObj.inout() ) &&
971 anObj->ReferencedObject( aRef.inout() ))
973 CORBA::Object_var obj = aRef->GetObject();
974 aSubShape = GEOM::GEOM_Object::_narrow( obj );
976 // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
977 // aSubShape = theSubMesh->GetSubShape();
979 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
980 builder->RemoveObjectWithChildren( anSO );
982 // Update Python script
983 TPythonDump() << SMESH::SMESH_Mesh_var( _this() ) << ".RemoveSubMesh( " << anSO << " )";
986 if ( removeSubMesh( theSubMesh, aSubShape.in() ))
988 _preMeshInfo->ForgetOrLoad();
990 SMESH_CATCH( SMESH::throwCorbaException );
993 //================================================================================
995 * \brief Create a standalone group
997 //================================================================================
999 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
1000 const char* theName )
1001 throw(SALOME::SALOME_Exception)
1003 Unexpect aCatch(SALOME_SalomeException);
1005 _preMeshInfo->FullLoadFromFile();
1007 SMESH::SMESH_Group_var aNewGroup =
1008 SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
1010 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1012 SMESH::SMESH_Mesh_var mesh = _this();
1013 SALOMEDS::SObject_wrap aSO =
1014 _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName);
1015 if ( !aSO->_is_nil())
1016 // Update Python script
1017 TPythonDump() << aSO << " = " << mesh << ".CreateGroup( "
1018 << theElemType << ", '" << theName << "' )";
1020 return aNewGroup._retn();
1023 //================================================================================
1025 * \brief Create a group based on the given geometry
1027 //================================================================================
1029 SMESH::SMESH_GroupOnGeom_ptr
1030 SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType theElemType,
1031 const char* theName,
1032 GEOM::GEOM_Object_ptr theGeomObj)
1033 throw(SALOME::SALOME_Exception)
1035 Unexpect aCatch(SALOME_SalomeException);
1037 _preMeshInfo->FullLoadFromFile();
1039 SMESH::SMESH_GroupOnGeom_var aNewGroup;
1041 TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
1042 if ( !aShape.IsNull() )
1045 SMESH::SMESH_GroupOnGeom::_narrow( createGroup( theElemType, theName, /*id=*/-1, aShape ));
1047 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1049 SMESH::SMESH_Mesh_var mesh = _this();
1050 SALOMEDS::SObject_wrap aSO =
1051 _gen_i->PublishGroup( mesh, aNewGroup, theGeomObj, theName );
1052 if ( !aSO->_is_nil())
1053 TPythonDump() << aSO << " = " << mesh << ".CreateGroupFromGEOM( "
1054 << theElemType << ", '" << theName << "', " << theGeomObj << " )";
1058 return aNewGroup._retn();
1061 //================================================================================
1063 * \brief Creates a group whose contents is defined by filter
1064 * \param theElemType - group type
1065 * \param theName - group name
1066 * \param theFilter - the filter
1067 * \retval SMESH::SMESH_GroupOnFilter_ptr - group defined by filter
1069 //================================================================================
1071 SMESH::SMESH_GroupOnFilter_ptr
1072 SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
1073 const char* theName,
1074 SMESH::Filter_ptr theFilter )
1075 throw (SALOME::SALOME_Exception)
1077 Unexpect aCatch(SALOME_SalomeException);
1079 _preMeshInfo->FullLoadFromFile();
1081 if ( CORBA::is_nil( theFilter ))
1082 THROW_SALOME_CORBA_EXCEPTION("NULL filter", SALOME::BAD_PARAM);
1084 SMESH_PredicatePtr predicate = SMESH_GroupOnFilter_i::GetPredicate( theFilter );
1086 THROW_SALOME_CORBA_EXCEPTION("Invalid filter", SALOME::BAD_PARAM);
1088 SMESH::SMESH_GroupOnFilter_var aNewGroup = SMESH::SMESH_GroupOnFilter::_narrow
1089 ( createGroup( theElemType, theName, /*id=*/-1, TopoDS_Shape(), predicate ));
1092 if ( !aNewGroup->_is_nil() )
1093 aNewGroup->SetFilter( theFilter );
1095 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1097 SMESH::SMESH_Mesh_var mesh = _this();
1098 SALOMEDS::SObject_wrap aSO =
1099 _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName );
1101 if ( !aSO->_is_nil())
1102 pd << aSO << " = " << mesh << ".CreateGroupFromFilter( "
1103 << theElemType << ", '" << theName << "', " << theFilter << " )";
1105 return aNewGroup._retn();
1108 //================================================================================
1110 * \brief Remove a group
1112 //================================================================================
1114 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
1115 throw (SALOME::SALOME_Exception)
1117 if ( theGroup->_is_nil() )
1122 SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
1126 if ( aGroup->GetMeshServant() != this )
1127 THROW_SALOME_CORBA_EXCEPTION( "RemoveGroup(): group does not belong to this mesh",
1128 SALOME::BAD_PARAM );
1130 SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( theGroup );
1131 if ( !aGroupSO->_is_nil() )
1133 // Update Python script
1134 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroup( " << aGroupSO << " )";
1136 // Remove group's SObject
1137 SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::getStudyServant()->NewBuilder();
1138 builder->RemoveObjectWithChildren( aGroupSO );
1140 aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
1142 // Remove the group from SMESH data structures
1143 removeGroup( aGroup->GetLocalID() );
1145 SMESH_CATCH( SMESH::throwCorbaException );
1148 //=============================================================================
1150 * Remove group with its contents
1152 //=============================================================================
1154 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
1155 throw (SALOME::SALOME_Exception)
1159 _preMeshInfo->FullLoadFromFile();
1161 if ( theGroup->_is_nil() )
1164 SMESH_GroupBase_i* groupImpl = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup );
1165 if ( !groupImpl || groupImpl->GetMeshServant() != this )
1166 THROW_SALOME_CORBA_EXCEPTION( "RemoveGroupWithContents(): group does not belong to this mesh",
1169 vector<int> nodeIds; // to remove nodes becoming free
1170 bool isNodal = ( theGroup->GetType() == SMESH::NODE );
1171 if ( !isNodal && !theGroup->IsEmpty() )
1173 CORBA::Long elemID = theGroup->GetID( 1 );
1174 int nbElemNodes = GetElemNbNodes( elemID );
1175 if ( nbElemNodes > 0 )
1176 nodeIds.reserve( theGroup->Size() * nbElemNodes );
1179 // Retrieve contents
1180 SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );
1181 SMDS_ElemIteratorPtr elemIt = GetElements( idSrc, theGroup->GetType() );
1182 SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > elemBeg( elemIt ), elemEnd;
1183 std::vector< const SMDS_MeshElement* > elems( theGroup->Size() );
1184 elems.assign( elemBeg, elemEnd );
1186 TPythonDump pyDump; // Suppress dump from RemoveGroup()
1189 RemoveGroup( theGroup );
1192 for ( size_t i = 0; i < elems.size(); ++i )
1194 // if ( !_impl->GetMeshDS()->Contains( elems[i] ))
1198 for ( SMDS_ElemIteratorPtr nIt = elems[i]->nodesIterator(); nIt->more(); )
1199 nodeIds.push_back( nIt->next()->GetID() );
1201 _impl->GetMeshDS()->RemoveFreeElement( elems[i], /*sm=*/0 );
1205 _impl->GetMeshDS()->RemoveElement( elems[i] );
1209 // Remove free nodes
1210 for ( size_t i = 0 ; i < nodeIds.size(); ++i )
1211 if ( const SMDS_MeshNode* n = _impl->GetMeshDS()->FindNode( nodeIds[i] ))
1212 if ( n->NbInverseElements() == 0 )
1213 _impl->GetMeshDS()->RemoveFreeNode( n, /*sm=*/0 );
1215 // Update Python script (theGroup must be alive for this)
1216 pyDump << SMESH::SMESH_Mesh_var(_this())
1217 << ".RemoveGroupWithContents( " << theGroup << " )";
1219 SMESH_CATCH( SMESH::throwCorbaException );
1222 //================================================================================
1224 * \brief Get the list of groups existing in the mesh
1225 * \retval SMESH::ListOfGroups * - list of groups
1227 //================================================================================
1229 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
1231 Unexpect aCatch(SALOME_SalomeException);
1232 if (MYDEBUG) MESSAGE("GetGroups");
1234 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
1237 TPythonDump aPythonDump;
1238 if ( !_mapGroups.empty() )
1240 aPythonDump << "[ ";
1242 aList->length( _mapGroups.size() );
1244 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
1245 for ( ; it != _mapGroups.end(); it++ ) {
1246 if ( CORBA::is_nil( it->second )) continue;
1247 aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
1249 if (i > 1) aPythonDump << ", ";
1250 aPythonDump << it->second;
1254 catch(SALOME_Exception & S_ex) {
1255 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1257 aPythonDump << " ] = " << SMESH::SMESH_Mesh_var(_this()) << ".GetGroups()";
1259 return aList._retn();
1262 //=============================================================================
1264 * Get number of groups existing in the mesh
1266 //=============================================================================
1268 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
1270 Unexpect aCatch(SALOME_SalomeException);
1271 return _mapGroups.size();
1274 //=============================================================================
1276 * New group including all mesh elements present in initial groups is created.
1278 //=============================================================================
1280 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1281 SMESH::SMESH_GroupBase_ptr theGroup2,
1282 const char* theName )
1283 throw (SALOME::SALOME_Exception)
1285 SMESH::SMESH_Group_var aResGrp;
1289 _preMeshInfo->FullLoadFromFile();
1291 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1292 THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): NULL Group",
1294 if ( theGroup1->GetType() != theGroup2->GetType() )
1295 THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): different group types",
1300 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1301 if ( aResGrp->_is_nil() )
1302 return SMESH::SMESH_Group::_nil();
1304 aResGrp->AddFrom( theGroup1 );
1305 aResGrp->AddFrom( theGroup2 );
1307 // Update Python script
1308 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this())
1309 << ".UnionGroups( " << theGroup1 << ", " << theGroup2 << ", '" << theName << "' )";
1311 SMESH_CATCH( SMESH::throwCorbaException );
1313 return aResGrp._retn();
1316 //=============================================================================
1318 * \brief New group including all mesh elements present in initial groups is created.
1319 * \param theGroups list of groups
1320 * \param theName name of group to be created
1321 * \return pointer to the new group
1323 //=============================================================================
1325 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
1326 const char* theName )
1327 throw (SALOME::SALOME_Exception)
1329 SMESH::SMESH_Group_var aResGrp;
1332 _preMeshInfo->FullLoadFromFile();
1335 return SMESH::SMESH_Group::_nil();
1340 SMESH::ElementType aType = SMESH::ALL;
1341 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1343 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1344 if ( CORBA::is_nil( aGrp ) )
1346 if ( aType == SMESH::ALL )
1347 aType = aGrp->GetType();
1348 else if ( aType != aGrp->GetType() )
1349 THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1352 if ( aType == SMESH::ALL )
1353 return SMESH::SMESH_Group::_nil();
1358 aResGrp = CreateGroup( aType, theName );
1359 if ( aResGrp->_is_nil() )
1360 return SMESH::SMESH_Group::_nil();
1362 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".UnionListOfGroups([ ";
1363 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1365 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1366 if ( !CORBA::is_nil( aGrp ) )
1368 aResGrp->AddFrom( aGrp );
1369 if ( g > 0 ) pyDump << ", ";
1373 pyDump << " ], '" << theName << "' )";
1375 SMESH_CATCH( SMESH::throwCorbaException );
1377 return aResGrp._retn();
1380 //=============================================================================
1382 * New group is created. All mesh elements that are
1383 * present in both initial groups are added to the new one.
1385 //=============================================================================
1387 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1388 SMESH::SMESH_GroupBase_ptr theGroup2,
1389 const char* theName )
1390 throw (SALOME::SALOME_Exception)
1392 SMESH::SMESH_Group_var aResGrp;
1397 _preMeshInfo->FullLoadFromFile();
1399 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1400 THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): NULL Group",
1402 if ( theGroup1->GetType() != theGroup2->GetType() )
1403 THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): different group types",
1407 // Create Intersection
1408 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1409 if ( aResGrp->_is_nil() )
1410 return aResGrp._retn();
1412 SMESHDS_GroupBase* groupDS1 = 0;
1413 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1414 groupDS1 = grp_i->GetGroupDS();
1416 SMESHDS_GroupBase* groupDS2 = 0;
1417 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1418 groupDS2 = grp_i->GetGroupDS();
1420 SMESHDS_Group* resGroupDS = 0;
1421 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1422 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1424 if ( groupDS1 && groupDS2 && resGroupDS && !groupDS2->IsEmpty() )
1426 SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1427 while ( elemIt1->more() )
1429 const SMDS_MeshElement* e = elemIt1->next();
1430 if ( groupDS2->Contains( e ))
1431 resGroupDS->SMDSGroup().Add( e );
1434 // Update Python script
1435 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".IntersectGroups( "
1436 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1438 SMESH_CATCH( SMESH::throwCorbaException );
1440 return aResGrp._retn();
1443 //=============================================================================
1445 \brief Intersect list of groups. New group is created. All mesh elements that
1446 are present in all initial groups simultaneously are added to the new one.
1447 \param theGroups list of groups
1448 \param theName name of group to be created
1449 \return pointer on the group
1451 //=============================================================================
1453 SMESH::SMESH_Group_ptr
1454 SMESH_Mesh_i::IntersectListOfGroups(const SMESH::ListOfGroups& theGroups,
1455 const char* theName )
1456 throw (SALOME::SALOME_Exception)
1458 SMESH::SMESH_Group_var aResGrp;
1463 _preMeshInfo->FullLoadFromFile();
1466 return SMESH::SMESH_Group::_nil();
1468 // check types and get SMESHDS_GroupBase's
1469 SMESH::ElementType aType = SMESH::ALL;
1470 vector< SMESHDS_GroupBase* > groupVec;
1471 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1473 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1474 if ( CORBA::is_nil( aGrp ) )
1476 if ( aType == SMESH::ALL )
1477 aType = aGrp->GetType();
1478 else if ( aType != aGrp->GetType() )
1479 THROW_SALOME_CORBA_EXCEPTION("IntersectListOfGroups(): different group types",
1482 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1483 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1485 if ( grpDS->IsEmpty() )
1490 groupVec.push_back( grpDS );
1493 if ( aType == SMESH::ALL ) // all groups are nil
1494 return SMESH::SMESH_Group::_nil();
1499 aResGrp = CreateGroup( aType, theName );
1501 SMESHDS_Group* resGroupDS = 0;
1502 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1503 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1504 if ( !resGroupDS || groupVec.empty() )
1505 return aResGrp._retn();
1508 size_t i, nb = groupVec.size();
1509 SMDS_ElemIteratorPtr elemIt1 = groupVec[0]->GetElements();
1510 while ( elemIt1->more() )
1512 const SMDS_MeshElement* e = elemIt1->next();
1514 for ( i = 1; ( i < nb && inAll ); ++i )
1515 inAll = groupVec[i]->Contains( e );
1518 resGroupDS->SMDSGroup().Add( e );
1521 // Update Python script
1522 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1523 << ".IntersectListOfGroups( " << theGroups << ", '" << theName << "' )";
1525 SMESH_CATCH( SMESH::throwCorbaException );
1527 return aResGrp._retn();
1530 //=============================================================================
1532 * New group is created. All mesh elements that are present in
1533 * a main group but is not present in a tool group are added to the new one
1535 //=============================================================================
1537 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1538 SMESH::SMESH_GroupBase_ptr theGroup2,
1539 const char* theName )
1540 throw (SALOME::SALOME_Exception)
1542 SMESH::SMESH_Group_var aResGrp;
1547 _preMeshInfo->FullLoadFromFile();
1549 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1550 THROW_SALOME_CORBA_EXCEPTION("CutGroups(): NULL Group",
1552 if ( theGroup1->GetType() != theGroup2->GetType() )
1553 THROW_SALOME_CORBA_EXCEPTION("CutGroups(): different group types",
1557 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1558 if ( aResGrp->_is_nil() )
1559 return aResGrp._retn();
1561 SMESHDS_GroupBase* groupDS1 = 0;
1562 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1563 groupDS1 = grp_i->GetGroupDS();
1565 SMESHDS_GroupBase* groupDS2 = 0;
1566 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1567 groupDS2 = grp_i->GetGroupDS();
1569 SMESHDS_Group* resGroupDS = 0;
1570 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1571 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1573 if ( groupDS1 && groupDS2 && resGroupDS )
1575 SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1576 while ( elemIt1->more() )
1578 const SMDS_MeshElement* e = elemIt1->next();
1579 if ( !groupDS2->Contains( e ))
1580 resGroupDS->SMDSGroup().Add( e );
1583 // Update Python script
1584 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".CutGroups( "
1585 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1587 SMESH_CATCH( SMESH::throwCorbaException );
1589 return aResGrp._retn();
1592 //=============================================================================
1594 \brief Cut lists of groups. New group is created. All mesh elements that are
1595 present in main groups but do not present in tool groups are added to the new one
1596 \param theMainGroups list of main groups
1597 \param theToolGroups list of tool groups
1598 \param theName name of group to be created
1599 \return pointer on the group
1601 //=============================================================================
1603 SMESH::SMESH_Group_ptr
1604 SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
1605 const SMESH::ListOfGroups& theToolGroups,
1606 const char* theName )
1607 throw (SALOME::SALOME_Exception)
1609 SMESH::SMESH_Group_var aResGrp;
1614 _preMeshInfo->FullLoadFromFile();
1617 return SMESH::SMESH_Group::_nil();
1619 // check types and get SMESHDS_GroupBase's
1620 SMESH::ElementType aType = SMESH::ALL;
1621 vector< SMESHDS_GroupBase* > toolGroupVec;
1622 vector< SMDS_ElemIteratorPtr > mainIterVec;
1624 for ( int g = 0, n = theMainGroups.length(); g < n; g++ )
1626 SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1627 if ( CORBA::is_nil( aGrp ) )
1629 if ( aType == SMESH::ALL )
1630 aType = aGrp->GetType();
1631 else if ( aType != aGrp->GetType() )
1632 THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1634 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1635 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1636 if ( !grpDS->IsEmpty() )
1637 mainIterVec.push_back( grpDS->GetElements() );
1639 if ( aType == SMESH::ALL ) // all main groups are nil
1640 return SMESH::SMESH_Group::_nil();
1641 if ( mainIterVec.empty() ) // all main groups are empty
1642 return aResGrp._retn();
1644 for ( int g = 0, n = theToolGroups.length(); g < n; g++ )
1646 SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1647 if ( CORBA::is_nil( aGrp ) )
1649 if ( aType != aGrp->GetType() )
1650 THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1652 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1653 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1654 toolGroupVec.push_back( grpDS );
1660 aResGrp = CreateGroup( aType, theName );
1662 SMESHDS_Group* resGroupDS = 0;
1663 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1664 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1666 return aResGrp._retn();
1669 size_t i, nb = toolGroupVec.size();
1670 SMDS_ElemIteratorPtr mainElemIt
1671 ( new SMDS_IteratorOnIterators
1672 < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > >( mainIterVec ));
1673 while ( mainElemIt->more() )
1675 const SMDS_MeshElement* e = mainElemIt->next();
1677 for ( i = 0; ( i < nb && !isIn ); ++i )
1678 isIn = toolGroupVec[i]->Contains( e );
1681 resGroupDS->SMDSGroup().Add( e );
1684 // Update Python script
1685 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1686 << ".CutListOfGroups( " << theMainGroups << ", "
1687 << theToolGroups << ", '" << theName << "' )";
1689 SMESH_CATCH( SMESH::throwCorbaException );
1691 return aResGrp._retn();
1694 namespace // functions making checks according to SMESH::NB_COMMON_NODES_ENUM
1696 bool isAllNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1697 bool & toStopChecking )
1699 toStopChecking = ( nbCommon < nbChecked );
1700 return nbCommon == nbNodes;
1702 bool isMainNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1703 bool & toStopChecking )
1705 toStopChecking = ( nbCommon < nbChecked || nbChecked >= nbCorners );
1706 return nbCommon == nbCorners;
1708 bool isAtLeastOneNodeCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1709 bool & toStopChecking )
1711 return nbCommon > 0;
1713 bool isMajorityOfNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1714 bool & toStopChecking )
1716 return nbCommon >= (nbNodes+1) / 2;
1720 //=============================================================================
1722 * Create a group of entities basing on nodes of other groups.
1723 * \param [in] theGroups - list of either groups, sub-meshes or filters.
1724 * \param [in] anElemType - a type of elements to include to the new group.
1725 * \param [in] theName - a name of the new group.
1726 * \param [in] theNbCommonNodes - criterion of inclusion of an element to the new group.
1727 * \param [in] theUnderlyingOnly - if \c True, an element is included to the
1728 * new group provided that it is based on nodes of an element of \a aListOfGroups
1729 * \return SMESH_Group - the created group
1731 // IMP 19939, bug 22010, IMP 22635
1732 //=============================================================================
1734 SMESH::SMESH_Group_ptr
1735 SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfIDSources& theGroups,
1736 SMESH::ElementType theElemType,
1737 const char* theName,
1738 SMESH::NB_COMMON_NODES_ENUM theNbCommonNodes,
1739 CORBA::Boolean theUnderlyingOnly)
1740 throw (SALOME::SALOME_Exception)
1742 SMESH::SMESH_Group_var aResGrp;
1746 _preMeshInfo->FullLoadFromFile();
1748 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1750 if ( !theName || !aMeshDS )
1751 return SMESH::SMESH_Group::_nil();
1753 SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1755 bool (*isToInclude)(int nbChecked, int nbCommon, int nbNodes, int nbCorners, bool & toStop);
1756 SMESH_Comment nbCoNoStr( "SMESH.");
1757 switch ( theNbCommonNodes ) {
1758 case SMESH::ALL_NODES : isToInclude = isAllNodesCommon; nbCoNoStr<<"ALL_NODES" ;break;
1759 case SMESH::MAIN : isToInclude = isMainNodesCommon; nbCoNoStr<<"MAIN" ;break;
1760 case SMESH::AT_LEAST_ONE: isToInclude = isAtLeastOneNodeCommon; nbCoNoStr<<"AT_LEAST_ONE";break;
1761 case SMESH::MAJORITY : isToInclude = isMajorityOfNodesCommon; nbCoNoStr<<"MAJORITY" ;break;
1762 default: return aResGrp._retn();
1764 int nbChecked, nbCommon, nbNodes, nbCorners;
1770 aResGrp = CreateGroup( theElemType, theName );
1771 if ( aResGrp->_is_nil() )
1772 return SMESH::SMESH_Group::_nil();
1774 SMESHDS_GroupBase* groupBaseDS =
1775 SMESH::DownCast<SMESH_GroupBase_i*>( aResGrp )->GetGroupDS();
1776 SMDS_MeshGroup& resGroupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1778 vector<bool> isNodeInGroups;
1780 for ( int g = 0, n = theGroups.length(); g < n; g++ ) // loop on theGroups
1782 SMESH::SMESH_IDSource_var aGrp = theGroups[ g ];
1783 if ( CORBA::is_nil( aGrp ) )
1785 SMESH::SMESH_Mesh_var mesh = aGrp->GetMesh();
1786 if ( mesh->_is_nil() || mesh->GetId() != this->GetId() )
1789 SMDS_ElemIteratorPtr elIt = GetElements( aGrp, SMESH::ALL );
1790 if ( !elIt ) continue;
1792 if ( theElemType == SMESH::NODE ) // get all nodes of elements
1794 while ( elIt->more() ) {
1795 const SMDS_MeshElement* el = elIt->next();
1796 SMDS_ElemIteratorPtr nIt = el->nodesIterator();
1797 while ( nIt->more() )
1798 resGroupCore.Add( nIt->next() );
1801 // get elements of theElemType based on nodes of every element of group
1802 else if ( theUnderlyingOnly )
1804 while ( elIt->more() )
1806 const SMDS_MeshElement* el = elIt->next(); // an element of ref group
1807 TIDSortedElemSet elNodes( el->begin_nodes(), el->end_nodes() );
1808 TIDSortedElemSet checkedElems;
1809 SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1810 while ( nIt->more() )
1812 const SMDS_MeshNode* n = nIt->next();
1813 SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1814 // check nodes of elements of theElemType around el
1815 while ( elOfTypeIt->more() )
1817 const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1818 if ( !checkedElems.insert( elOfType ).second ) continue;
1819 nbNodes = elOfType->NbNodes();
1820 nbCorners = elOfType->NbCornerNodes();
1822 bool toStopChecking = false;
1823 SMDS_ElemIteratorPtr nIt2 = elOfType->nodesIterator();
1824 for ( nbChecked = 1; nIt2->more() && !toStopChecking; ++nbChecked )
1825 if ( elNodes.count( nIt2->next() ) &&
1826 isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1828 resGroupCore.Add( elOfType );
1835 // get all nodes of elements of groups
1838 while ( elIt->more() )
1840 const SMDS_MeshElement* el = elIt->next(); // an element of group
1841 SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1842 while ( nIt->more() )
1844 const SMDS_MeshNode* n = nIt->next();
1845 if ( n->GetID() >= (int) isNodeInGroups.size() )
1846 isNodeInGroups.resize( n->GetID() + 1, false );
1847 isNodeInGroups[ n->GetID() ] = true;
1853 // Get elements of theElemType based on a certain number of nodes of elements of groups
1854 if ( !theUnderlyingOnly && !isNodeInGroups.empty() )
1856 const SMDS_MeshNode* n;
1857 vector<bool> isElemChecked( aMeshDS->MaxElementID() + 1 );
1858 const int isNodeInGroupsSize = isNodeInGroups.size();
1859 for ( int iN = 0; iN < isNodeInGroupsSize; ++iN )
1861 if ( !isNodeInGroups[ iN ] ||
1862 !( n = aMeshDS->FindNode( iN )))
1865 // check nodes of elements of theElemType around n
1866 SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1867 while ( elOfTypeIt->more() )
1869 const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1870 vector<bool>::reference isChecked = isElemChecked[ elOfType->GetID() ];
1875 nbNodes = elOfType->NbNodes();
1876 nbCorners = elOfType->NbCornerNodes();
1878 bool toStopChecking = false;
1879 SMDS_ElemIteratorPtr nIt = elOfType->nodesIterator();
1880 for ( nbChecked = 1; nIt->more() && !toStopChecking; ++nbChecked )
1882 const int nID = nIt->next()->GetID();
1883 if ( nID < isNodeInGroupsSize && isNodeInGroups[ nID ] &&
1884 isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1886 resGroupCore.Add( elOfType );
1894 // Update Python script
1895 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this())
1896 << ".CreateDimGroup( "
1897 << theGroups << ", " << theElemType << ", '" << theName << "', "
1898 << nbCoNoStr << ", " << theUnderlyingOnly << ")";
1900 SMESH_CATCH( SMESH::throwCorbaException );
1902 return aResGrp._retn();
1905 //================================================================================
1907 * \brief Distribute all faces of the mesh between groups using sharp edges and optionally
1908 * existing 1D elements as group boundaries.
1909 * \param [in] theSharpAngle - edge is considered sharp if an angle between normals of
1910 * adjacent faces is more than \a sharpAngle in degrees.
1911 * \param [in] theCreateEdges - to create 1D elements for detected sharp edges.
1912 * \param [in] theUseExistingEdges - to use existing edges as group boundaries
1913 * \return ListOfGroups - the created groups
1915 //================================================================================
1917 SMESH::ListOfGroups*
1918 SMESH_Mesh_i::FaceGroupsSeparatedByEdges( CORBA::Double theSharpAngle,
1919 CORBA::Boolean theCreateEdges,
1920 CORBA::Boolean theUseExistingEdges )
1921 throw (SALOME::SALOME_Exception)
1923 if ( theSharpAngle < 0 || theSharpAngle > 180 )
1924 THROW_SALOME_CORBA_EXCEPTION("Invalid sharp angle, it must be between 0 and 180 degrees",
1927 SMESH::ListOfGroups_var resultGroups = new SMESH::ListOfGroups;
1933 _preMeshInfo->FullLoadFromFile();
1935 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1937 std::vector< SMESH_MeshAlgos::Edge > edges =
1938 SMESH_MeshAlgos::FindSharpEdges( meshDS, theSharpAngle, theUseExistingEdges );
1940 if ( theCreateEdges )
1942 std::vector<const SMDS_MeshNode *> nodes(2);
1943 for ( size_t i = 0; i < edges.size(); ++i )
1945 nodes[0] = edges[i]._node1;
1946 nodes[1] = edges[i]._node2;
1947 if ( meshDS->FindElement( nodes, SMDSAbs_Edge ))
1949 if ( edges[i]._medium )
1950 meshDS->AddEdge( edges[i]._node1, edges[i]._node2, edges[i]._medium );
1952 meshDS->AddEdge( edges[i]._node1, edges[i]._node2 );
1956 std::vector< std::vector< const SMDS_MeshElement* > > faceGroups =
1957 SMESH_MeshAlgos::SeparateFacesByEdges( meshDS, edges );
1959 SMESH::SMESH_MeshEditor_var editor = GetMeshEditor(); // create _editor
1961 resultGroups->length( faceGroups.size() );
1962 for ( size_t iG = 0; iG < faceGroups.size(); ++iG )
1964 SMESH::SMESH_Group_var group = CreateGroup( SMESH::FACE,
1965 _editor->GenerateGroupName("Group").c_str());
1966 resultGroups[iG] = SMESH::SMESH_Group::_duplicate( group );
1968 SMESHDS_GroupBase* groupBaseDS =
1969 SMESH::DownCast<SMESH_GroupBase_i*>( group )->GetGroupDS();
1970 SMDS_MeshGroup& groupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1972 std::vector< const SMDS_MeshElement* >& faces = faceGroups[ iG ];
1973 for ( size_t i = 0; i < faces.size(); ++i )
1974 groupCore.Add( faces[i] );
1977 pyDump << resultGroups << " = " << SMESH::SMESH_Mesh_var(_this())
1978 << ".FaceGroupsSeparatedByEdges( "
1979 << TVar( theSharpAngle ) << ", "
1980 << theCreateEdges << ", "
1981 << theUseExistingEdges << " )";
1983 SMESH_CATCH( SMESH::throwCorbaException );
1984 return resultGroups._retn();
1988 //================================================================================
1990 * \brief Remember GEOM group data
1992 //================================================================================
1994 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1995 CORBA::Object_ptr theSmeshObj)
1997 if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
2000 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( theGeomObj );
2001 if ( groupSO->_is_nil() )
2004 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( theGeomObj );
2005 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
2006 GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
2009 _geomGroupData.push_back( TGeomGroupData() );
2010 TGeomGroupData & groupData = _geomGroupData.back();
2012 CORBA::String_var entry = groupSO->GetID();
2013 groupData._groupEntry = entry.in();
2015 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2016 groupData._indices.insert( ids[i] );
2018 groupData._smeshObject = CORBA::Object::_duplicate( theSmeshObj );
2019 // shape index in SMESHDS
2020 // TopoDS_Shape shape = _gen_i->GeomObjectToShape( theGeomObj );
2021 // groupData._dsID = shape.IsNull() ? 0 : _impl->GetSubMesh( shape )->GetId();
2024 //================================================================================
2026 * Remove GEOM group data relating to removed smesh object
2028 //================================================================================
2030 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
2032 list<TGeomGroupData>::iterator
2033 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2034 for ( ; data != dataEnd; ++data ) {
2035 if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
2036 _geomGroupData.erase( data );
2042 //================================================================================
2044 * \brief Replace a shape in the mesh upon Break Link
2046 //================================================================================
2048 void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom)
2049 throw (SALOME::SALOME_Exception)
2051 // check if geometry changed
2052 bool geomChanged = true;
2053 GEOM::GEOM_Object_var oldGeom = GetShapeToMesh();
2054 if ( !theNewGeom->_is_nil() && !oldGeom->_is_nil() )
2055 geomChanged = ( //oldGeom->_is_equivalent( theNewGeom ) ||
2056 oldGeom->GetTick() < theNewGeom->GetTick() );
2058 TopoDS_Shape S = _impl->GetShapeToMesh();
2059 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2060 TCollection_AsciiString aIOR;
2061 CORBA::String_var ior;
2062 if ( geomClient->Find( S, aIOR ))
2063 geomClient->RemoveShapeFromBuffer( aIOR );
2065 // clear buffer also for sub-groups
2066 const std::set<SMESHDS_GroupBase*>& groups = _impl->GetMeshDS()->GetGroups();
2067 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2068 for (; g != groups.end(); ++g)
2069 if (const SMESHDS_GroupOnGeom* group = dynamic_cast<SMESHDS_GroupOnGeom*>(*g))
2071 const TopoDS_Shape& s = group->GetShape();
2072 if ( geomClient->Find( s, aIOR ))
2073 geomClient->RemoveShapeFromBuffer( aIOR );
2077 int shapeID, fromID, toID; // indices of elements of a sub-mesh
2079 std::vector< TRange > elemRanges, nodeRanges; // elements of sub-meshes
2080 std::vector< SMDS_PositionPtr > positions; // node positions
2081 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2084 // store positions of elements on geometry
2086 if ( meshDS->MaxNodeID() > meshDS->NbNodes() ||
2087 meshDS->MaxElementID() > meshDS->NbElements() )
2090 meshDS->CompactMesh();
2092 positions.resize( meshDS->NbNodes() + 1 );
2093 for ( SMDS_NodeIteratorPtr nodeIt = meshDS->nodesIterator(); nodeIt->more(); )
2095 const SMDS_MeshNode* n = nodeIt->next();
2096 positions[ n->GetID() ] = n->GetPosition();
2099 // remove elements from sub-meshes to avoid their removal at hypotheses addition
2100 for ( int isNode = 0; isNode < 2; ++isNode )
2102 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2103 ranges.reserve( meshDS->MaxShapeIndex() + 10 );
2104 ranges.push_back( TRange{ 0,0,0 });
2105 SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
2106 while ( elemIt->more() )
2108 const SMDS_MeshElement* e = elemIt->next();
2109 const int elemID = e->GetID();
2110 const int shapeID = e->GetShapeID();
2111 TRange & lastRange = ranges.back();
2112 if ( lastRange.shapeID != shapeID ||
2113 lastRange.toID != elemID )
2114 ranges.push_back( TRange{ shapeID, elemID, elemID + 1 });
2116 lastRange.toID = elemID + 1;
2118 if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( shapeID ))
2120 if ( isNode ) sm->RemoveNode( static_cast< const SMDS_MeshNode *>( e ));
2121 else sm->RemoveElement( e );
2128 // update the reference to theNewGeom (needed for correct execution of a dumped python script)
2129 SMESH::SMESH_Mesh_var me = _this();
2130 SALOMEDS::SObject_wrap aSO = _gen_i->ObjectToSObject( me );
2131 CORBA::String_var entry = theNewGeom->GetStudyEntry();
2132 if ( !aSO->_is_nil() )
2134 SALOMEDS::SObject_wrap aShapeRefSO;
2135 if ( aSO->FindSubObject( _gen_i->GetRefOnShapeTag(), aShapeRefSO.inout() ))
2137 SALOMEDS::SObject_wrap aShapeSO = _gen_i->getStudyServant()->FindObjectID( entry );
2138 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2139 builder->Addreference( aShapeRefSO, aShapeSO );
2143 // re-assign global hypotheses to the new shape
2144 _mainShapeTick = geomChanged ? -1 : theNewGeom->GetTick();
2145 CheckGeomModif( true );
2149 // restore positions of elements on geometry
2150 for ( int isNode = 0; isNode < 2; ++isNode )
2152 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2153 for ( size_t i = 1; i < ranges.size(); ++i )
2155 int elemID = ranges[ i ].fromID;
2156 int toID = ranges[ i ].toID;
2157 SMESHDS_SubMesh * smDS = meshDS->NewSubMesh( ranges[ i ].shapeID );
2159 for ( ; elemID < toID; ++elemID )
2160 smDS->AddNode( meshDS->FindNode( elemID ));
2162 for ( ; elemID < toID; ++elemID )
2163 smDS->AddElement( meshDS->FindElement( elemID ));
2165 if ( SMESH_subMesh* sm = _impl->GetSubMeshContaining( ranges[ i ].shapeID ))
2166 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
2169 for ( unsigned int nodeID = 1; nodeID < positions.size(); ++nodeID )
2170 if ( positions[ nodeID ])
2171 if ( SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( meshDS->FindNode( nodeID )))
2172 n->SetPosition( positions[ nodeID ], n->GetShapeID() );
2175 _gen_i->UpdateIcons( SMESH::SMESH_Mesh_var( _this() ));
2178 TPythonDump() << "SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject("
2179 << me <<".GetMesh()), " << entry.in() << ")";
2181 TPythonDump() << me << ".ReplaceShape( " << entry.in() << " )";
2185 //================================================================================
2187 * \brief Return new group contents if it has been changed and update group data
2189 //================================================================================
2191 enum { ONLY_IF_CHANGED, IS_BREAK_LINK, MAIN_TRANSFORMED };
2193 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData, int how )
2195 TopoDS_Shape newShape;
2196 SALOMEDS::SObject_wrap groupSO;
2198 if ( how == IS_BREAK_LINK )
2200 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( groupData._smeshObject );
2201 SALOMEDS::SObject_wrap geomRefSO;
2202 if ( !meshSO->_is_nil() &&
2203 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ))
2205 geomRefSO->ReferencedObject( groupSO.inout() );
2211 groupSO = _gen_i->getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
2214 if ( groupSO->_is_nil() )
2217 CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
2218 GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
2219 if ( geomGroup->_is_nil() )
2222 // get indices of group items
2223 set<int> curIndices;
2224 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( geomGroup );
2225 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
2226 GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
2227 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2228 curIndices.insert( ids[i] );
2230 bool sameIndices = ( groupData._indices == curIndices );
2231 if ( how == ONLY_IF_CHANGED && sameIndices )
2232 return newShape; // group not changed
2235 CORBA::String_var entry = geomGroup->GetStudyEntry();
2236 groupData._groupEntry = entry.in();
2237 groupData._indices = curIndices;
2239 newShape = _gen_i->GeomObjectToShape( geomGroup );
2241 // check if newShape is up-to-date
2242 if ( !newShape.IsNull() && ids->length() > 0 )
2244 bool toUpdate = ! _impl->GetMeshDS()->IsGroupOfSubShapes( newShape );
2247 TopExp_Explorer exp( newShape, (TopAbs_ShapeEnum)( groupOp->GetType( geomGroup )));
2248 for ( ; exp.More() && !toUpdate; exp.Next() )
2250 int ind = _impl->GetMeshDS()->ShapeToIndex( exp.Current() );
2251 toUpdate = ( curIndices.erase( ind ) == 0 );
2253 if ( !curIndices.empty() )
2258 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2259 CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
2260 geomClient->RemoveShapeFromBuffer( groupIOR.in() );
2261 newShape = _gen_i->GeomObjectToShape( geomGroup );
2266 // geom group becomes empty - return empty compound
2267 TopoDS_Compound compound;
2268 BRep_Builder().MakeCompound(compound);
2269 newShape = compound;
2277 //-----------------------------------------------------------------------------
2279 * \brief Storage of shape and index used in CheckGeomGroupModif()
2281 struct TIndexedShape
2284 TopoDS_Shape _shape;
2285 TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
2287 //-----------------------------------------------------------------------------
2289 * \brief Data to re-create a group on geometry
2291 struct TGroupOnGeomData
2294 TopoDS_Shape _shape;
2295 SMDSAbs_ElementType _type;
2297 Quantity_Color _color;
2299 TGroupOnGeomData( const SMESHDS_GroupOnGeom* group )
2301 _oldID = group->GetID();
2302 _type = group->GetType();
2303 _name = group->GetStoreName();
2304 _color = group->GetColor();
2308 //-----------------------------------------------------------------------------
2310 * \brief Check if a filter is still valid after geometry removal
2312 bool isValidGeomFilter( SMESH::Filter_var theFilter )
2314 if ( theFilter->_is_nil() )
2316 SMESH::Filter::Criteria_var criteria;
2317 theFilter->GetCriteria( criteria.out() );
2319 for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
2321 const char* thresholdID = criteria[ iCr ].ThresholdID.in();
2323 switch ( criteria[ iCr ].Type )
2325 case SMESH::FT_BelongToGeom:
2326 case SMESH::FT_BelongToPlane:
2327 case SMESH::FT_BelongToCylinder:
2328 case SMESH::FT_BelongToGenSurface:
2329 case SMESH::FT_LyingOnGeom:
2330 entry = thresholdID;
2332 case SMESH::FT_ConnectedElements:
2335 entry = thresholdID;
2341 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
2342 SALOMEDS::SObject_wrap so = gen->getStudyServant()->FindObjectID( entry.c_str() );
2343 if ( so->_is_nil() )
2345 CORBA::Object_var obj = so->GetObject();
2346 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj );
2347 if ( gen->GeomObjectToShape( geom ).IsNull() )
2350 } // loop on criteria
2356 //=============================================================================
2358 * \brief Update data if geometry changes
2362 //=============================================================================
2364 void SMESH_Mesh_i::CheckGeomModif( bool theIsBreakLink )
2366 SMESH::SMESH_Mesh_var me = _this();
2367 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2369 TPythonDump dumpNothing; // prevent any dump
2371 //bool removedFromClient = false;
2373 if ( mainGO->_is_nil() ) // GEOM_Client cleared or geometry removed? (IPAL52735, PAL23636)
2375 //removedFromClient = _impl->HasShapeToMesh();
2377 // try to find geometry by study reference
2378 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2379 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2380 if ( !meshSO->_is_nil() &&
2381 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2382 geomRefSO->ReferencedObject( geomSO.inout() ))
2384 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2385 mainGO = GEOM::GEOM_Object::_narrow( geomObj );
2388 if ( mainGO->_is_nil() && // geometry removed ==>
2389 !geomRefSO->_is_nil() ) // remove geom dependent data: sub-meshes etc.
2391 // convert geom dependent groups into standalone ones
2392 CheckGeomGroupModif();
2394 _impl->ShapeToMesh( TopoDS_Shape() );
2396 // remove sub-meshes
2397 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2398 while ( i_sm != _mapSubMeshIor.end() )
2400 SMESH::SMESH_subMesh_ptr sm = i_sm->second;
2402 RemoveSubMesh( sm );
2404 // remove all children except groups in the study
2405 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2406 SALOMEDS::SObject_wrap so;
2407 for ( CORBA::Long tag = SMESH::Tag_RefOnShape; tag <= SMESH::Tag_LastSubMesh; ++tag )
2408 if ( meshSO->FindSubObject( tag, so.inout() ))
2409 builder->RemoveObjectWithChildren( so );
2411 _gen_i->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED" );
2417 if ( !_impl->HasShapeToMesh() ) return;
2420 // Update after group modification
2422 const bool geomChanged = ( mainGO->GetTick() != _mainShapeTick );
2423 if ( !theIsBreakLink )
2424 if ( mainGO->GetType() == GEOM_GROUP || !geomChanged ) // is group or not modified
2426 int nb = NbNodes() + NbElements();
2427 CheckGeomGroupModif();
2428 if ( nb != NbNodes() + NbElements() ) // something removed due to hypotheses change
2429 _gen_i->UpdateIcons( me );
2433 // Update after shape modification or breakLink w/o geometry change
2435 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2436 if ( !geomClient ) return;
2437 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( mainGO );
2438 if ( geomGen->_is_nil() ) return;
2439 CORBA::String_var geomComponentType = geomGen->ComponentDataType();
2440 bool isShaper = ( strcmp( geomComponentType.in(), "SHAPERSTUDY" ) == 0 );
2442 SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
2444 TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
2445 if ( meshDS->ShapeToIndex( newShape ) == 1 ) // not yet updated
2447 CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
2448 geomClient->RemoveShapeFromBuffer( ior.in() );
2449 newShape = _gen_i->GeomObjectToShape( mainGO );
2452 // Update data taking into account that if topology doesn't change
2453 // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
2456 _preMeshInfo->ForgetAllData();
2458 if ( geomChanged || !isShaper )
2460 if ( newShape.IsNull() )
2463 _mainShapeTick = mainGO->GetTick();
2465 // store data of groups on geometry including new TopoDS_Shape's
2466 std::vector< TGroupOnGeomData > groupsData;
2467 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2468 groupsData.reserve( groups.size() );
2469 TopTools_DataMapOfShapeShape old2newShapeMap;
2470 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2471 for ( ; g != groups.end(); ++g )
2473 if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
2475 groupsData.push_back( TGroupOnGeomData( group ));
2478 SMESH::SMESH_GroupOnGeom_var gog;
2479 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.find( group->GetID() );
2480 if ( i_grp != _mapGroups.end() )
2481 gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second );
2483 GEOM::GEOM_Object_var geom;
2484 if ( !gog->_is_nil() )
2486 if ( !theIsBreakLink )
2487 geom = gog->GetShape();
2489 if ( theIsBreakLink || geom->_is_nil() )
2491 SALOMEDS::SObject_wrap grpSO = _gen_i->ObjectToSObject( gog );
2492 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2493 if ( !grpSO->_is_nil() &&
2494 grpSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2495 geomRefSO->ReferencedObject( geomSO.inout() ))
2497 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2498 geom = GEOM::GEOM_Object::_narrow( geomObj );
2502 if ( old2newShapeMap.IsBound( group->GetShape() ))
2504 groupsData.back()._shape = old2newShapeMap( group->GetShape() );
2506 else if ( !geom->_is_nil() )
2508 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2509 if ( meshDS->IsGroupOfSubShapes( groupsData.back()._shape ))
2511 CORBA::String_var ior = geomGen->GetStringFromIOR( geom );
2512 geomClient->RemoveShapeFromBuffer( ior.in() );
2513 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2515 old2newShapeMap.Bind( group->GetShape(), groupsData.back()._shape );
2520 // store assigned hypotheses
2521 std::vector< pair< int, THypList > > ids2Hyps;
2522 const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
2523 for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
2525 const TopoDS_Shape& s = s2hyps.Key();
2526 const THypList& hyps = s2hyps.ChangeValue();
2527 ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
2530 std::multimap< std::set<int>, int > ii2iMap; // group sub-ids to group id in SMESHDS
2532 // count shapes excluding compounds corresponding to geom groups
2533 int oldNbSubShapes = meshDS->MaxShapeIndex();
2534 for ( ; oldNbSubShapes > 0; --oldNbSubShapes )
2536 const TopoDS_Shape& s = meshDS->IndexToShape( oldNbSubShapes );
2537 if ( s.IsNull() || s.ShapeType() != TopAbs_COMPOUND )
2540 std::set<int> subIds;
2541 for ( TopoDS_Iterator it( s ); it.More(); it.Next() )
2542 subIds.insert( meshDS->ShapeToIndex( it.Value() ));
2543 ii2iMap.insert( std::make_pair( subIds, oldNbSubShapes ));
2546 // check if shape topology changes - save shape type per shape ID
2547 std::vector< TopAbs_ShapeEnum > shapeTypes( Max( oldNbSubShapes + 1, 1 ));
2548 for ( int shapeID = oldNbSubShapes; shapeID > 0; --shapeID )
2549 shapeTypes[ shapeID ] = meshDS->IndexToShape( shapeID ).ShapeType();
2551 // change shape to mesh
2552 _impl->ShapeToMesh( TopoDS_Shape() );
2553 _impl->ShapeToMesh( newShape );
2555 // check if shape topology changes - check new shape types
2556 bool sameTopology = ( oldNbSubShapes == meshDS->MaxShapeIndex() );
2557 for ( int shapeID = oldNbSubShapes; shapeID > 0 && sameTopology; --shapeID )
2559 const TopoDS_Shape& s = meshDS->IndexToShape( shapeID );
2560 sameTopology = ( !s.IsNull() && s.ShapeType() == shapeTypes[ shapeID ]);
2563 // re-add shapes (compounds) of geom groups
2564 typedef std::map< std::vector< int >, TGeomGroupData* > TIndices2GroupData;
2565 TIndices2GroupData ii2grData;
2566 std::vector< int > ii;
2567 std::map< int, int > old2newIDs; // group IDs
2568 std::list<TGeomGroupData>::iterator dataIt = _geomGroupData.begin();
2569 for ( ; dataIt != _geomGroupData.end(); ++dataIt )
2571 TGeomGroupData* data = &(*dataIt);
2572 ii.reserve( data->_indices.size() );
2573 ii.assign( data->_indices.begin(), data->_indices.end() );
2574 TIndices2GroupData::iterator ii2gd = ii2grData.insert( std::make_pair( ii, data )).first;
2575 if ( ii2gd->second != data )
2577 data->_groupEntry = ii2gd->second->_groupEntry;
2578 data->_indices = ii2gd->second->_indices;
2581 const int oldNbSub = data->_indices.size();
2582 const int soleOldID = oldNbSub == 1 ? *data->_indices.begin() : 0;
2584 std::multimap< std::set<int>, int >::iterator ii2i = ii2iMap.find( data->_indices );
2585 if ( ii2i != ii2iMap.end() )
2587 oldID = ii2i->second;
2588 ii2iMap.erase( ii2i );
2590 if ( !oldID && oldNbSub == 1 )
2592 if ( old2newIDs.count( oldID ))
2595 int how = ( theIsBreakLink || !sameTopology ) ? IS_BREAK_LINK : MAIN_TRANSFORMED;
2596 newShape = newGroupShape( *data, how );
2598 if ( !newShape.IsNull() )
2600 if ( oldNbSub > 1 && meshDS->ShapeToIndex( newShape ) > 0 ) // group reduced to one sub-shape
2602 TopoDS_Compound compound;
2603 BRep_Builder().MakeCompound( compound );
2604 BRep_Builder().Add( compound, newShape );
2605 newShape = compound;
2607 int newID = _impl->GetSubMesh( newShape )->GetId();
2608 if ( oldID /*&& oldID != newID*/ )
2609 old2newIDs.insert( std::make_pair( oldID, newID ));
2610 if ( oldNbSub == 1 )
2611 old2newIDs.insert( std::make_pair( soleOldID, newID ));
2615 // re-assign hypotheses
2616 for ( size_t i = 0; i < ids2Hyps.size(); ++i )
2618 int sID = ids2Hyps[i].first;
2621 std::map< int, int >::iterator o2n = old2newIDs.find( sID );
2622 if ( o2n != old2newIDs.end() )
2624 else if ( !sameTopology )
2627 const TopoDS_Shape& s = meshDS->IndexToShape( sID );
2630 const THypList& hyps = ids2Hyps[i].second;
2631 THypList::const_iterator h = hyps.begin();
2632 for ( ; h != hyps.end(); ++h )
2633 _impl->AddHypothesis( s, (*h)->GetID() );
2637 // restore groups on geometry
2638 for ( size_t i = 0; i < groupsData.size(); ++i )
2640 const TGroupOnGeomData& data = groupsData[i];
2641 if ( data._shape.IsNull() )
2644 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
2645 if ( i2g == _mapGroups.end() ) continue;
2647 SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
2648 if ( !gr_i ) continue;
2650 SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape );
2652 _mapGroups.erase( i2g );
2654 g->GetGroupDS()->SetColor( data._color );
2657 if ( !sameTopology )
2659 std::map< int, int >::iterator o2n = old2newIDs.begin();
2660 for ( ; o2n != old2newIDs.end(); ++o2n )
2662 int newID = o2n->second, oldID = o2n->first;
2663 if ( newID == oldID || !_mapSubMesh.count( oldID ))
2667 _mapSubMesh [ newID ] = _impl->GetSubMeshContaining( newID );
2668 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2669 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2671 _mapSubMesh. erase(oldID);
2672 _mapSubMesh_i. erase(oldID);
2673 _mapSubMeshIor.erase(oldID);
2675 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2679 // update _mapSubMesh
2680 std::map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
2681 for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
2682 i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
2685 if ( !sameTopology )
2687 // remove invalid study sub-objects
2688 CheckGeomGroupModif();
2691 _gen_i->UpdateIcons( me );
2693 if ( !theIsBreakLink && isShaper )
2695 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2696 if ( !meshSO->_is_nil() )
2697 _gen_i->SetPixMap(meshSO, "ICON_SMESH_TREE_GEOM_MODIF");
2701 //=============================================================================
2703 * \brief Update objects depending on changed geom groups
2705 * NPAL16168: geometrical group edition from a submesh don't modify mesh computation
2706 * issue 0020210: Update of a smesh group after modification of the associated geom group
2708 //=============================================================================
2710 void SMESH_Mesh_i::CheckGeomGroupModif()
2712 // remove sub-meshes referring a removed sub-shapes (if main shape still exists)
2713 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2714 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2715 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() ));
2716 if ( !mainGO->_is_nil() && !meshSO->_is_nil() )
2718 SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO;
2719 for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag )
2720 if ( meshSO->FindSubObject( tag, rootSO.inout() ))
2722 int nbValid = 0, nbRemoved = 0;
2723 SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO );
2724 for ( ; chItr->More(); chItr->Next() )
2726 SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO
2727 if ( !smSO->_is_nil() &&
2728 smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2729 geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference
2731 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2732 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj );
2733 if ( !geom->_non_existent() )
2736 continue; // keep the sub-mesh
2739 CORBA::Object_var smObj = _gen_i->SObjectToObject( smSO );
2740 SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj );
2741 if ( !sm->_is_nil() && !sm->_non_existent() )
2743 GEOM::GEOM_Object_var smGeom = sm->GetSubShape();
2744 if ( smGeom->_is_nil() )
2746 RemoveSubMesh( sm );
2753 _preMeshInfo->ForgetAllData(); // unknown hypothesis modified
2754 builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH
2758 if ( /*nbRemoved > 0 &&*/ nbValid == 0 )
2759 builder->RemoveObjectWithChildren( rootSO );
2763 // check for removed sub-shapes and convert geom dependent groups into standalone ones
2764 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2765 while ( i_gr != _mapGroups.end())
2767 SMESH::SMESH_GroupBase_ptr group = i_gr->second;
2769 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( group ), refSO, geomSO;
2770 SMESH::SMESH_GroupOnGeom_var onGeom = SMESH::SMESH_GroupOnGeom::_narrow ( group );
2771 SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group );
2772 bool isValidGeom = false;
2773 if ( !onGeom->_is_nil() )
2775 isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() ); // check TopoDS
2776 if ( !isValidGeom ) // check reference
2778 isValidGeom = ( ! groupSO->_is_nil() &&
2779 groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ) &&
2780 refSO->ReferencedObject( geomSO.inout() ) &&
2781 ! geomSO->_is_nil() &&
2782 !CORBA::is_nil( CORBA::Object_var( geomSO->GetObject() )));
2785 else if ( !onFilt->_is_nil() )
2787 isValidGeom = isValidGeomFilter( onFilt->GetFilter() );
2791 isValidGeom = ( !groupSO->_is_nil() &&
2792 !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ));
2796 if ( !IsLoaded() || group->IsEmpty() )
2798 RemoveGroup( group );
2800 else if ( !onGeom->_is_nil() || !onFilt->_is_nil() )
2802 SMESH::SMESH_Group_var ( ConvertToStandalone( group ));
2804 else // is it possible?
2806 builder->RemoveObjectWithChildren( refSO );
2812 if ( !_impl->HasShapeToMesh() ) return;
2814 CORBA::Long nbEntities = NbNodes() + NbElements();
2816 // Check if group contents changed
2818 typedef map< string, TopoDS_Shape > TEntry2Geom;
2819 TEntry2Geom newGroupContents;
2821 list<TGeomGroupData>::iterator
2822 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2823 for ( ; data != dataEnd; ++data )
2825 pair< TEntry2Geom::iterator, bool > it_new =
2826 newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
2827 bool processedGroup = !it_new.second;
2828 TopoDS_Shape& newShape = it_new.first->second;
2829 if ( !processedGroup )
2830 newShape = newGroupShape( *data, ONLY_IF_CHANGED );
2831 if ( newShape.IsNull() )
2832 continue; // no changes
2835 _preMeshInfo->ForgetOrLoad();
2837 if ( processedGroup ) { // update group indices
2838 list<TGeomGroupData>::iterator data2 = data;
2839 for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
2840 data->_indices = data2->_indices;
2843 // Update SMESH objects according to new GEOM group contents
2845 SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2846 if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2848 int oldID = submesh->GetId();
2849 if ( !_mapSubMeshIor.count( oldID ))
2851 TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2853 // update hypotheses
2854 list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2855 list <const SMESHDS_Hypothesis * >::iterator hypIt;
2856 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2858 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2859 _impl->AddHypothesis ( newShape, (*hypIt)->GetID());
2861 // care of submeshes
2862 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2863 int newID = newSubmesh->GetId();
2864 if ( newID != oldID ) {
2865 _mapSubMesh [ newID ] = newSubmesh;
2866 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2867 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2868 _mapSubMesh. erase(oldID);
2869 _mapSubMesh_i. erase(oldID);
2870 _mapSubMeshIor.erase(oldID);
2871 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2876 SMESH::SMESH_GroupOnGeom_var smeshGroup =
2877 SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2878 if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2880 SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2882 ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2883 SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2884 ds->SetShape( newShape );
2889 SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2890 if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2892 // Remove groups and submeshes basing on removed sub-shapes
2894 TopTools_MapOfShape newShapeMap;
2895 TopoDS_Iterator shapeIt( newShape );
2896 for ( ; shapeIt.More(); shapeIt.Next() )
2897 newShapeMap.Add( shapeIt.Value() );
2899 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2900 for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2902 if ( newShapeMap.Contains( shapeIt.Value() ))
2904 TopTools_IndexedMapOfShape oldShapeMap;
2905 TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2906 for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2908 const TopoDS_Shape& oldShape = oldShapeMap(i);
2909 int oldInd = meshDS->ShapeToIndex( oldShape );
2911 map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2912 if ( i_smIor != _mapSubMeshIor.end() ) {
2913 RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2916 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2917 for ( ; i_grp != _mapGroups.end(); ++i_grp )
2919 // check if a group bases on oldInd shape
2920 SMESHDS_GroupOnGeom* grpOnGeom = 0;
2921 if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2922 grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2923 if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2925 RemoveGroup( i_grp->second ); // several groups can base on same shape
2926 i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2931 // Reassign hypotheses and update groups after setting the new shape to mesh
2933 // collect anassigned hypotheses
2934 typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2935 list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2936 TShapeHypList assignedHyps;
2937 for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2939 const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2940 list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2941 if ( !hyps.empty() ) {
2942 assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2943 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2944 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2947 // collect shapes supporting groups
2948 typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2949 TShapeTypeList groupData;
2950 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2951 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2952 for ( ; grIt != groups.end(); ++grIt )
2954 if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2956 ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2958 // set new shape to mesh -> DS of sub-meshes and geom groups is deleted
2960 _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
2961 _impl->ShapeToMesh( newShape );
2963 // reassign hypotheses
2964 TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2965 for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2967 TIndexedShape& geom = indS_hyps->first;
2968 list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2969 int oldID = geom._index;
2970 int newID = meshDS->ShapeToIndex( geom._shape );
2971 if ( oldID == 1 ) { // main shape
2973 geom._shape = newShape;
2977 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2978 _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2979 // care of sub-meshes
2980 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2981 if ( newID != oldID ) {
2982 _mapSubMesh [ newID ] = newSubmesh;
2983 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2984 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2985 _mapSubMesh. erase(oldID);
2986 _mapSubMesh_i. erase(oldID);
2987 _mapSubMeshIor.erase(oldID);
2988 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2992 TShapeTypeList::iterator geomType = groupData.begin();
2993 for ( ; geomType != groupData.end(); ++geomType )
2995 const TIndexedShape& geom = geomType->first;
2996 int oldID = geom._index;
2997 if ( _mapGroups.find( oldID ) == _mapGroups.end() )
3000 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( _mapGroups[oldID] );
3001 CORBA::String_var name = groupSO->GetName();
3003 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID]))
3004 if ( SMESH_Group* group = _impl->AddGroup( geomType->second, name.in(),
3005 /*id=*/-1, geom._shape ))
3006 group_i->changeLocalId( group->GetID() );
3009 break; // everything has been updated
3012 } // loop on group data
3016 CORBA::Long newNbEntities = NbNodes() + NbElements();
3017 list< SALOMEDS::SObject_wrap > soToUpdateIcons;
3018 if ( newNbEntities != nbEntities )
3020 // Add all SObjects with icons to soToUpdateIcons
3021 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( _this() )); // mesh
3023 for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
3024 i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
3025 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_sm->second ));
3027 for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
3028 i_gr != _mapGroups.end(); ++i_gr ) // groups
3029 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_gr->second ));
3032 list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
3033 for ( ; so != soToUpdateIcons.end(); ++so )
3034 _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
3037 //=============================================================================
3039 * \brief Create standalone group from a group on geometry or filter
3041 //=============================================================================
3043 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
3044 throw (SALOME::SALOME_Exception)
3046 SMESH::SMESH_Group_var aGroup;
3051 _preMeshInfo->FullLoadFromFile();
3053 if ( theGroup->_is_nil() )
3054 return aGroup._retn();
3056 SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
3058 return aGroup._retn();
3060 const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
3062 const int anId = aGroupToRem->GetLocalID();
3063 if ( !_impl->ConvertToStandalone( anId ) )
3064 return aGroup._retn();
3065 removeGeomGroupData( theGroup );
3067 SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3069 // remove old instance of group from own map
3070 { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
3071 _mapGroups.erase( anId );
3073 SALOMEDS::StudyBuilder_var builder;
3074 SALOMEDS::SObject_wrap aGroupSO;
3075 SALOMEDS::Study_var aStudy = SMESH_Gen_i::getStudyServant();
3076 if ( !aStudy->_is_nil() ) {
3077 builder = aStudy->NewBuilder();
3078 aGroupSO = _gen_i->ObjectToSObject( theGroup );
3079 if ( !aGroupSO->_is_nil() )
3081 // remove reference to geometry
3082 SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
3083 for ( ; chItr->More(); chItr->Next() )
3085 // Remove group's child SObject
3086 SALOMEDS::SObject_wrap so = chItr->Value();
3087 builder->RemoveObject( so );
3089 // Update Python script
3090 TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
3091 << ".ConvertToStandalone( " << aGroupSO << " )";
3093 // change icon of Group on Filter
3096 // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
3097 // const int isEmpty = ( elemTypes->length() == 0 );
3100 SALOMEDS::GenericAttribute_wrap anAttr =
3101 builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
3102 SALOMEDS::AttributePixMap_wrap pm = anAttr;
3103 pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
3109 // remember new group in own map
3110 aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
3111 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3113 // register CORBA object for persistence
3114 _gen_i->RegisterObject( aGroup );
3116 CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
3117 builder->SetIOR( aGroupSO, ior.in() ); // == aGroup->Register();
3118 //aGroup->Register();
3119 aGroupToRem->UnRegister();
3121 SMESH_CATCH( SMESH::throwCorbaException );
3123 return aGroup._retn();
3126 //================================================================================
3128 * \brief Create a sub-mesh on a given sub-shape
3130 //================================================================================
3132 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
3134 if(MYDEBUG) MESSAGE( "createSubMesh" );
3135 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
3136 ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
3139 SMESH_subMesh_i * subMeshServant;
3142 subMeshId = mySubMesh->GetId();
3143 subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
3145 else // "invalid sub-mesh"
3147 // The invalid sub-mesh is created for the case where a valid sub-shape not found
3148 // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0.
3149 if ( _mapSubMesh.empty() )
3152 subMeshId = _mapSubMesh.begin()->first - 1;
3153 subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject);
3156 SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
3158 _mapSubMesh [subMeshId] = mySubMesh;
3159 _mapSubMesh_i [subMeshId] = subMeshServant;
3160 _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
3162 subMeshServant->Register();
3164 // register CORBA object for persistence
3165 int nextId = _gen_i->RegisterObject( subMesh );
3166 if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
3167 else { nextId = 0; } // avoid "unused variable" warning
3169 // to track changes of GEOM groups
3170 if ( subMeshId > 0 )
3171 addGeomGroupData( theSubShapeObject, subMesh );
3173 return subMesh._retn();
3176 //================================================================================
3178 * \brief Return an existing sub-mesh based on a sub-shape with the given ID
3180 //================================================================================
3182 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
3184 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
3185 if ( it == _mapSubMeshIor.end() )
3186 return SMESH::SMESH_subMesh::_nil();
3188 return SMESH::SMESH_subMesh::_duplicate( (*it).second );
3191 //================================================================================
3193 * \brief Remove a sub-mesh based on the given sub-shape
3195 //================================================================================
3197 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
3198 GEOM::GEOM_Object_ptr theSubShapeObject )
3200 bool isHypChanged = false;
3201 if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
3202 return isHypChanged;
3204 const int subMeshId = theSubMesh->GetId();
3206 if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
3209 if (( _mapSubMesh.count( subMeshId )) &&
3210 ( sm = _impl->GetSubMeshContaining( subMeshId )))
3212 TopoDS_Shape S = sm->GetSubShape();
3215 list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
3216 isHypChanged = !hyps.empty();
3217 if ( isHypChanged && _preMeshInfo )
3218 _preMeshInfo->ForgetOrLoad();
3219 list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
3220 for ( ; hyp != hyps.end(); ++hyp )
3221 _impl->RemoveHypothesis(S, (*hyp)->GetID());
3228 SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
3229 isHypChanged = ( aHypList->length() > 0 );
3230 for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
3231 removeHypothesis( theSubShapeObject, aHypList[i] );
3234 catch( const SALOME::SALOME_Exception& ) {
3235 INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
3237 removeGeomGroupData( theSubShapeObject );
3241 std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
3242 if ( id_smi != _mapSubMesh_i.end() )
3243 id_smi->second->UnRegister();
3245 // remove a CORBA object
3246 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
3247 if ( id_smptr != _mapSubMeshIor.end() )
3248 SMESH::SMESH_subMesh_var( id_smptr->second );
3250 _mapSubMesh.erase(subMeshId);
3251 _mapSubMesh_i.erase(subMeshId);
3252 _mapSubMeshIor.erase(subMeshId);
3254 return isHypChanged;
3257 //================================================================================
3259 * \brief Create a group. Group type depends on given arguments
3261 //================================================================================
3263 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
3264 const char* theName,
3266 const TopoDS_Shape& theShape,
3267 const SMESH_PredicatePtr& thePredicate )
3269 std::string newName;
3270 if ( !theName || !theName[0] )
3272 std::set< std::string > presentNames;
3273 std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
3274 for ( ; i_gr != _mapGroups.end(); ++i_gr )
3276 CORBA::String_var name = i_gr->second->GetName();
3277 presentNames.insert( name.in() );
3280 newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
3281 } while ( !presentNames.insert( newName ).second );
3282 theName = newName.c_str();
3284 SMESH::SMESH_GroupBase_var aGroup;
3285 if ( SMESH_Group* g = _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName,
3286 theID, theShape, thePredicate ))
3288 int anId = g->GetID();
3289 SMESH_GroupBase_i* aGroupImpl;
3290 if ( !theShape.IsNull() )
3291 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3292 else if ( thePredicate )
3293 aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
3295 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3297 aGroup = aGroupImpl->_this();
3298 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3299 aGroupImpl->Register();
3301 // register CORBA object for persistence
3302 int nextId = _gen_i->RegisterObject( aGroup );
3303 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
3304 else { nextId = ( nextId > 0 ); } // avoid "unused variable" warning in release mode
3306 // to track changes of GEOM groups
3307 if ( !theShape.IsNull() ) {
3308 GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
3309 addGeomGroupData( geom, aGroup );
3312 return aGroup._retn();
3315 //=============================================================================
3317 * SMESH_Mesh_i::removeGroup
3319 * Should be called by ~SMESH_Group_i()
3321 //=============================================================================
3323 void SMESH_Mesh_i::removeGroup( const int theId )
3325 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
3326 if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
3327 SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
3328 _mapGroups.erase( theId );
3329 removeGeomGroupData( group );
3330 if ( !_impl->RemoveGroup( theId ))
3332 // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
3333 RemoveGroup( group );
3335 group->UnRegister();
3339 //================================================================================
3341 * \brief Return a log that can be used to move another mesh to the same state as this one
3343 //================================================================================
3345 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
3346 throw(SALOME::SALOME_Exception)
3348 SMESH::log_array_var aLog;
3352 _preMeshInfo->FullLoadFromFile();
3354 list < SMESHDS_Command * >logDS = _impl->GetLog();
3355 aLog = new SMESH::log_array;
3357 int lg = logDS.size();
3359 list < SMESHDS_Command * >::iterator its = logDS.begin();
3360 while(its != logDS.end()){
3361 SMESHDS_Command *com = *its;
3362 int comType = com->GetType();
3363 int lgcom = com->GetNumber();
3364 const list < int >&intList = com->GetIndexes();
3365 int inum = intList.size();
3366 list < int >::const_iterator ii = intList.begin();
3367 const list < double >&coordList = com->GetCoords();
3368 int rnum = coordList.size();
3369 list < double >::const_iterator ir = coordList.begin();
3370 aLog[indexLog].commandType = comType;
3371 aLog[indexLog].number = lgcom;
3372 aLog[indexLog].coords.length(rnum);
3373 aLog[indexLog].indexes.length(inum);
3374 for(int i = 0; i < rnum; i++){
3375 aLog[indexLog].coords[i] = *ir;
3378 for(int i = 0; i < inum; i++){
3379 aLog[indexLog].indexes[i] = *ii;
3388 SMESH_CATCH( SMESH::throwCorbaException );
3390 return aLog._retn();
3393 //================================================================================
3395 * \brief Remove the log of commands
3397 //================================================================================
3399 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
3403 SMESH_CATCH( SMESH::throwCorbaException );
3406 //================================================================================
3408 * \brief Return a mesh ID
3410 //================================================================================
3412 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
3417 //=============================================================================
3420 //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
3421 // issue 0020918: groups removal is caused by hyp modification
3422 // issue 0021208: to forget not loaded mesh data at hyp modification
3423 struct TCallUp_i : public SMESH_Mesh::TCallUp
3425 SMESH_Mesh_i* _mesh;
3426 TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
3427 virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
3428 virtual void HypothesisModified( int hypID,
3429 bool updIcons) { _mesh->onHypothesisModified( hypID,
3431 virtual void Load () { _mesh->Load(); }
3432 virtual bool IsLoaded() { return _mesh->IsLoaded(); }
3436 //================================================================================
3438 * \brief callback from _impl to
3439 * 1) forget not loaded mesh data (issue 0021208)
3440 * 2) mark hypothesis as valid
3442 //================================================================================
3444 void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons)
3447 _preMeshInfo->ForgetOrLoad();
3449 if ( theUpdateIcons )
3451 SMESH::SMESH_Mesh_var mesh = _this();
3452 _gen_i->UpdateIcons( mesh );
3455 if ( _nbInvalidHypos != 0 )
3457 // mark a hypothesis as valid after edition
3459 SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
3460 SALOMEDS::SObject_wrap hypRoot;
3461 if ( !smeshComp->_is_nil() &&
3462 smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
3464 SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
3465 for ( ; anIter->More(); anIter->Next() )
3467 SALOMEDS::SObject_wrap hypSO = anIter->Value();
3468 CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO );
3469 SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
3470 if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
3471 _gen_i->HighLightInvalid( hyp, false );
3473 nbInvalid += _gen_i->IsInvalid( hypSO );
3476 _nbInvalidHypos = nbInvalid;
3480 //================================================================================
3482 * \brief Set mesh implementation
3484 //================================================================================
3486 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
3488 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
3491 _impl->SetCallUp( new TCallUp_i(this));
3494 //=============================================================================
3496 * Return a mesh implementation
3498 //=============================================================================
3500 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
3502 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
3506 //=============================================================================
3508 * Return mesh editor
3510 //=============================================================================
3512 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
3513 throw (SALOME::SALOME_Exception)
3515 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3519 _preMeshInfo->FullLoadFromFile();
3521 // Create MeshEditor
3523 _editor = new SMESH_MeshEditor_i( this, false );
3524 aMeshEdVar = _editor->_this();
3526 // Update Python script
3527 TPythonDump() << _editor << " = "
3528 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
3530 SMESH_CATCH( SMESH::throwCorbaException );
3532 return aMeshEdVar._retn();
3535 //=============================================================================
3537 * Return mesh edition previewer
3539 //=============================================================================
3541 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
3542 throw (SALOME::SALOME_Exception)
3544 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3548 _preMeshInfo->FullLoadFromFile();
3550 if ( !_previewEditor )
3551 _previewEditor = new SMESH_MeshEditor_i( this, true );
3552 aMeshEdVar = _previewEditor->_this();
3554 SMESH_CATCH( SMESH::throwCorbaException );
3556 return aMeshEdVar._retn();
3559 //================================================================================
3561 * \brief Return true if the mesh has been edited since a last total re-compute
3562 * and those modifications may prevent successful partial re-compute
3564 //================================================================================
3566 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
3568 Unexpect aCatch(SALOME_SalomeException);
3569 return _impl->HasModificationsToDiscard();
3572 //================================================================================
3574 * \brief Return a random unique color
3576 //================================================================================
3578 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
3580 const int MAX_ATTEMPTS = 100;
3582 double tolerance = 0.5;
3583 SALOMEDS::Color col;
3587 // generate random color
3588 double red = (double)rand() / RAND_MAX;
3589 double green = (double)rand() / RAND_MAX;
3590 double blue = (double)rand() / RAND_MAX;
3591 // check existence in the list of the existing colors
3592 bool matched = false;
3593 std::list<SALOMEDS::Color>::const_iterator it;
3594 for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
3595 SALOMEDS::Color color = *it;
3596 double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B - blue );
3597 matched = tol < tolerance;
3599 if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
3600 ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
3608 //=============================================================================
3610 * Set auto-color mode. If it is on, groups get unique random colors
3612 //=============================================================================
3614 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
3616 Unexpect aCatch(SALOME_SalomeException);
3617 _impl->SetAutoColor(theAutoColor);
3619 TPythonDump pyDump; // not to dump group->SetColor() from below code
3620 pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
3622 std::list<SALOMEDS::Color> aReservedColors;
3623 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
3624 for ( ; it != _mapGroups.end(); it++ ) {
3625 if ( CORBA::is_nil( it->second )) continue;
3626 SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
3627 it->second->SetColor( aColor );
3628 aReservedColors.push_back( aColor );
3632 //=============================================================================
3634 * Return true if auto-color mode is on
3636 //=============================================================================
3638 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
3640 Unexpect aCatch(SALOME_SalomeException);
3641 return _impl->GetAutoColor();
3644 //=============================================================================
3646 * Check if there are groups with equal names
3648 //=============================================================================
3650 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
3652 return _impl->HasDuplicatedGroupNamesMED();
3655 //================================================================================
3657 * \brief Care of a file before exporting mesh into it
3659 //================================================================================
3661 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
3663 SMESH_File aFile( file, false );
3665 if ( aFile.exists() ) {
3666 // existing filesystem node
3667 if ( !aFile.isDirectory() ) {
3668 if ( aFile.openForWriting() ) {
3669 if ( overwrite && ! aFile.remove()) {
3670 msg << "Can't replace " << aFile.getName();
3673 msg << "Can't write into " << aFile.getName();
3676 msg << "Location " << aFile.getName() << " is not a file";
3680 // nonexisting file; check if it can be created
3681 if ( !aFile.openForWriting() ) {
3682 msg << "You cannot create the file "
3684 << ". Check the directory existence and access rights";
3692 THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
3696 //================================================================================
3698 * \brief Prepare a file for export and pass names of mesh groups from study to mesh DS
3699 * \param file - file name
3700 * \param overwrite - to erase the file or not
3701 * \retval string - mesh name
3703 //================================================================================
3705 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char* file,
3706 CORBA::Boolean overwrite)
3709 PrepareForWriting(file, overwrite);
3710 string aMeshName = "Mesh";
3711 SALOMEDS::Study_var aStudy = SMESH_Gen_i::getStudyServant();
3712 if ( !aStudy->_is_nil() ) {
3713 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3714 if ( !aMeshSO->_is_nil() ) {
3715 CORBA::String_var name = aMeshSO->GetName();
3717 // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
3718 if ( !aStudy->GetProperties()->IsLocked() )
3720 SALOMEDS::GenericAttribute_wrap anAttr;
3721 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3722 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
3723 SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
3724 ASSERT(!aFileName->_is_nil());
3725 aFileName->SetValue(file);
3726 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
3727 SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
3728 ASSERT(!aFileType->_is_nil());
3729 aFileType->SetValue("FICHIERMED");
3733 // Update Python script
3734 // set name of mesh before export
3735 TPythonDump() << _gen_i << ".SetName("
3736 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
3738 // check names of groups
3744 //================================================================================
3746 * \brief Export to MED file
3748 //================================================================================
3750 void SMESH_Mesh_i::ExportMED(const char* file,
3751 CORBA::Boolean auto_groups,
3752 CORBA::Long version,
3753 CORBA::Boolean overwrite,
3754 CORBA::Boolean autoDimension)
3755 throw(SALOME::SALOME_Exception)
3757 //MESSAGE("MED minor version: "<< minor);
3760 _preMeshInfo->FullLoadFromFile();
3762 string aMeshName = prepareMeshNameAndGroups(file, overwrite);
3763 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, 0, autoDimension );
3765 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportMED( r'"
3767 << "auto_groups=" <<auto_groups << ", "
3768 << "minor=" << version << ", "
3769 << "overwrite=" << overwrite << ", "
3770 << "meshPart=None, "
3771 << "autoDimension=" << autoDimension << " )";
3773 SMESH_CATCH( SMESH::throwCorbaException );
3776 //================================================================================
3778 * \brief Export a mesh to a SAUV file
3780 //================================================================================
3782 void SMESH_Mesh_i::ExportSAUV (const char* file,
3783 CORBA::Boolean auto_groups)
3784 throw(SALOME::SALOME_Exception)
3786 Unexpect aCatch(SALOME_SalomeException);
3788 _preMeshInfo->FullLoadFromFile();
3790 string aMeshName = prepareMeshNameAndGroups(file, true);
3791 TPythonDump() << SMESH::SMESH_Mesh_var( _this())
3792 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
3793 _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
3797 //================================================================================
3799 * \brief Export a mesh to a DAT file
3801 //================================================================================
3803 void SMESH_Mesh_i::ExportDAT (const char *file)
3804 throw(SALOME::SALOME_Exception)
3806 Unexpect aCatch(SALOME_SalomeException);
3808 _preMeshInfo->FullLoadFromFile();
3810 // Update Python script
3811 // check names of groups
3813 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
3816 PrepareForWriting(file);
3817 _impl->ExportDAT(file);
3820 //================================================================================
3822 * \brief Export a mesh to an UNV file
3824 //================================================================================
3826 void SMESH_Mesh_i::ExportUNV (const char *file)
3827 throw(SALOME::SALOME_Exception)
3829 Unexpect aCatch(SALOME_SalomeException);
3831 _preMeshInfo->FullLoadFromFile();
3833 // Update Python script
3834 // check names of groups
3836 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
3839 PrepareForWriting(file);
3840 _impl->ExportUNV(file);
3843 //================================================================================
3845 * \brief Export a mesh to an STL file
3847 //================================================================================
3849 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3850 throw(SALOME::SALOME_Exception)
3852 Unexpect aCatch(SALOME_SalomeException);
3854 _preMeshInfo->FullLoadFromFile();
3856 // Update Python script
3857 // check names of groups
3859 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3860 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3862 CORBA::String_var name;
3863 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( _this() );
3864 if ( !so->_is_nil() )
3865 name = so->GetName();
3868 PrepareForWriting( file );
3869 _impl->ExportSTL( file, isascii, name.in() );
3872 //================================================================================
3874 * \brief Export a part of mesh to a med file
3876 //================================================================================
3878 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
3880 CORBA::Boolean auto_groups,
3881 CORBA::Long version,
3882 CORBA::Boolean overwrite,
3883 CORBA::Boolean autoDimension,
3884 const GEOM::ListOfFields& fields,
3885 const char* geomAssocFields,
3886 CORBA::Double ZTolerance)
3887 throw (SALOME::SALOME_Exception)
3889 MESSAGE("MED version: "<< version);
3892 _preMeshInfo->FullLoadFromFile();
3895 bool have0dField = false;
3896 if ( fields.length() > 0 )
3898 GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3899 if ( shapeToMesh->_is_nil() )
3900 THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3902 for ( size_t i = 0; i < fields.length(); ++i )
3904 if ( fields[i]->GetDataType() == GEOM::FDT_String )
3905 THROW_SALOME_CORBA_EXCEPTION
3906 ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3907 GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3908 if ( fieldShape->_is_nil() )
3909 THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3910 if ( !fieldShape->IsSame( shapeToMesh ) )
3911 THROW_SALOME_CORBA_EXCEPTION
3912 ( "Field defined not on shape", SALOME::BAD_PARAM);
3913 if ( fields[i]->GetDimension() == 0 )
3916 if ( geomAssocFields )
3917 for ( int i = 0; geomAssocFields[i]; ++i )
3918 switch ( geomAssocFields[i] ) {
3919 case 'v':case 'e':case 'f':case 's': break;
3920 case 'V':case 'E':case 'F':case 'S': break;
3921 default: THROW_SALOME_CORBA_EXCEPTION
3922 ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3926 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3930 string aMeshName = "Mesh";
3931 SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3932 if ( CORBA::is_nil( meshPart ) ||
3933 SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3935 aMeshName = prepareMeshNameAndGroups(file, overwrite);
3936 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3937 0, autoDimension, /*addODOnVertices=*/have0dField,
3939 meshDS = _impl->GetMeshDS();
3944 _preMeshInfo->FullLoadFromFile();
3946 PrepareForWriting(file, overwrite);
3948 SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( meshPart );
3949 if ( !SO->_is_nil() ) {
3950 CORBA::String_var name = SO->GetName();
3954 SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
3955 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3956 partDS, autoDimension, /*addODOnVertices=*/have0dField, ZTolerance);
3957 meshDS = tmpDSDeleter._obj = partDS;
3962 if ( _impl->HasShapeToMesh() )
3964 DriverMED_W_Field fieldWriter;
3965 fieldWriter.SetFile( file );
3966 fieldWriter.SetMeshName( aMeshName );
3967 fieldWriter.AddODOnVertices( have0dField );
3969 exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3973 GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
3974 goList->length( fields.length() );
3975 for ( size_t i = 0; i < fields.length(); ++i )
3977 GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
3980 TPythonDump() << _this() << ".ExportPartToMED( "
3981 << meshPart << ", r'"
3983 << auto_groups << ", "
3985 << overwrite << ", "
3986 << autoDimension << ", "
3988 << ( geomAssocFields ? geomAssocFields : "" ) << "',"
3989 << TVar( ZTolerance )
3992 SMESH_CATCH( SMESH::throwCorbaException );
3995 //================================================================================
3997 * Write GEOM fields to MED file
3999 //================================================================================
4001 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field& fieldWriter,
4002 SMESHDS_Mesh* meshDS,
4003 const GEOM::ListOfFields& fields,
4004 const char* geomAssocFields)
4006 #define METH "SMESH_Mesh_i::exportMEDFields() "
4008 if (( fields.length() < 1 ) &&
4009 ( !geomAssocFields || !geomAssocFields[0] ))
4012 std::vector< std::vector< double > > dblVals;
4013 std::vector< std::vector< int > > intVals;
4014 std::vector< int > subIdsByDim[ 4 ];
4015 const double noneDblValue = 0.;
4016 const double noneIntValue = 0;
4018 for ( size_t iF = 0; iF < fields.length(); ++iF )
4022 int dim = fields[ iF ]->GetDimension();
4023 SMDSAbs_ElementType elemType;
4024 TopAbs_ShapeEnum shapeType;
4026 case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
4027 case 1: elemType = SMDSAbs_Edge; shapeType = TopAbs_EDGE; break;
4028 case 2: elemType = SMDSAbs_Face; shapeType = TopAbs_FACE; break;
4029 case 3: elemType = SMDSAbs_Volume; shapeType = TopAbs_SOLID; break;
4031 continue; // skip fields on whole shape
4033 GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
4034 if ( dataType == GEOM::FDT_String )
4036 GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
4037 if ( stepIDs->length() < 1 )
4039 GEOM::string_array_var comps = fields[ iF ]->GetComponents();
4040 if ( comps->length() < 1 )
4042 CORBA::String_var name = fields[ iF ]->GetName();
4044 if ( !fieldWriter.Set( meshDS,
4048 /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
4051 for ( size_t iC = 0; iC < comps->length(); ++iC )
4052 fieldWriter.SetCompName( iC, comps[ iC ].in() );
4054 dblVals.resize( comps->length() );
4055 intVals.resize( comps->length() );
4057 // find sub-shape IDs
4059 std::vector< int >& subIds = subIdsByDim[ dim ];
4060 if ( subIds.empty() )
4061 for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
4062 if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
4063 subIds.push_back( id );
4067 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4071 for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
4073 GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
4074 if ( step->_is_nil() )
4077 CORBA::Long stamp = step->GetStamp();
4078 CORBA::Long id = step->GetID();
4079 fieldWriter.SetDtIt( int( stamp ), int( id ));
4081 // fill dblVals or intVals
4082 for ( size_t iC = 0; iC < comps->length(); ++iC )
4083 if ( dataType == GEOM::FDT_Double )
4085 dblVals[ iC ].clear();
4086 dblVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4090 intVals[ iC ].clear();
4091 intVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4095 case GEOM::FDT_Double:
4097 GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
4098 if ( dblStep->_is_nil() ) continue;
4099 GEOM::ListOfDouble_var vv = dblStep->GetValues();
4100 if ( vv->length() != subIds.size() * comps->length() )
4101 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4102 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4103 for ( size_t iC = 0; iC < comps->length(); ++iC )
4104 dblVals[ iC ][ subIds[ iS ]] = vv[ iV++ ];
4109 GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
4110 if ( intStep->_is_nil() ) continue;
4111 GEOM::ListOfLong_var vv = intStep->GetValues();
4112 if ( vv->length() != subIds.size() * comps->length() )
4113 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4114 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4115 for ( size_t iC = 0; iC < comps->length(); ++iC )
4116 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4119 case GEOM::FDT_Bool:
4121 GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
4122 if ( boolStep->_is_nil() ) continue;
4123 GEOM::short_array_var vv = boolStep->GetValues();
4124 if ( vv->length() != subIds.size() * comps->length() )
4125 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4126 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4127 for ( size_t iC = 0; iC < comps->length(); ++iC )
4128 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4134 // pass values to fieldWriter
4135 elemIt = fieldWriter.GetOrderedElems();
4136 if ( dataType == GEOM::FDT_Double )
4137 while ( elemIt->more() )
4139 const SMDS_MeshElement* e = elemIt->next();
4140 const int shapeID = e->getshapeId();
4141 if ( shapeID < 1 || shapeID >= (int) dblVals[0].size() )
4142 for ( size_t iC = 0; iC < comps->length(); ++iC )
4143 fieldWriter.AddValue( noneDblValue );
4145 for ( size_t iC = 0; iC < comps->length(); ++iC )
4146 fieldWriter.AddValue( dblVals[ iC ][ shapeID ]);
4149 while ( elemIt->more() )
4151 const SMDS_MeshElement* e = elemIt->next();
4152 const int shapeID = e->getshapeId();
4153 if ( shapeID < 1 || shapeID >= (int) intVals[0].size() )
4154 for ( size_t iC = 0; iC < comps->length(); ++iC )
4155 fieldWriter.AddValue( (double) noneIntValue );
4157 for ( size_t iC = 0; iC < comps->length(); ++iC )
4158 fieldWriter.AddValue( (double) intVals[ iC ][ shapeID ]);
4162 fieldWriter.Perform();
4163 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4164 if ( res && res->IsKO() )
4166 if ( res->myComment.empty() )
4167 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4169 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4175 if ( !geomAssocFields || !geomAssocFields[0] )
4178 // write geomAssocFields
4180 std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
4181 shapeDim[ TopAbs_COMPOUND ] = 3;
4182 shapeDim[ TopAbs_COMPSOLID ] = 3;
4183 shapeDim[ TopAbs_SOLID ] = 3;
4184 shapeDim[ TopAbs_SHELL ] = 2;
4185 shapeDim[ TopAbs_FACE ] = 2;
4186 shapeDim[ TopAbs_WIRE ] = 1;
4187 shapeDim[ TopAbs_EDGE ] = 1;
4188 shapeDim[ TopAbs_VERTEX ] = 0;
4189 shapeDim[ TopAbs_SHAPE ] = 3;
4191 for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
4193 std::vector< std::string > compNames;
4194 switch ( geomAssocFields[ iF ]) {
4196 fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
4197 compNames.push_back( "dim" );
4200 fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
4203 fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
4206 fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
4210 compNames.push_back( "id" );
4211 for ( size_t iC = 0; iC < compNames.size(); ++iC )
4212 fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
4214 fieldWriter.SetDtIt( -1, -1 );
4216 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4220 if ( compNames.size() == 2 ) // _vertices_
4221 while ( elemIt->more() )
4223 const SMDS_MeshElement* e = elemIt->next();
4224 const int shapeID = e->getshapeId();
4227 fieldWriter.AddValue( (double) -1 );
4228 fieldWriter.AddValue( (double) -1 );
4232 const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
4233 fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
4234 fieldWriter.AddValue( (double) shapeID );
4238 while ( elemIt->more() )
4240 const SMDS_MeshElement* e = elemIt->next();
4241 const int shapeID = e->getshapeId();
4243 fieldWriter.AddValue( (double) -1 );
4245 fieldWriter.AddValue( (double) shapeID );
4249 fieldWriter.Perform();
4250 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4251 if ( res && res->IsKO() )
4253 if ( res->myComment.empty() )
4254 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4256 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4259 } // loop on geomAssocFields
4264 //================================================================================
4266 * \brief Export a part of mesh to a DAT file
4268 //================================================================================
4270 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
4272 throw (SALOME::SALOME_Exception)
4274 Unexpect aCatch(SALOME_SalomeException);
4276 _preMeshInfo->FullLoadFromFile();
4278 PrepareForWriting(file);
4280 SMESH_MeshPartDS partDS( meshPart );
4281 _impl->ExportDAT(file,&partDS);
4283 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4284 << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
4286 //================================================================================
4288 * \brief Export a part of mesh to an UNV file
4290 //================================================================================
4292 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
4294 throw (SALOME::SALOME_Exception)
4296 Unexpect aCatch(SALOME_SalomeException);
4298 _preMeshInfo->FullLoadFromFile();
4300 PrepareForWriting(file);
4302 SMESH_MeshPartDS partDS( meshPart );
4303 _impl->ExportUNV(file, &partDS);
4305 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4306 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
4308 //================================================================================
4310 * \brief Export a part of mesh to an STL file
4312 //================================================================================
4314 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
4316 ::CORBA::Boolean isascii)
4317 throw (SALOME::SALOME_Exception)
4319 Unexpect aCatch(SALOME_SalomeException);
4321 _preMeshInfo->FullLoadFromFile();
4323 PrepareForWriting(file);
4325 CORBA::String_var name;
4326 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4327 if ( !so->_is_nil() )
4328 name = so->GetName();
4330 SMESH_MeshPartDS partDS( meshPart );
4331 _impl->ExportSTL( file, isascii, name.in(), &partDS );
4333 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
4334 << meshPart<< ", r'" << file << "', " << isascii << ")";
4337 //================================================================================
4339 * \brief Export a part of mesh to an STL file
4341 //================================================================================
4343 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
4345 CORBA::Boolean overwrite,
4346 CORBA::Boolean groupElemsByType)
4347 throw (SALOME::SALOME_Exception)
4350 Unexpect aCatch(SALOME_SalomeException);
4352 _preMeshInfo->FullLoadFromFile();
4354 PrepareForWriting(file,overwrite);
4356 std::string meshName("");
4357 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4358 if ( !so->_is_nil() )
4360 CORBA::String_var name = so->GetName();
4361 meshName = name.in();
4365 SMESH_MeshPartDS partDS( meshPart );
4366 _impl->ExportCGNS(file, &partDS, meshName.c_str(), groupElemsByType );
4368 SMESH_CATCH( SMESH::throwCorbaException );
4370 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
4371 << meshPart<< ", r'" << file << "', " << overwrite << ")";
4373 THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
4377 //================================================================================
4379 * \brief Export a part of mesh to a GMF file
4381 //================================================================================
4383 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
4385 bool withRequiredGroups)
4386 throw (SALOME::SALOME_Exception)
4388 Unexpect aCatch(SALOME_SalomeException);
4390 _preMeshInfo->FullLoadFromFile();
4392 PrepareForWriting(file,/*overwrite=*/true);
4394 SMESH_MeshPartDS partDS( meshPart );
4395 _impl->ExportGMF(file, &partDS, withRequiredGroups);
4397 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
4398 << meshPart<< ", r'"
4400 << withRequiredGroups << ")";
4403 //=============================================================================
4405 * Return computation progress [0.,1]
4407 //=============================================================================
4409 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
4413 return _impl->GetComputeProgress();
4415 SMESH_CATCH( SMESH::doNothing );
4419 //================================================================================
4421 * \brief Return nb of nodes
4423 //================================================================================
4425 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
4427 Unexpect aCatch(SALOME_SalomeException);
4429 return _preMeshInfo->NbNodes();
4431 return _impl->NbNodes();
4434 //================================================================================
4436 * \brief Return nb of elements
4438 //================================================================================
4440 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
4442 Unexpect aCatch(SALOME_SalomeException);
4444 return _preMeshInfo->NbElements();
4446 return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
4449 //================================================================================
4451 * \brief Return nb of 0D elements
4453 //================================================================================
4455 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
4457 Unexpect aCatch(SALOME_SalomeException);
4459 return _preMeshInfo->Nb0DElements();
4461 return _impl->Nb0DElements();
4464 //================================================================================
4466 * \brief Return nb of BALL elements
4468 //================================================================================
4470 CORBA::Long SMESH_Mesh_i::NbBalls() throw (SALOME::SALOME_Exception)
4472 Unexpect aCatch(SALOME_SalomeException);
4474 return _preMeshInfo->NbBalls();
4476 return _impl->NbBalls();
4479 //================================================================================
4481 * \brief Return nb of 1D elements
4483 //================================================================================
4485 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
4487 Unexpect aCatch(SALOME_SalomeException);
4489 return _preMeshInfo->NbEdges();
4491 return _impl->NbEdges();
4494 //================================================================================
4496 * \brief Return nb of edges
4498 //================================================================================
4500 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
4501 throw(SALOME::SALOME_Exception)
4503 Unexpect aCatch(SALOME_SalomeException);
4505 return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
4507 return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
4510 //================================================================================
4512 * \brief Return nb of faces
4514 //================================================================================
4516 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
4518 Unexpect aCatch(SALOME_SalomeException);
4520 return _preMeshInfo->NbFaces();
4522 return _impl->NbFaces();
4525 //================================================================================
4527 * \brief Return nb of tringles
4529 //================================================================================
4531 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
4533 Unexpect aCatch(SALOME_SalomeException);
4535 return _preMeshInfo->NbTriangles();
4537 return _impl->NbTriangles();
4540 //================================================================================
4542 * \brief Return nb of bi-quadratic triangles
4544 //================================================================================
4546 CORBA::Long SMESH_Mesh_i::NbBiQuadTriangles()throw(SALOME::SALOME_Exception)
4548 Unexpect aCatch(SALOME_SalomeException);
4550 return _preMeshInfo->NbBiQuadTriangles();
4552 return _impl->NbBiQuadTriangles();
4555 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
4557 Unexpect aCatch(SALOME_SalomeException);
4559 return _preMeshInfo->NbQuadrangles();
4561 return _impl->NbQuadrangles();
4564 CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
4566 Unexpect aCatch(SALOME_SalomeException);
4568 return _preMeshInfo->NbBiQuadQuadrangles();
4570 return _impl->NbBiQuadQuadrangles();
4573 CORBA::Long SMESH_Mesh_i::NbPolygons() throw(SALOME::SALOME_Exception)
4575 Unexpect aCatch(SALOME_SalomeException);
4577 return _preMeshInfo->NbPolygons();
4579 return _impl->NbPolygons();
4582 CORBA::Long SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order) throw(SALOME::SALOME_Exception)
4584 Unexpect aCatch(SALOME_SalomeException);
4586 return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
4588 return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
4591 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
4592 throw(SALOME::SALOME_Exception)
4594 Unexpect aCatch(SALOME_SalomeException);
4596 return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
4598 return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
4601 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
4602 throw(SALOME::SALOME_Exception)
4604 Unexpect aCatch(SALOME_SalomeException);
4606 return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
4608 return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
4611 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
4612 throw(SALOME::SALOME_Exception)
4614 Unexpect aCatch(SALOME_SalomeException);
4616 return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
4618 return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
4621 //=============================================================================
4623 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
4625 Unexpect aCatch(SALOME_SalomeException);
4627 return _preMeshInfo->NbVolumes();
4629 return _impl->NbVolumes();
4632 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
4634 Unexpect aCatch(SALOME_SalomeException);
4636 return _preMeshInfo->NbTetras();
4638 return _impl->NbTetras();
4641 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
4643 Unexpect aCatch(SALOME_SalomeException);
4645 return _preMeshInfo->NbHexas();
4647 return _impl->NbHexas();
4650 CORBA::Long SMESH_Mesh_i::NbTriQuadraticHexas()throw(SALOME::SALOME_Exception)
4652 Unexpect aCatch(SALOME_SalomeException);
4654 return _preMeshInfo->NbTriQuadHexas();
4656 return _impl->NbTriQuadraticHexas();
4659 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
4661 Unexpect aCatch(SALOME_SalomeException);
4663 return _preMeshInfo->NbPyramids();
4665 return _impl->NbPyramids();
4668 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
4670 Unexpect aCatch(SALOME_SalomeException);
4672 return _preMeshInfo->NbPrisms();
4674 return _impl->NbPrisms();
4677 CORBA::Long SMESH_Mesh_i::NbHexagonalPrisms()throw(SALOME::SALOME_Exception)
4679 Unexpect aCatch(SALOME_SalomeException);
4681 return _preMeshInfo->NbHexPrisms();
4683 return _impl->NbHexagonalPrisms();
4686 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
4688 Unexpect aCatch(SALOME_SalomeException);
4690 return _preMeshInfo->NbPolyhedrons();
4692 return _impl->NbPolyhedrons();
4695 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
4696 throw(SALOME::SALOME_Exception)
4698 Unexpect aCatch(SALOME_SalomeException);
4700 return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
4702 return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
4705 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
4706 throw(SALOME::SALOME_Exception)
4708 Unexpect aCatch(SALOME_SalomeException);
4710 return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
4712 return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
4715 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
4716 throw(SALOME::SALOME_Exception)
4718 Unexpect aCatch(SALOME_SalomeException);
4720 return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
4722 return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
4725 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
4726 throw(SALOME::SALOME_Exception)
4728 Unexpect aCatch(SALOME_SalomeException);
4730 return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
4732 return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
4735 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
4736 throw(SALOME::SALOME_Exception)
4738 Unexpect aCatch(SALOME_SalomeException);
4740 return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
4742 return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
4745 //=============================================================================
4747 * Return nb of published sub-meshes
4749 //=============================================================================
4751 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
4753 Unexpect aCatch(SALOME_SalomeException);
4754 return _mapSubMesh_i.size();
4757 //=============================================================================
4759 * Dumps mesh into a string
4761 //=============================================================================
4763 char* SMESH_Mesh_i::Dump()
4767 return CORBA::string_dup( os.str().c_str() );
4770 //=============================================================================
4772 * Method of SMESH_IDSource interface
4774 //=============================================================================
4776 SMESH::long_array* SMESH_Mesh_i::GetIDs()
4778 return GetElementsId();
4781 //=============================================================================
4783 * Return ids of all elements
4785 //=============================================================================
4787 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
4788 throw (SALOME::SALOME_Exception)
4790 Unexpect aCatch(SALOME_SalomeException);
4792 _preMeshInfo->FullLoadFromFile();
4794 SMESH::long_array_var aResult = new SMESH::long_array();
4795 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4797 if ( aSMESHDS_Mesh == NULL )
4798 return aResult._retn();
4800 long nbElements = NbElements();
4801 aResult->length( nbElements );
4802 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
4803 for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
4804 aResult[i] = anIt->next()->GetID();
4806 return aResult._retn();
4810 //=============================================================================
4812 * Return ids of all elements of given type
4814 //=============================================================================
4816 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
4817 throw (SALOME::SALOME_Exception)
4819 Unexpect aCatch(SALOME_SalomeException);
4821 _preMeshInfo->FullLoadFromFile();
4823 SMESH::long_array_var aResult = new SMESH::long_array();
4824 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4826 if ( aSMESHDS_Mesh == NULL )
4827 return aResult._retn();
4829 long nbElements = NbElements();
4831 // No sense in returning ids of elements along with ids of nodes:
4832 // when theElemType == SMESH::ALL, return node ids only if
4833 // there are no elements
4834 if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
4835 return GetNodesId();
4837 aResult->length( nbElements );
4841 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
4842 while ( i < nbElements && anIt->more() )
4843 aResult[i++] = anIt->next()->GetID();
4845 aResult->length( i );
4847 return aResult._retn();
4850 //=============================================================================
4852 * Return ids of all nodes
4854 //=============================================================================
4856 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
4857 throw (SALOME::SALOME_Exception)
4859 Unexpect aCatch(SALOME_SalomeException);
4861 _preMeshInfo->FullLoadFromFile();
4863 SMESH::long_array_var aResult = new SMESH::long_array();
4864 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4866 if ( aMeshDS == NULL )
4867 return aResult._retn();
4869 long nbNodes = NbNodes();
4870 aResult->length( nbNodes );
4871 SMDS_NodeIteratorPtr anIt = aMeshDS->nodesIterator();
4872 for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
4873 aResult[i] = anIt->next()->GetID();
4875 return aResult._retn();
4878 //=============================================================================
4880 * Return type of the given element
4882 //=============================================================================
4884 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
4885 throw (SALOME::SALOME_Exception)
4887 SMESH::ElementType type = SMESH::ALL;
4891 _preMeshInfo->FullLoadFromFile();
4893 type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
4895 SMESH_CATCH( SMESH::throwCorbaException );
4900 //=============================================================================
4902 * Return geometric type of the given element
4904 //=============================================================================
4906 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
4907 throw (SALOME::SALOME_Exception)
4910 _preMeshInfo->FullLoadFromFile();
4912 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4914 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4916 return ( SMESH::EntityType ) e->GetEntityType();
4919 //=============================================================================
4921 * Return type of the given element
4923 //=============================================================================
4925 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const CORBA::Long id )
4926 throw (SALOME::SALOME_Exception)
4929 _preMeshInfo->FullLoadFromFile();
4931 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4933 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4935 return ( SMESH::GeometryType ) e->GetGeomType();
4938 //=============================================================================
4940 * Return ID of elements for given submesh
4942 //=============================================================================
4944 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
4945 throw (SALOME::SALOME_Exception)
4947 SMESH::long_array_var aResult = new SMESH::long_array();
4951 _preMeshInfo->FullLoadFromFile();
4953 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4954 if(!SM) return aResult._retn();
4956 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4957 if(!SDSM) return aResult._retn();
4959 aResult->length(SDSM->NbElements());
4961 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4963 while ( eIt->more() ) {
4964 aResult[i++] = eIt->next()->GetID();
4967 SMESH_CATCH( SMESH::throwCorbaException );
4969 return aResult._retn();
4972 //=============================================================================
4974 * Return ID of nodes for given sub-mesh
4975 * If param all==true - return all nodes, else -
4976 * Return only nodes on shapes.
4978 //=============================================================================
4980 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
4982 throw (SALOME::SALOME_Exception)
4984 SMESH::long_array_var aResult = new SMESH::long_array();
4988 _preMeshInfo->FullLoadFromFile();
4990 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4991 if(!SM) return aResult._retn();
4993 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4994 if(!SDSM) return aResult._retn();
4997 if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
4998 SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
4999 while ( nIt->more() ) {
5000 const SMDS_MeshNode* elem = nIt->next();
5001 theElems.insert( elem->GetID() );
5004 else { // all nodes of submesh elements
5005 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5006 while ( eIt->more() ) {
5007 const SMDS_MeshElement* anElem = eIt->next();
5008 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
5009 while ( nIt->more() ) {
5010 const SMDS_MeshElement* elem = nIt->next();
5011 theElems.insert( elem->GetID() );
5016 aResult->length(theElems.size());
5017 set<int>::iterator itElem;
5019 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
5020 aResult[i++] = *itElem;
5022 SMESH_CATCH( SMESH::throwCorbaException );
5024 return aResult._retn();
5027 //=============================================================================
5029 * Return type of elements for given sub-mesh
5031 //=============================================================================
5033 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
5034 throw (SALOME::SALOME_Exception)
5036 SMESH::ElementType type = SMESH::ALL;
5040 _preMeshInfo->FullLoadFromFile();
5042 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5043 if(!SM) return SMESH::ALL;
5045 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5046 if(!SDSM) return SMESH::ALL;
5048 if(SDSM->NbElements()==0)
5049 return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
5051 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5052 const SMDS_MeshElement* anElem = eIt->next();
5054 type = ( SMESH::ElementType ) anElem->GetType();
5056 SMESH_CATCH( SMESH::throwCorbaException );
5062 //=============================================================================
5064 * Return pointer to _impl as an integer value. Is called from constructor of SMESH_Client
5066 //=============================================================================
5068 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
5071 _preMeshInfo->FullLoadFromFile();
5073 CORBA::LongLong pointeur = CORBA::LongLong(_impl);
5074 if ( MYDEBUG ) MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
5079 //=============================================================================
5081 * Get XYZ coordinates of node as list of double
5082 * If there is not node for given ID - return empty list
5084 //=============================================================================
5086 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
5089 _preMeshInfo->FullLoadFromFile();
5091 SMESH::double_array_var aResult = new SMESH::double_array();
5092 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5093 if ( aMeshDS == NULL )
5094 return aResult._retn();
5097 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5099 return aResult._retn();
5103 aResult[0] = aNode->X();
5104 aResult[1] = aNode->Y();
5105 aResult[2] = aNode->Z();
5106 return aResult._retn();
5110 //=============================================================================
5112 * For given node return list of IDs of inverse elements
5113 * If there is not node for given ID - return empty list
5115 //=============================================================================
5117 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id,
5118 SMESH::ElementType elemType)
5121 _preMeshInfo->FullLoadFromFile();
5123 SMESH::long_array_var aResult = new SMESH::long_array();
5124 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5125 if ( aMeshDS == NULL )
5126 return aResult._retn();
5129 const SMDS_MeshNode* aNode = aMeshDS->FindNode( id );
5131 return aResult._retn();
5133 // find inverse elements
5134 SMDSAbs_ElementType type = SMDSAbs_ElementType( elemType );
5135 SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator( type );
5136 aResult->length( aNode->NbInverseElements( type ));
5137 for( int i = 0; eIt->more(); ++i )
5139 const SMDS_MeshElement* elem = eIt->next();
5140 aResult[ i ] = elem->GetID();
5142 return aResult._retn();
5145 //=============================================================================
5147 * \brief Return position of a node on shape
5149 //=============================================================================
5151 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
5154 _preMeshInfo->FullLoadFromFile();
5156 SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
5157 aNodePosition->shapeID = 0;
5158 aNodePosition->shapeType = GEOM::SHAPE;
5160 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5161 if ( !mesh ) return aNodePosition;
5163 if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
5165 if ( SMDS_PositionPtr pos = aNode->GetPosition() )
5167 aNodePosition->shapeID = aNode->getshapeId();
5168 switch ( pos->GetTypeOfPosition() ) {
5170 aNodePosition->shapeType = GEOM::EDGE;
5171 aNodePosition->params.length(1);
5172 aNodePosition->params[0] = SMDS_EdgePositionPtr( pos )->GetUParameter();
5174 case SMDS_TOP_FACE: {
5175 SMDS_FacePositionPtr fPos = pos;
5176 aNodePosition->shapeType = GEOM::FACE;
5177 aNodePosition->params.length(2);
5178 aNodePosition->params[0] = fPos->GetUParameter();
5179 aNodePosition->params[1] = fPos->GetVParameter();
5182 case SMDS_TOP_VERTEX:
5183 aNodePosition->shapeType = GEOM::VERTEX;
5185 case SMDS_TOP_3DSPACE:
5186 if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
5187 aNodePosition->shapeType = GEOM::SOLID;
5188 else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
5189 aNodePosition->shapeType = GEOM::SHELL;
5195 return aNodePosition;
5198 //=============================================================================
5200 * \brief Return position of an element on shape
5202 //=============================================================================
5204 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
5207 _preMeshInfo->FullLoadFromFile();
5209 SMESH::ElementPosition anElementPosition;
5210 anElementPosition.shapeID = 0;
5211 anElementPosition.shapeType = GEOM::SHAPE;
5213 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5214 if ( !mesh ) return anElementPosition;
5216 if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
5218 anElementPosition.shapeID = anElem->getshapeId();
5219 const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
5220 if ( !aSp.IsNull() ) {
5221 switch ( aSp.ShapeType() ) {
5223 anElementPosition.shapeType = GEOM::EDGE;
5226 anElementPosition.shapeType = GEOM::FACE;
5229 anElementPosition.shapeType = GEOM::VERTEX;
5232 anElementPosition.shapeType = GEOM::SOLID;
5235 anElementPosition.shapeType = GEOM::SHELL;
5241 return anElementPosition;
5244 //=============================================================================
5246 * If given element is node return IDs of shape from position
5247 * If there is not node for given ID - return -1
5249 //=============================================================================
5251 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
5254 _preMeshInfo->FullLoadFromFile();
5256 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5257 if ( aMeshDS == NULL )
5261 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5263 return aNode->getshapeId();
5270 //=============================================================================
5272 * For given element return ID of result shape after
5273 * ::FindShape() from SMESH_MeshEditor
5274 * If there is not element for given ID - return -1
5276 //=============================================================================
5278 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
5281 _preMeshInfo->FullLoadFromFile();
5283 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5284 if ( aMeshDS == NULL )
5287 // try to find element
5288 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5292 ::SMESH_MeshEditor aMeshEditor(_impl);
5293 int index = aMeshEditor.FindShape( elem );
5301 //=============================================================================
5303 * Return number of nodes for given element
5304 * If there is not element for given ID - return -1
5306 //=============================================================================
5308 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
5311 _preMeshInfo->FullLoadFromFile();
5313 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5314 if ( aMeshDS == NULL ) return -1;
5315 // try to find element
5316 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5317 if(!elem) return -1;
5318 return elem->NbNodes();
5322 //=============================================================================
5324 * Return ID of node by given index for given element
5325 * If there is not element for given ID - return -1
5326 * If there is not node for given index - return -2
5328 //=============================================================================
5330 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
5333 _preMeshInfo->FullLoadFromFile();
5335 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5336 if ( aMeshDS == NULL ) return -1;
5337 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5338 if(!elem) return -1;
5339 if( index>=elem->NbNodes() || index<0 ) return -1;
5340 return elem->GetNode(index)->GetID();
5343 //=============================================================================
5345 * Return IDs of nodes of given element
5347 //=============================================================================
5349 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
5352 _preMeshInfo->FullLoadFromFile();
5354 SMESH::long_array_var aResult = new SMESH::long_array();
5355 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5357 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(id) )
5359 aResult->length( elem->NbNodes() );
5360 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5361 if ( const SMDS_MeshNode* n = elem->GetNode( i ))
5362 aResult[ i ] = n->GetID();
5365 return aResult._retn();
5368 //=============================================================================
5370 * Return true if given node is medium node
5371 * in given quadratic element
5373 //=============================================================================
5375 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
5378 _preMeshInfo->FullLoadFromFile();
5380 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5381 if ( aMeshDS == NULL ) return false;
5383 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5384 if(!aNode) return false;
5385 // try to find element
5386 const SMDS_MeshElement* elem = aMeshDS->FindElement(ide);
5387 if(!elem) return false;
5389 return elem->IsMediumNode(aNode);
5393 //=============================================================================
5395 * Return true if given node is medium node
5396 * in one of quadratic elements
5398 //=============================================================================
5400 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
5401 SMESH::ElementType theElemType)
5404 _preMeshInfo->FullLoadFromFile();
5406 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5407 if ( aMeshDS == NULL ) return false;
5410 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5411 if(!aNode) return false;
5413 SMESH_MesherHelper aHelper( *(_impl) );
5415 SMDSAbs_ElementType aType;
5416 if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
5417 else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
5418 else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
5419 else aType = SMDSAbs_All;
5421 return aHelper.IsMedium(aNode,aType);
5425 //=============================================================================
5427 * Return number of edges for given element
5429 //=============================================================================
5431 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
5434 _preMeshInfo->FullLoadFromFile();
5436 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5437 if ( aMeshDS == NULL ) return -1;
5438 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5439 if(!elem) return -1;
5440 return elem->NbEdges();
5444 //=============================================================================
5446 * Return number of faces for given element
5448 //=============================================================================
5450 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
5453 _preMeshInfo->FullLoadFromFile();
5455 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5456 if ( aMeshDS == NULL ) return -1;
5457 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5458 if(!elem) return -1;
5459 return elem->NbFaces();
5462 //================================================================================
5464 * \brief Return nodes of given face (counted from zero) for given element.
5466 //================================================================================
5468 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long elemId,
5469 CORBA::Short faceIndex)
5472 _preMeshInfo->FullLoadFromFile();
5474 SMESH::long_array_var aResult = new SMESH::long_array();
5475 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5477 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) )
5479 SMDS_VolumeTool vtool( elem, /*skipCentralNodes = */false );
5480 if ( faceIndex < vtool.NbFaces() )
5482 aResult->length( vtool.NbFaceNodes( faceIndex ));
5483 const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
5484 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5485 aResult[ i ] = nn[ i ]->GetID();
5489 return aResult._retn();
5492 //================================================================================
5494 * \brief Return three components of normal of given mesh face.
5496 //================================================================================
5498 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long elemId,
5499 CORBA::Boolean normalized)
5502 _preMeshInfo->FullLoadFromFile();
5504 SMESH::double_array_var aResult = new SMESH::double_array();
5506 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5509 if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
5511 aResult->length( 3 );
5512 aResult[ 0 ] = normal.X();
5513 aResult[ 1 ] = normal.Y();
5514 aResult[ 2 ] = normal.Z();
5517 return aResult._retn();
5520 //================================================================================
5522 * \brief Return an element based on all given nodes.
5524 //================================================================================
5526 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
5529 _preMeshInfo->FullLoadFromFile();
5531 CORBA::Long elemID(0);
5532 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5534 vector< const SMDS_MeshNode * > nn( nodes.length() );
5535 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5536 if ( !( nn[i] = mesh->FindNode( nodes[i] )))
5539 const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
5540 if ( !elem && ( _impl->NbEdges ( ORDER_QUADRATIC ) ||
5541 _impl->NbFaces ( ORDER_QUADRATIC ) ||
5542 _impl->NbVolumes( ORDER_QUADRATIC )))
5543 elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
5545 if ( elem ) elemID = CORBA::Long( elem->GetID() );
5550 //================================================================================
5552 * \brief Return elements including all given nodes.
5554 //================================================================================
5556 SMESH::long_array* SMESH_Mesh_i::GetElementsByNodes(const SMESH::long_array& nodes,
5557 SMESH::ElementType elemType)
5560 _preMeshInfo->FullLoadFromFile();
5562 SMESH::long_array_var result = new SMESH::long_array();
5564 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5566 vector< const SMDS_MeshNode * > nn( nodes.length() );
5567 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5568 nn[i] = mesh->FindNode( nodes[i] );
5570 std::vector<const SMDS_MeshElement *> elems;
5571 mesh->GetElementsByNodes( nn, elems, (SMDSAbs_ElementType) elemType );
5572 result->length( elems.size() );
5573 for ( size_t i = 0; i < elems.size(); ++i )
5574 result[i] = elems[i]->GetID();
5576 return result._retn();
5579 //=============================================================================
5581 * Return true if given element is polygon
5583 //=============================================================================
5585 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
5588 _preMeshInfo->FullLoadFromFile();
5590 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5591 if ( aMeshDS == NULL ) return false;
5592 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5593 if(!elem) return false;
5594 return elem->IsPoly();
5598 //=============================================================================
5600 * Return true if given element is quadratic
5602 //=============================================================================
5604 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
5607 _preMeshInfo->FullLoadFromFile();
5609 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5610 if ( aMeshDS == NULL ) return false;
5611 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5612 if(!elem) return false;
5613 return elem->IsQuadratic();
5616 //=============================================================================
5618 * Return diameter of ball discrete element or zero in case of an invalid \a id
5620 //=============================================================================
5622 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
5625 _preMeshInfo->FullLoadFromFile();
5627 if ( const SMDS_BallElement* ball =
5628 SMDS_Mesh::DownCast<SMDS_BallElement>( _impl->GetMeshDS()->FindElement( id )))
5629 return ball->GetDiameter();
5634 //=============================================================================
5636 * Return bary center for given element
5638 //=============================================================================
5640 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
5643 _preMeshInfo->FullLoadFromFile();
5645 SMESH::double_array_var aResult = new SMESH::double_array();
5646 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5647 if ( aMeshDS == NULL )
5648 return aResult._retn();
5650 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5652 return aResult._retn();
5654 if(elem->GetType()==SMDSAbs_Volume) {
5655 SMDS_VolumeTool aTool;
5656 if(aTool.Set(elem)) {
5658 if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
5663 SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
5665 double x=0., y=0., z=0.;
5666 for(; anIt->more(); ) {
5668 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
5682 return aResult._retn();
5685 //================================================================================
5687 * \brief Create a group of elements preventing computation of a sub-shape
5689 //================================================================================
5691 SMESH::ListOfGroups*
5692 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int theSubShapeID,
5693 const char* theGroupName )
5694 throw ( SALOME::SALOME_Exception )
5696 Unexpect aCatch(SALOME_SalomeException);
5698 if ( !theGroupName || strlen( theGroupName) == 0 )
5699 THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
5701 SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
5702 ::SMESH_MeshEditor::ElemFeatures elemType;
5704 // submesh by subshape id
5705 if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
5706 if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
5709 SMESH_ComputeErrorPtr error = sm->GetComputeError();
5710 if ( error && error->HasBadElems() )
5712 // sort bad elements by type
5713 vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
5714 const list<const SMDS_MeshElement*>& badElems =
5715 static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
5716 list<const SMDS_MeshElement*>::const_iterator elemIt = badElems.begin();
5717 list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
5718 for ( ; elemIt != elemEnd; ++elemIt )
5720 const SMDS_MeshElement* elem = *elemIt;
5721 if ( !elem ) continue;
5723 if ( elem->GetID() < 1 )
5725 // elem is a temporary element, make a real element
5726 vector< const SMDS_MeshNode* > nodes;
5727 SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
5728 while ( nIt->more() && elem )
5730 nodes.push_back( nIt->next() );
5731 if ( nodes.back()->GetID() < 1 )
5732 elem = 0; // a temporary element on temporary nodes
5736 ::SMESH_MeshEditor editor( _impl );
5737 elem = editor.AddElement( nodes, elemType.Init( elem ));
5741 elemsByType[ elem->GetType() ].push_back( elem );
5744 // how many groups to create?
5746 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5747 nbTypes += int( !elemsByType[ i ].empty() );
5748 groups->length( nbTypes );
5751 for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
5753 vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
5754 if ( elems.empty() ) continue;
5756 groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
5757 if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
5759 SMESH::SMESH_Mesh_var mesh = _this();
5760 SALOMEDS::SObject_wrap aSO =
5761 _gen_i->PublishGroup( mesh, groups[ iG ],
5762 GEOM::GEOM_Object::_nil(), theGroupName);
5764 SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
5765 if ( !grp_i ) continue;
5767 if ( SMESHDS_Group* grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
5768 for ( size_t iE = 0; iE < elems.size(); ++iE )
5769 grpDS->SMDSGroup().Add( elems[ iE ]);
5774 return groups._retn();
5777 //=============================================================================
5779 * Create and publish group servants if any groups were imported or created anyhow
5781 //=============================================================================
5783 void SMESH_Mesh_i::CreateGroupServants()
5785 SMESH::SMESH_Mesh_var aMesh = _this();
5788 ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
5789 while ( groupIt->more() )
5791 ::SMESH_Group* group = groupIt->next();
5792 int anId = group->GetID();
5794 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
5795 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5797 addedIDs.insert( anId );
5799 SMESH_GroupBase_i* aGroupImpl;
5801 if ( SMESHDS_GroupOnGeom* groupOnGeom =
5802 dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
5804 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
5805 shape = groupOnGeom->GetShape();
5808 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
5811 SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
5812 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
5813 aGroupImpl->Register();
5815 // register CORBA object for persistence
5816 int nextId = _gen_i->RegisterObject( groupVar );
5817 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
5818 else { nextId = 0; } // avoid "unused variable" warning in release mode
5820 // publishing the groups in the study
5821 GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
5822 _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName());
5824 if ( !addedIDs.empty() )
5827 set<int>::iterator id = addedIDs.begin();
5828 for ( ; id != addedIDs.end(); ++id )
5830 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
5831 int i = std::distance( _mapGroups.begin(), it );
5832 TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]";
5837 //=============================================================================
5839 * \brief Return true if all sub-meshes are computed OK - to update an icon
5841 //=============================================================================
5843 bool SMESH_Mesh_i::IsComputedOK()
5845 return _impl->IsComputedOK();
5848 //=============================================================================
5850 * \brief Return groups cantained in _mapGroups by their IDs
5852 //=============================================================================
5854 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
5856 int nbGroups = groupIDs.size();
5857 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
5858 aList->length( nbGroups );
5860 list<int>::const_iterator ids = groupIDs.begin();
5861 for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
5863 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
5864 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5865 aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
5867 aList->length( nbGroups );
5868 return aList._retn();
5871 //=============================================================================
5873 * \brief Return information about imported file
5875 //=============================================================================
5877 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
5879 SMESH::MedFileInfo_var res( _medFileInfo );
5880 if ( !res.operator->() ) {
5881 res = new SMESH::MedFileInfo;
5883 res->fileSize = res->major = res->minor = res->release = -1;
5888 //=======================================================================
5889 //function : FileInfoToString
5890 //purpose : Persistence of file info
5891 //=======================================================================
5893 std::string SMESH_Mesh_i::FileInfoToString()
5896 if ( &_medFileInfo.in() && _medFileInfo->fileName[0] )
5898 s = SMESH_Comment( _medFileInfo->fileSize )
5899 << " " << _medFileInfo->major
5900 << " " << _medFileInfo->minor
5901 << " " << _medFileInfo->release
5902 << " " << _medFileInfo->fileName;
5907 //=======================================================================
5908 //function : FileInfoFromString
5909 //purpose : Persistence of file info
5910 //=======================================================================
5912 void SMESH_Mesh_i::FileInfoFromString(const std::string& info)
5914 std::string size, major, minor, release, fileName;
5915 std::istringstream is(info);
5916 is >> size >> major >> minor >> release;
5917 fileName = info.data() + ( size.size() + 1 +
5920 release.size()+ 1 );
5922 _medFileInfo = new SMESH::MedFileInfo();
5923 _medFileInfo->fileName = fileName.c_str();
5924 _medFileInfo->fileSize = atoi( size.c_str() );
5925 _medFileInfo->major = atoi( major.c_str() );
5926 _medFileInfo->minor = atoi( minor.c_str() );
5927 _medFileInfo->release = atoi( release.c_str() );
5930 //=============================================================================
5932 * \brief Pass names of mesh groups from study to mesh DS
5934 //=============================================================================
5936 void SMESH_Mesh_i::checkGroupNames()
5938 int nbGrp = NbGroups();
5942 SMESH::ListOfGroups* grpList = 0;
5943 // avoid dump of "GetGroups"
5945 // store python dump into a local variable inside local scope
5946 SMESH::TPythonDump pDump; // do not delete this line of code
5947 grpList = GetGroups();
5950 for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
5951 SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
5954 SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aGrp );
5955 if ( aGrpSO->_is_nil() )
5957 // correct name of the mesh group if necessary
5958 const char* guiName = aGrpSO->GetName();
5959 if ( strcmp(guiName, aGrp->GetName()) )
5960 aGrp->SetName( guiName );
5964 //=============================================================================
5966 * \brief Set list of notebook variables used for Mesh operations separated by ":" symbol
5968 //=============================================================================
5969 void SMESH_Mesh_i::SetParameters(const char* theParameters)
5971 SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
5975 //=============================================================================
5977 * \brief Return list of notebook variables used for Mesh operations separated by ":" symbol
5979 //=============================================================================
5981 char* SMESH_Mesh_i::GetParameters()
5983 return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
5986 //=============================================================================
5988 * \brief Return list of notebook variables used for last Mesh operation
5990 //=============================================================================
5991 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
5993 SMESH::string_array_var aResult = new SMESH::string_array();
5994 SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
5996 CORBA::String_var aParameters = GetParameters();
5997 SALOMEDS::ListOfListOfStrings_var aSections = SMESH_Gen_i::getStudyServant()->ParseVariables(aParameters);
5998 if ( aSections->length() > 0 ) {
5999 SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
6000 aResult->length( aVars.length() );
6001 for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
6002 aResult[i] = CORBA::string_dup( aVars[i] );
6005 return aResult._retn();
6008 //================================================================================
6010 * \brief Return types of elements it contains
6012 //================================================================================
6014 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
6017 return _preMeshInfo->GetTypes();
6019 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
6023 if (_impl->NbEdges()) types[nbTypes++] = SMESH::EDGE;
6024 if (_impl->NbFaces()) types[nbTypes++] = SMESH::FACE;
6025 if (_impl->NbVolumes()) types[nbTypes++] = SMESH::VOLUME;
6026 if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
6027 if (_impl->NbBalls()) types[nbTypes++] = SMESH::BALL;
6028 if (_impl->NbNodes() &&
6029 nbTypes == 0 ) types[nbTypes++] = SMESH::NODE;
6030 types->length( nbTypes );
6032 return types._retn();
6035 //================================================================================
6037 * \brief Return self
6039 //================================================================================
6041 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
6043 return SMESH::SMESH_Mesh::_duplicate( _this() );
6046 //================================================================================
6048 * \brief Return false if GetMeshInfo() return incorrect information that may
6049 * happen if mesh data is not yet fully loaded from the file of study.
6053 //================================================================================
6055 bool SMESH_Mesh_i::IsMeshInfoCorrect()
6057 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
6060 //=============================================================================
6062 * \brief Return number of mesh elements per each \a EntityType
6064 //=============================================================================
6066 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
6069 return _preMeshInfo->GetMeshInfo();
6071 SMESH::long_array_var aRes = new SMESH::long_array();
6072 aRes->length(SMESH::Entity_Last);
6073 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6075 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6077 return aRes._retn();
6078 const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
6079 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6080 aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
6081 return aRes._retn();
6084 //=============================================================================
6086 * \brief Return number of mesh elements per each \a ElementType
6088 //=============================================================================
6090 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
6092 SMESH::long_array_var aRes = new SMESH::long_array();
6093 aRes->length(SMESH::NB_ELEMENT_TYPES);
6094 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6097 const SMDS_MeshInfo* meshInfo = 0;
6099 meshInfo = _preMeshInfo;
6100 else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
6101 meshInfo = & meshDS->GetMeshInfo();
6104 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6105 aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
6107 return aRes._retn();
6110 //=============================================================================
6112 * Collect statistic of mesh elements given by iterator
6114 //=============================================================================
6116 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
6117 SMESH::long_array& theInfo)
6119 if (!theItr) return;
6120 while (theItr->more())
6121 theInfo[ theItr->next()->GetEntityType() ]++;
6123 //=============================================================================
6125 * Return mesh unstructed grid information.
6127 //=============================================================================
6129 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
6131 SALOMEDS::TMPFile_var SeqFile;
6132 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
6133 SMDS_UnstructuredGrid* aGrid = aMeshDS->GetGrid();
6135 vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
6136 aWriter->WriteToOutputStringOn();
6137 aWriter->SetInputData(aGrid);
6138 aWriter->SetFileTypeToBinary();
6140 char* str = aWriter->GetOutputString();
6141 int size = aWriter->GetOutputStringLength();
6143 //Allocate octet buffer of required size
6144 CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
6145 //Copy ostrstream content to the octet buffer
6146 memcpy(OctetBuf, str, size);
6147 //Create and return TMPFile
6148 SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
6152 return SeqFile._retn();
6155 //=============================================================================
6156 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
6157 * SMESH::ElementType type) */
6159 using namespace SMESH::Controls;
6160 //-----------------------------------------------------------------------------
6161 struct PredicateIterator : public SMDS_ElemIterator
6163 SMDS_ElemIteratorPtr _elemIter;
6164 PredicatePtr _predicate;
6165 const SMDS_MeshElement* _elem;
6166 SMDSAbs_ElementType _type;
6168 PredicateIterator( SMDS_ElemIteratorPtr iterator,
6169 PredicatePtr predicate,
6170 SMDSAbs_ElementType type):
6171 _elemIter(iterator), _predicate(predicate), _type(type)
6179 virtual const SMDS_MeshElement* next()
6181 const SMDS_MeshElement* res = _elem;
6183 while ( _elemIter->more() && !_elem )
6185 if ((_elem = _elemIter->next()) &&
6186 (( _type != SMDSAbs_All && _type != _elem->GetType() ) ||
6187 ( !_predicate->IsSatisfy( _elem->GetID() ))))
6194 //-----------------------------------------------------------------------------
6195 struct IDSourceIterator : public SMDS_ElemIterator
6197 const CORBA::Long* _idPtr;
6198 const CORBA::Long* _idEndPtr;
6199 SMESH::long_array_var _idArray;
6200 const SMDS_Mesh* _mesh;
6201 const SMDSAbs_ElementType _type;
6202 const SMDS_MeshElement* _elem;
6204 IDSourceIterator( const SMDS_Mesh* mesh,
6205 const CORBA::Long* ids,
6207 SMDSAbs_ElementType type):
6208 _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
6210 if ( _idPtr && nbIds && _mesh )
6213 IDSourceIterator( const SMDS_Mesh* mesh,
6214 SMESH::long_array* idArray,
6215 SMDSAbs_ElementType type):
6216 _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
6218 if ( idArray && _mesh )
6220 _idPtr = &_idArray[0];
6221 _idEndPtr = _idPtr + _idArray->length();
6229 virtual const SMDS_MeshElement* next()
6231 const SMDS_MeshElement* res = _elem;
6233 while ( _idPtr < _idEndPtr && !_elem )
6235 if ( _type == SMDSAbs_Node )
6237 _elem = _mesh->FindNode( *_idPtr++ );
6239 else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
6240 (_elem->GetType() != _type && _type != SMDSAbs_All ))
6248 //-----------------------------------------------------------------------------
6250 struct NodeOfElemIterator : public SMDS_ElemIterator
6252 TColStd_MapOfInteger _checkedNodeIDs;
6253 SMDS_ElemIteratorPtr _elemIter;
6254 SMDS_ElemIteratorPtr _nodeIter;
6255 const SMDS_MeshElement* _node;
6257 NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
6259 if ( _elemIter && _elemIter->more() )
6261 _nodeIter = _elemIter->next()->nodesIterator();
6269 virtual const SMDS_MeshElement* next()
6271 const SMDS_MeshElement* res = _node;
6273 while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
6275 if ( _nodeIter->more() )
6277 _node = _nodeIter->next();
6278 if ( !_checkedNodeIDs.Add( _node->GetID() ))
6283 _nodeIter = _elemIter->next()->nodesIterator();
6291 //=============================================================================
6293 * Return iterator on elements of given type in given object
6295 //=============================================================================
6297 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
6298 SMESH::ElementType theType)
6300 SMDS_ElemIteratorPtr elemIt;
6301 bool typeOK = ( theType == SMESH::ALL );
6302 SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
6304 SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
6305 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
6306 if ( !mesh_i ) return elemIt;
6307 SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
6309 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
6311 elemIt = meshDS->elementsIterator( elemType );
6314 else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
6316 SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
6319 elemIt = sm->GetElements();
6320 if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6322 typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
6323 elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
6327 else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
6329 SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
6330 if ( groupDS && ( elemType == groupDS->GetType() ||
6331 elemType == SMDSAbs_Node ||
6332 elemType == SMDSAbs_All ))
6334 elemIt = groupDS->GetElements();
6335 typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
6338 else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
6340 if ( filter_i->GetElementType() == theType ||
6341 filter_i->GetElementType() == SMESH::ALL ||
6342 elemType == SMDSAbs_Node ||
6343 elemType == SMDSAbs_All)
6345 SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
6346 if ( pred_i && pred_i->GetPredicate() )
6348 SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
6349 SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
6350 SMDSAbs_ElementType iterType = elemType == SMDSAbs_Node ? filterType : elemType;
6351 elemIt = SMDS_ElemIteratorPtr
6352 ( new PredicateIterator( allElemIt, pred_i->GetPredicate(), iterType ));
6353 typeOK = ( elemType == SMDSAbs_Node ? filterType == SMDSAbs_Node : elemIt->more() );
6359 SMESH::array_of_ElementType_var types = theObject->GetTypes();
6360 const bool isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
6361 if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6363 SMDSAbs_ElementType iterType = isNodes ? SMDSAbs_Node : elemType;
6364 if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
6367 if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
6368 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, iterType ));
6372 SMESH::long_array_var ids = theObject->GetIDs();
6373 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), iterType ));
6375 typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
6378 if ( elemIt && elemIt->more() && !typeOK )
6380 if ( elemType == SMDSAbs_Node )
6382 elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
6386 elemIt = SMDS_ElemIteratorPtr();
6392 //=============================================================================
6393 namespace // Finding concurrent hypotheses
6394 //=============================================================================
6398 * \brief mapping of mesh dimension into shape type
6400 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
6402 TopAbs_ShapeEnum aType = TopAbs_SOLID;
6404 case 0: aType = TopAbs_VERTEX; break;
6405 case 1: aType = TopAbs_EDGE; break;
6406 case 2: aType = TopAbs_FACE; break;
6408 default:aType = TopAbs_SOLID; break;
6413 //-----------------------------------------------------------------------------
6415 * \brief Internal structure used to find concurrent submeshes
6417 * It represents a pair < submesh, concurrent dimension >, where
6418 * 'concurrent dimension' is dimension of shape where the submesh can concurrent
6419 * with another submesh. In other words, it is dimension of a hypothesis assigned
6426 int _dim; //!< a dimension the algo can build (concurrent dimension)
6427 int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
6428 TopTools_MapOfShape _shapeMap; //!< [sub-]shapes of dimension == _dim
6429 SMESH_subMesh* _subMesh;
6430 list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
6432 //-----------------------------------------------------------------------------
6433 // Return the algorithm
6434 const SMESH_Algo* GetAlgo() const
6435 { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
6437 //-----------------------------------------------------------------------------
6439 SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
6441 const TopoDS_Shape& theShape)
6443 _subMesh = (SMESH_subMesh*)theSubMesh;
6444 SetShape( theDim, theShape );
6447 //-----------------------------------------------------------------------------
6449 void SetShape(const int theDim,
6450 const TopoDS_Shape& theShape)
6453 _ownDim = SMESH_Gen::GetShapeDim(theShape);
6454 if (_dim >= _ownDim)
6455 _shapeMap.Add( theShape );
6457 TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
6458 for( ; anExp.More(); anExp.Next() )
6459 _shapeMap.Add( anExp.Current() );
6463 //-----------------------------------------------------------------------------
6464 //! Check sharing of sub-shapes
6465 static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
6466 const TopTools_MapOfShape& theToFind,
6467 const TopAbs_ShapeEnum theType)
6469 bool isShared = false;
6470 TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
6471 for (; !isShared && anItr.More(); anItr.Next() )
6473 const TopoDS_Shape aSubSh = anItr.Key();
6474 // check for case when concurrent dimensions are same
6475 isShared = theToFind.Contains( aSubSh );
6476 // check for sub-shape with concurrent dimension
6477 TopExp_Explorer anExp( aSubSh, theType );
6478 for ( ; !isShared && anExp.More(); anExp.Next() )
6479 isShared = theToFind.Contains( anExp.Current() );
6484 //-----------------------------------------------------------------------------
6485 //! check algorithms
6486 static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
6487 const SMESHDS_Hypothesis* theA2)
6489 if ( !theA1 || !theA2 ||
6490 theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
6491 theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
6492 return false; // one of the hypothesis is not algorithm
6493 // check algorithm names (should be equal)
6494 return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
6498 //-----------------------------------------------------------------------------
6499 //! Check if sub-shape hypotheses are concurrent
6500 bool IsConcurrent(const SMESH_DimHyp* theOther) const
6502 if ( _subMesh == theOther->_subMesh )
6503 return false; // same sub-shape - should not be
6505 // if ( <own dim of either of submeshes> == <concurrent dim> &&
6506 // any of the two submeshes is not on COMPOUND shape )
6507 // -> no concurrency
6508 bool meIsCompound = (_subMesh->GetSubMeshDS() &&
6509 _subMesh->GetSubMeshDS()->IsComplexSubmesh());
6510 bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
6511 theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
6512 if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
6515 bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
6516 if ( !checkSubShape )
6519 // check algorithms to be same
6520 const SMESH_Algo* a1 = this->GetAlgo();
6521 const SMESH_Algo* a2 = theOther->GetAlgo();
6522 bool isSame = checkAlgo( a1, a2 );
6526 // commented off for IPAL54678
6527 // if ( !a1 || !a2 )
6528 // return false; // pb?
6529 // return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency !
6532 // check hypothesises for concurrence (skip first as algorithm)
6534 // pointers should be same, because it is referened from mesh hypothesis partition
6535 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
6536 list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
6537 for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
6538 if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
6540 // the submeshes are concurrent if their algorithms has different parameters
6541 return nbSame != theOther->_hypotheses.size() - 1;
6544 // Return true if algorithm of this SMESH_DimHyp is used if no
6545 // sub-mesh order is imposed by the user
6546 bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
6548 // NeedDiscreteBoundary() algo has a higher priority
6549 if ( this ->GetAlgo()->NeedDiscreteBoundary() !=
6550 theOther->GetAlgo()->NeedDiscreteBoundary() )
6551 return !this->GetAlgo()->NeedDiscreteBoundary();
6553 return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
6556 }; // end of SMESH_DimHyp
6557 //-----------------------------------------------------------------------------
6559 typedef list<const SMESH_DimHyp*> TDimHypList;
6561 //-----------------------------------------------------------------------------
6563 void addDimHypInstance(const int theDim,
6564 const TopoDS_Shape& theShape,
6565 const SMESH_Algo* theAlgo,
6566 const SMESH_subMesh* theSubMesh,
6567 const list <const SMESHDS_Hypothesis*>& theHypList,
6568 TDimHypList* theDimHypListArr )
6570 if ( !theAlgo->NeedDiscreteBoundary() &&
6571 theAlgo->NeedLowerHyps( theDim )) // IPAL54678
6573 TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
6574 if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
6575 SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
6576 dimHyp->_hypotheses.push_front(theAlgo);
6577 listOfdimHyp.push_back( dimHyp );
6580 SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
6581 dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
6582 theHypList.begin(), theHypList.end() );
6585 //-----------------------------------------------------------------------------
6586 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
6587 TDimHypList& theListOfConcurr)
6589 if ( theListOfConcurr.empty() )
6591 theListOfConcurr.push_back( theDimHyp );
6595 TDimHypList::iterator hypIt = theListOfConcurr.begin();
6596 while ( hypIt != theListOfConcurr.end() &&
6597 !theDimHyp->IsHigherPriorityThan( *hypIt ))
6599 theListOfConcurr.insert( hypIt, theDimHyp );
6603 //-----------------------------------------------------------------------------
6604 void findConcurrents(const SMESH_DimHyp* theDimHyp,
6605 const TDimHypList& theListOfDimHyp,
6606 TDimHypList& theListOfConcurrHyp,
6607 set<int>& theSetOfConcurrId )
6609 TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
6610 for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
6612 const SMESH_DimHyp* curDimHyp = *rIt;
6613 if ( curDimHyp == theDimHyp )
6614 break; // meet own dimHyp pointer in same dimension
6616 if ( theDimHyp->IsConcurrent( curDimHyp ) &&
6617 theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
6619 addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
6624 //-----------------------------------------------------------------------------
6625 void unionLists(TListOfInt& theListOfId,
6626 TListOfListOfInt& theListOfListOfId,
6629 TListOfListOfInt::iterator it = theListOfListOfId.begin();
6630 for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
6632 continue; //skip already treated lists
6633 // check if other list has any same submesh object
6634 TListOfInt& otherListOfId = *it;
6635 if ( find_first_of( theListOfId.begin(), theListOfId.end(),
6636 otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
6639 // union two lists (from source into target)
6640 TListOfInt::iterator it2 = otherListOfId.begin();
6641 for ( ; it2 != otherListOfId.end(); it2++ ) {
6642 if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
6643 theListOfId.push_back(*it2);
6645 // clear source list
6646 otherListOfId.clear();
6649 //-----------------------------------------------------------------------------
6651 //! free memory allocated for dimension-hypothesis objects
6652 void removeDimHyps( TDimHypList* theArrOfList )
6654 for (int i = 0; i < 4; i++ ) {
6655 TDimHypList& listOfdimHyp = theArrOfList[i];
6656 TDimHypList::const_iterator it = listOfdimHyp.begin();
6657 for ( ; it != listOfdimHyp.end(); it++ )
6662 //-----------------------------------------------------------------------------
6664 * \brief find common submeshes with given submesh
6665 * \param theSubMeshList list of already collected submesh to check
6666 * \param theSubMesh given submesh to intersect with other
6667 * \param theCommonSubMeshes collected common submeshes
6669 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
6670 const SMESH_subMesh* theSubMesh,
6671 set<const SMESH_subMesh*>& theCommon )
6675 list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
6676 for ( ; it != theSubMeshList.end(); it++ )
6677 theSubMesh->FindIntersection( *it, theCommon );
6678 theSubMeshList.push_back( theSubMesh );
6679 //theCommon.insert( theSubMesh );
6682 //-----------------------------------------------------------------------------
6683 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
6685 TListOfListOfInt::const_iterator listsIt = smLists.begin();
6686 for ( ; listsIt != smLists.end(); ++listsIt )
6688 const TListOfInt& smIDs = *listsIt;
6689 if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
6697 //=============================================================================
6699 * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
6701 //=============================================================================
6703 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
6705 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6706 if ( isSubMeshInList( submeshID, anOrder ))
6709 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6710 return isSubMeshInList( submeshID, allConurrent );
6713 //=============================================================================
6715 * \brief Return sub-mesh objects list in meshing order
6717 //=============================================================================
6719 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
6721 SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
6723 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6725 return aResult._retn();
6727 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6728 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6729 anOrder.splice( anOrder.end(), allConurrent );
6732 TListOfListOfInt::iterator listIt = anOrder.begin();
6733 for(; listIt != anOrder.end(); listIt++, listIndx++ )
6734 unionLists( *listIt, anOrder, listIndx + 1 );
6736 // convert submesh ids into interface instances
6737 // and dump command into python
6738 convertMeshOrder( anOrder, aResult, false );
6740 return aResult._retn();
6743 //=============================================================================
6745 * \brief Finds concurrent sub-meshes
6747 //=============================================================================
6749 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
6751 TListOfListOfInt anOrder;
6752 ::SMESH_Mesh& mesh = GetImpl();
6754 // collect submeshes and detect concurrent algorithms and hypothesises
6755 TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
6757 map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
6758 for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
6759 ::SMESH_subMesh* sm = (*i_sm).second;
6761 const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
6763 // list of assigned hypothesises
6764 const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
6765 // Find out dimensions where the submesh can be concurrent.
6766 // We define the dimensions by algo of each of hypotheses in hypList
6767 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
6768 for( ; hypIt != hypList.end(); hypIt++ ) {
6769 SMESH_Algo* anAlgo = 0;
6770 const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
6771 if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
6772 // hyp it-self is algo
6773 anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
6775 // try to find algorithm with help of sub-shapes
6776 TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
6777 for ( ; !anAlgo && anExp.More(); anExp.Next() )
6778 anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
6781 continue; // no algorithm assigned to a current submesh
6783 int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
6784 // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary()
6785 // and !anAlgo->NeedLowerHyps( dim ))
6787 // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
6788 for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
6789 addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
6791 } // end iterations on submesh
6793 // iterate on created dimension-hypotheses and check for concurrents
6794 for ( int i = 0; i < 4; i++ ) {
6795 const TDimHypList& listOfDimHyp = dimHypListArr[i];
6796 // check for concurrents in own and other dimensions (step-by-step)
6797 TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
6798 for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
6799 const SMESH_DimHyp* dimHyp = *dhIt;
6800 TDimHypList listOfConcurr;
6801 set<int> setOfConcurrIds;
6802 // looking for concurrents and collect into own list
6803 for ( int j = i; j < 4; j++ )
6804 findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
6805 // check if any concurrents found
6806 if ( listOfConcurr.size() > 0 ) {
6807 // add own submesh to list of concurrent
6808 addInOrderOfPriority( dimHyp, listOfConcurr );
6809 list<int> listOfConcurrIds;
6810 TDimHypList::iterator hypIt = listOfConcurr.begin();
6811 for ( ; hypIt != listOfConcurr.end(); ++hypIt )
6812 listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
6813 anOrder.push_back( listOfConcurrIds );
6818 removeDimHyps(dimHypListArr);
6820 // now, minimize the number of concurrent groups
6821 // Here we assume that lists of submeshes can have same submesh
6822 // in case of multi-dimension algorithms, as result
6823 // list with common submesh has to be united into one list
6825 TListOfListOfInt::iterator listIt = anOrder.begin();
6826 for(; listIt != anOrder.end(); listIt++, listIndx++ )
6827 unionLists( *listIt, anOrder, listIndx + 1 );
6833 //=============================================================================
6835 * \brief Set submesh object order
6836 * \param theSubMeshArray submesh array order
6838 //=============================================================================
6840 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
6843 _preMeshInfo->ForgetOrLoad();
6846 ::SMESH_Mesh& mesh = GetImpl();
6848 TPythonDump aPythonDump; // prevent dump of called methods
6849 aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
6851 TListOfListOfInt subMeshOrder;
6852 for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
6854 const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
6855 TListOfInt subMeshIds;
6857 aPythonDump << ", ";
6858 aPythonDump << "[ ";
6859 // Collect subMeshes which should be clear
6860 // do it list-by-list, because modification of submesh order
6861 // take effect between concurrent submeshes only
6862 set<const SMESH_subMesh*> subMeshToClear;
6863 list<const SMESH_subMesh*> subMeshList;
6864 for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
6866 const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
6868 aPythonDump << ", ";
6869 aPythonDump << subMesh;
6870 subMeshIds.push_back( subMesh->GetId() );
6871 // detect common parts of submeshes
6872 if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
6873 findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
6875 aPythonDump << " ]";
6876 subMeshOrder.push_back( subMeshIds );
6878 // clear collected sub-meshes
6879 set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
6880 for ( ; clrIt != subMeshToClear.end(); clrIt++ )
6881 if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
6883 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
6884 if ( SMESH_Algo* algo = sm->GetAlgo() ) // #16748
6885 sm->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, algo ); // to clear a cached algo
6888 aPythonDump << " ])";
6890 mesh.SetMeshOrder( subMeshOrder );
6893 SMESH::SMESH_Mesh_var me = _this();
6894 _gen_i->UpdateIcons( me );
6899 //=============================================================================
6901 * \brief Convert submesh ids into submesh interfaces
6903 //=============================================================================
6905 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt& theIdsOrder,
6906 SMESH::submesh_array_array& theResOrder,
6907 const bool theIsDump)
6909 int nbSet = theIdsOrder.size();
6910 TPythonDump aPythonDump; // prevent dump of called methods
6912 aPythonDump << "[ ";
6913 theResOrder.length(nbSet);
6914 TListOfListOfInt::const_iterator it = theIdsOrder.begin();
6916 for( ; it != theIdsOrder.end(); it++ ) {
6917 // translate submesh identificators into submesh objects
6918 // takeing into account real number of concurrent lists
6919 const TListOfInt& aSubOrder = (*it);
6920 if (!aSubOrder.size())
6923 aPythonDump << "[ ";
6924 // convert shape indices into interfaces
6925 SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
6926 aResSubSet->length(aSubOrder.size());
6927 TListOfInt::const_iterator subIt = aSubOrder.begin();
6929 for( j = 0; subIt != aSubOrder.end(); subIt++ ) {
6930 if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
6932 SMESH::SMESH_subMesh_var subMesh =
6933 SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
6936 aPythonDump << ", ";
6937 aPythonDump << subMesh;
6939 aResSubSet[ j++ ] = subMesh;
6942 aPythonDump << " ]";
6944 theResOrder[ listIndx++ ] = aResSubSet;
6946 // correct number of lists
6947 theResOrder.length( listIndx );
6950 // finilise python dump
6951 aPythonDump << " ]";
6952 aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
6956 namespace // utils used by SMESH_MeshPartDS
6959 * \brief Class used to access to protected data of SMDS_MeshInfo
6961 struct TMeshInfo : public SMDS_MeshInfo
6963 void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
6966 * \brief Element holing its ID only
6968 struct TElemID : public SMDS_LinearEdge
6970 TElemID(int ID) : SMDS_LinearEdge(0,0) { setID( ID ); }
6974 //================================================================================
6976 // Implementation of SMESH_MeshPartDS
6978 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
6979 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
6981 SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
6982 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
6985 _meshDS = mesh_i->GetImpl().GetMeshDS();
6987 SetPersistentId( _meshDS->GetPersistentId() );
6989 if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
6991 // <meshPart> is the whole mesh
6992 myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
6994 set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
6995 myGroupSet = _meshDS->GetGroups();
7000 SMESH::long_array_var anIDs = meshPart->GetIDs();
7001 SMESH::array_of_ElementType_var types = meshPart->GetTypes();
7002 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
7004 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7005 if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
7006 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7011 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7012 if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
7013 if ( _elements[ e->GetType() ].insert( e ).second )
7016 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7017 while ( nIt->more() )
7019 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7020 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7027 ShapeToMesh( _meshDS->ShapeToMesh() );
7029 _meshDS = 0; // to enforce iteration on _elements and _nodes
7032 // -------------------------------------------------------------------------------------
7033 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
7034 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
7037 list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
7038 for ( ; partIt != meshPart.end(); ++partIt )
7039 if ( const SMDS_MeshElement * e = *partIt )
7040 if ( _elements[ e->GetType() ].insert( e ).second )
7043 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7044 while ( nIt->more() )
7046 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7047 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7053 // -------------------------------------------------------------------------------------
7054 const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const
7056 if ( _meshDS ) return _meshDS->FindElement( IDelem );
7058 TElemID elem( IDelem );
7059 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7060 if ( !_elements[ iType ].empty() )
7062 TIDSortedElemSet::const_iterator it = _elements[ iType ].find( &elem );
7063 if ( it != _elements[ iType ].end() )
7068 // -------------------------------------------------------------------------------------
7069 bool SMESH_MeshPartDS::HasNumerationHoles()
7071 if ( _meshDS ) return _meshDS->HasNumerationHoles();
7073 return ( MinNodeID() != 1 ||
7074 MaxNodeID() != NbNodes() ||
7075 MinElementID() != 1 ||
7076 MaxElementID() != NbElements() );
7078 // -------------------------------------------------------------------------------------
7079 int SMESH_MeshPartDS::MaxNodeID() const
7081 if ( _meshDS ) return _meshDS->MaxNodeID();
7082 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].rbegin())->GetID();
7084 // -------------------------------------------------------------------------------------
7085 int SMESH_MeshPartDS::MinNodeID() const
7087 if ( _meshDS ) return _meshDS->MinNodeID();
7088 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].begin())->GetID();
7090 // -------------------------------------------------------------------------------------
7091 int SMESH_MeshPartDS::MaxElementID() const
7093 if ( _meshDS ) return _meshDS->MaxElementID();
7095 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7096 if ( !_elements[ iType ].empty() )
7097 maxID = Max( maxID, (*_elements[ iType ].rbegin())->GetID() );
7100 // -------------------------------------------------------------------------------------
7101 int SMESH_MeshPartDS::MinElementID() const
7103 if ( _meshDS ) return _meshDS->MinElementID();
7105 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7106 if ( !_elements[ iType ].empty() )
7107 minID = Min( minID, (*_elements[ iType ].begin())->GetID() );
7110 // -------------------------------------------------------------------------------------
7111 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
7113 if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
7115 typedef SMDS_SetIterator
7116 <const SMDS_MeshElement*,
7117 TIDSortedElemSet::const_iterator,
7118 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7119 SMDS_MeshElement::GeomFilter
7122 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( geomType );
7124 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7125 _elements[type].end(),
7126 SMDS_MeshElement::GeomFilter( geomType )));
7128 // -------------------------------------------------------------------------------------
7129 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
7131 if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
7133 typedef SMDS_SetIterator
7134 <const SMDS_MeshElement*,
7135 TIDSortedElemSet::const_iterator,
7136 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7137 SMDS_MeshElement::EntityFilter
7140 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( entity );
7142 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7143 _elements[type].end(),
7144 SMDS_MeshElement::EntityFilter( entity )));
7146 // -------------------------------------------------------------------------------------
7147 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
7149 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
7150 if ( type == SMDSAbs_All && !_meshDS )
7152 typedef vector< SMDS_ElemIteratorPtr > TIterVec;
7154 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
7155 if ( !_elements[i].empty() && i != SMDSAbs_Node )
7157 ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
7159 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
7160 return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
7162 return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
7163 ( new TIter( _elements[type].begin(), _elements[type].end() ));
7165 // -------------------------------------------------------------------------------------
7166 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType) \
7167 iterType SMESH_MeshPartDS::methName() const \
7169 typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
7170 return _meshDS ? _meshDS->methName() : iterType \
7171 ( new TIter( _elements[elemType].begin(), _elements[elemType].end() )); \
7173 // -------------------------------------------------------------------------------------
7174 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
7175 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
7176 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
7177 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
7178 #undef _GET_ITER_DEFINE
7180 // END Implementation of SMESH_MeshPartDS
7182 //================================================================================