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 if ( geomClient->Find( S, aIOR ))
2062 geomClient->RemoveShapeFromBuffer( aIOR );
2064 // clear buffer also for sub-groups
2065 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2066 const std::set<SMESHDS_GroupBase*>& groups = meshDS->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 );
2076 // clear buffer also for sub-meshes
2077 std::map<int, SMESH_subMesh_i*>::const_iterator aSubMeshIter = _mapSubMesh_i.cbegin();
2078 for(; aSubMeshIter != _mapSubMesh_i.cend(); aSubMeshIter++) {
2079 int aShapeID = aSubMeshIter->first;
2080 const TopoDS_Shape& aSubShape = meshDS->IndexToShape(aShapeID);
2081 TCollection_AsciiString aShapeIOR;
2082 if ( geomClient->Find( aSubShape, aShapeIOR ))
2083 geomClient->RemoveShapeFromBuffer( aShapeIOR );
2087 int shapeID, fromID, toID; // indices of elements of a sub-mesh
2089 std::vector< TRange > elemRanges, nodeRanges; // elements of sub-meshes
2090 std::vector< SMDS_PositionPtr > positions; // node positions
2093 // store positions of elements on geometry
2095 if ( meshDS->MaxNodeID() > meshDS->NbNodes() ||
2096 meshDS->MaxElementID() > meshDS->NbElements() )
2099 meshDS->CompactMesh();
2101 positions.resize( meshDS->NbNodes() + 1 );
2102 for ( SMDS_NodeIteratorPtr nodeIt = meshDS->nodesIterator(); nodeIt->more(); )
2104 const SMDS_MeshNode* n = nodeIt->next();
2105 positions[ n->GetID() ] = n->GetPosition();
2108 // remove elements from sub-meshes to avoid their removal at hypotheses addition
2109 for ( int isNode = 0; isNode < 2; ++isNode )
2111 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2112 ranges.reserve( meshDS->MaxShapeIndex() + 10 );
2113 ranges.push_back( TRange{ 0,0,0 });
2114 SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
2115 while ( elemIt->more() )
2117 const SMDS_MeshElement* e = elemIt->next();
2118 const int elemID = e->GetID();
2119 const int shapeID = e->GetShapeID();
2120 TRange & lastRange = ranges.back();
2121 if ( lastRange.shapeID != shapeID ||
2122 lastRange.toID != elemID )
2123 ranges.push_back( TRange{ shapeID, elemID, elemID + 1 });
2125 lastRange.toID = elemID + 1;
2127 if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( shapeID ))
2129 if ( isNode ) sm->RemoveNode( static_cast< const SMDS_MeshNode *>( e ));
2130 else sm->RemoveElement( e );
2137 // update the reference to theNewGeom (needed for correct execution of a dumped python script)
2138 SMESH::SMESH_Mesh_var me = _this();
2139 SALOMEDS::SObject_wrap aSO = _gen_i->ObjectToSObject( me );
2140 CORBA::String_var entry = theNewGeom->GetStudyEntry();
2141 if ( !aSO->_is_nil() )
2143 SALOMEDS::SObject_wrap aShapeRefSO;
2144 if ( aSO->FindSubObject( _gen_i->GetRefOnShapeTag(), aShapeRefSO.inout() ))
2146 SALOMEDS::SObject_wrap aShapeSO = _gen_i->getStudyServant()->FindObjectID( entry );
2147 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2148 builder->Addreference( aShapeRefSO, aShapeSO );
2152 // re-assign global hypotheses to the new shape
2153 _mainShapeTick = geomChanged ? -1 : theNewGeom->GetTick();
2154 CheckGeomModif( true );
2158 // restore positions of elements on geometry
2159 for ( int isNode = 0; isNode < 2; ++isNode )
2161 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2162 for ( size_t i = 1; i < ranges.size(); ++i )
2164 int elemID = ranges[ i ].fromID;
2165 int toID = ranges[ i ].toID;
2166 SMESHDS_SubMesh * smDS = meshDS->NewSubMesh( ranges[ i ].shapeID );
2168 for ( ; elemID < toID; ++elemID )
2169 smDS->AddNode( meshDS->FindNode( elemID ));
2171 for ( ; elemID < toID; ++elemID )
2172 smDS->AddElement( meshDS->FindElement( elemID ));
2174 if ( SMESH_subMesh* sm = _impl->GetSubMeshContaining( ranges[ i ].shapeID ))
2175 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
2178 for ( unsigned int nodeID = 1; nodeID < positions.size(); ++nodeID )
2179 if ( positions[ nodeID ])
2180 if ( SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( meshDS->FindNode( nodeID )))
2181 n->SetPosition( positions[ nodeID ], n->GetShapeID() );
2184 _gen_i->UpdateIcons( SMESH::SMESH_Mesh_var( _this() ));
2187 TPythonDump() << "SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject("
2188 << me <<".GetMesh()), " << entry.in() << ")";
2190 TPythonDump() << me << ".ReplaceShape( " << entry.in() << " )";
2194 //================================================================================
2196 * \brief Return new group contents if it has been changed and update group data
2198 //================================================================================
2200 enum { ONLY_IF_CHANGED, IS_BREAK_LINK, MAIN_TRANSFORMED };
2202 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData, int how )
2204 TopoDS_Shape newShape;
2205 SALOMEDS::SObject_wrap groupSO;
2207 if ( how == IS_BREAK_LINK )
2209 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( groupData._smeshObject );
2210 SALOMEDS::SObject_wrap geomRefSO;
2211 if ( !meshSO->_is_nil() &&
2212 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ))
2214 geomRefSO->ReferencedObject( groupSO.inout() );
2220 groupSO = _gen_i->getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
2223 if ( groupSO->_is_nil() )
2226 CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
2227 GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
2228 if ( geomGroup->_is_nil() )
2231 // get indices of group items
2232 set<int> curIndices;
2233 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( geomGroup );
2234 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
2235 GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
2236 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2237 curIndices.insert( ids[i] );
2239 bool sameIndices = ( groupData._indices == curIndices );
2240 if ( how == ONLY_IF_CHANGED && sameIndices )
2241 return newShape; // group not changed
2244 CORBA::String_var entry = geomGroup->GetStudyEntry();
2245 groupData._groupEntry = entry.in();
2246 groupData._indices = curIndices;
2248 newShape = _gen_i->GeomObjectToShape( geomGroup );
2250 // check if newShape is up-to-date
2251 if ( !newShape.IsNull() && ids->length() > 0 )
2253 bool toUpdate = ! _impl->GetMeshDS()->IsGroupOfSubShapes( newShape );
2256 TopExp_Explorer exp( newShape, (TopAbs_ShapeEnum)( groupOp->GetType( geomGroup )));
2257 for ( ; exp.More() && !toUpdate; exp.Next() )
2259 int ind = _impl->GetMeshDS()->ShapeToIndex( exp.Current() );
2260 toUpdate = ( curIndices.erase( ind ) == 0 );
2262 if ( !curIndices.empty() )
2267 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2268 CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
2269 geomClient->RemoveShapeFromBuffer( groupIOR.in() );
2270 newShape = _gen_i->GeomObjectToShape( geomGroup );
2275 // geom group becomes empty - return empty compound
2276 TopoDS_Compound compound;
2277 BRep_Builder().MakeCompound(compound);
2278 newShape = compound;
2286 //-----------------------------------------------------------------------------
2288 * \brief Storage of shape and index used in CheckGeomGroupModif()
2290 struct TIndexedShape
2293 TopoDS_Shape _shape;
2294 TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
2296 //-----------------------------------------------------------------------------
2298 * \brief Data to re-create a group on geometry
2300 struct TGroupOnGeomData
2303 TopoDS_Shape _shape;
2304 SMDSAbs_ElementType _type;
2306 Quantity_Color _color;
2308 TGroupOnGeomData( const SMESHDS_GroupOnGeom* group )
2310 _oldID = group->GetID();
2311 _type = group->GetType();
2312 _name = group->GetStoreName();
2313 _color = group->GetColor();
2317 //-----------------------------------------------------------------------------
2319 * \brief Check if a filter is still valid after geometry removal
2321 bool isValidGeomFilter( SMESH::Filter_var theFilter )
2323 if ( theFilter->_is_nil() )
2325 SMESH::Filter::Criteria_var criteria;
2326 theFilter->GetCriteria( criteria.out() );
2328 for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
2330 const char* thresholdID = criteria[ iCr ].ThresholdID.in();
2332 switch ( criteria[ iCr ].Type )
2334 case SMESH::FT_BelongToGeom:
2335 case SMESH::FT_BelongToPlane:
2336 case SMESH::FT_BelongToCylinder:
2337 case SMESH::FT_BelongToGenSurface:
2338 case SMESH::FT_LyingOnGeom:
2339 entry = thresholdID;
2341 case SMESH::FT_ConnectedElements:
2344 entry = thresholdID;
2350 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
2351 SALOMEDS::SObject_wrap so = gen->getStudyServant()->FindObjectID( entry.c_str() );
2352 if ( so->_is_nil() )
2354 CORBA::Object_var obj = so->GetObject();
2355 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj );
2356 if ( gen->GeomObjectToShape( geom ).IsNull() )
2359 } // loop on criteria
2365 //=============================================================================
2367 * \brief Update data if geometry changes
2371 //=============================================================================
2373 void SMESH_Mesh_i::CheckGeomModif( bool theIsBreakLink )
2375 SMESH::SMESH_Mesh_var me = _this();
2376 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2378 TPythonDump dumpNothing; // prevent any dump
2380 //bool removedFromClient = false;
2382 if ( mainGO->_is_nil() ) // GEOM_Client cleared or geometry removed? (IPAL52735, PAL23636)
2384 //removedFromClient = _impl->HasShapeToMesh();
2386 // try to find geometry by study reference
2387 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2388 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2389 if ( !meshSO->_is_nil() &&
2390 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2391 geomRefSO->ReferencedObject( geomSO.inout() ))
2393 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2394 mainGO = GEOM::GEOM_Object::_narrow( geomObj );
2397 if ( mainGO->_is_nil() && // geometry removed ==>
2398 !geomRefSO->_is_nil() ) // remove geom dependent data: sub-meshes etc.
2400 // convert geom dependent groups into standalone ones
2401 CheckGeomGroupModif();
2403 _impl->ShapeToMesh( TopoDS_Shape() );
2405 // remove sub-meshes
2406 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2407 while ( i_sm != _mapSubMeshIor.end() )
2409 SMESH::SMESH_subMesh_ptr sm = i_sm->second;
2411 RemoveSubMesh( sm );
2413 // remove all children except groups in the study
2414 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2415 SALOMEDS::SObject_wrap so;
2416 for ( CORBA::Long tag = SMESH::Tag_RefOnShape; tag <= SMESH::Tag_LastSubMesh; ++tag )
2417 if ( meshSO->FindSubObject( tag, so.inout() ))
2418 builder->RemoveObjectWithChildren( so );
2420 _gen_i->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED" );
2426 if ( !_impl->HasShapeToMesh() ) return;
2429 // Update after group modification
2431 const bool geomChanged = ( mainGO->GetTick() != _mainShapeTick );
2432 if ( !theIsBreakLink )
2433 if ( mainGO->GetType() == GEOM_GROUP || !geomChanged ) // is group or not modified
2435 int nb = NbNodes() + NbElements();
2436 CheckGeomGroupModif();
2437 if ( nb != NbNodes() + NbElements() ) // something removed due to hypotheses change
2438 _gen_i->UpdateIcons( me );
2442 // Update after shape modification or breakLink w/o geometry change
2444 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2445 if ( !geomClient ) return;
2446 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( mainGO );
2447 if ( geomGen->_is_nil() ) return;
2448 CORBA::String_var geomComponentType = geomGen->ComponentDataType();
2449 bool isShaper = ( strcmp( geomComponentType.in(), "SHAPERSTUDY" ) == 0 );
2451 SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
2453 TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
2454 if ( meshDS->ShapeToIndex( newShape ) == 1 ) // not yet updated
2456 CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
2457 geomClient->RemoveShapeFromBuffer( ior.in() );
2458 newShape = _gen_i->GeomObjectToShape( mainGO );
2461 // Update data taking into account that if topology doesn't change
2462 // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
2465 _preMeshInfo->ForgetAllData();
2467 if ( geomChanged || !isShaper )
2469 if ( newShape.IsNull() )
2472 _mainShapeTick = mainGO->GetTick();
2474 // store data of groups on geometry including new TopoDS_Shape's
2475 std::vector< TGroupOnGeomData > groupsData;
2476 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2477 groupsData.reserve( groups.size() );
2478 TopTools_DataMapOfShapeShape old2newShapeMap;
2479 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2480 for ( ; g != groups.end(); ++g )
2482 if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
2484 groupsData.push_back( TGroupOnGeomData( group ));
2487 SMESH::SMESH_GroupOnGeom_var gog;
2488 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.find( group->GetID() );
2489 if ( i_grp != _mapGroups.end() )
2490 gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second );
2492 GEOM::GEOM_Object_var geom;
2493 if ( !gog->_is_nil() )
2495 if ( !theIsBreakLink )
2496 geom = gog->GetShape();
2498 if ( theIsBreakLink || geom->_is_nil() )
2500 SALOMEDS::SObject_wrap grpSO = _gen_i->ObjectToSObject( gog );
2501 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2502 if ( !grpSO->_is_nil() &&
2503 grpSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2504 geomRefSO->ReferencedObject( geomSO.inout() ))
2506 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2507 geom = GEOM::GEOM_Object::_narrow( geomObj );
2511 if ( old2newShapeMap.IsBound( group->GetShape() ))
2513 groupsData.back()._shape = old2newShapeMap( group->GetShape() );
2515 else if ( !geom->_is_nil() )
2517 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2518 if ( meshDS->IsGroupOfSubShapes( groupsData.back()._shape ))
2520 CORBA::String_var ior = geomGen->GetStringFromIOR( geom );
2521 geomClient->RemoveShapeFromBuffer( ior.in() );
2522 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2524 old2newShapeMap.Bind( group->GetShape(), groupsData.back()._shape );
2529 // store assigned hypotheses
2530 std::vector< pair< int, THypList > > ids2Hyps;
2531 const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
2532 for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
2534 const TopoDS_Shape& s = s2hyps.Key();
2535 const THypList& hyps = s2hyps.ChangeValue();
2536 ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
2539 std::multimap< std::set<int>, int > ii2iMap; // group sub-ids to group id in SMESHDS
2541 // count shapes excluding compounds corresponding to geom groups
2542 int oldNbSubShapes = meshDS->MaxShapeIndex();
2543 for ( ; oldNbSubShapes > 0; --oldNbSubShapes )
2545 const TopoDS_Shape& s = meshDS->IndexToShape( oldNbSubShapes );
2546 if ( s.IsNull() || s.ShapeType() != TopAbs_COMPOUND )
2549 std::set<int> subIds;
2550 for ( TopoDS_Iterator it( s ); it.More(); it.Next() )
2551 subIds.insert( meshDS->ShapeToIndex( it.Value() ));
2552 ii2iMap.insert( std::make_pair( subIds, oldNbSubShapes ));
2555 // check if shape topology changes - save shape type per shape ID
2556 std::vector< TopAbs_ShapeEnum > shapeTypes( Max( oldNbSubShapes + 1, 1 ));
2557 for ( int shapeID = oldNbSubShapes; shapeID > 0; --shapeID )
2558 shapeTypes[ shapeID ] = meshDS->IndexToShape( shapeID ).ShapeType();
2560 // change shape to mesh
2561 _impl->ShapeToMesh( TopoDS_Shape() );
2562 _impl->ShapeToMesh( newShape );
2564 // check if shape topology changes - check new shape types
2565 bool sameTopology = ( oldNbSubShapes == meshDS->MaxShapeIndex() );
2566 for ( int shapeID = oldNbSubShapes; shapeID > 0 && sameTopology; --shapeID )
2568 const TopoDS_Shape& s = meshDS->IndexToShape( shapeID );
2569 sameTopology = ( !s.IsNull() && s.ShapeType() == shapeTypes[ shapeID ]);
2572 // re-add shapes (compounds) of geom groups
2573 typedef std::map< std::vector< int >, TGeomGroupData* > TIndices2GroupData;
2574 TIndices2GroupData ii2grData;
2575 std::vector< int > ii;
2576 std::map< int, int > old2newIDs; // group IDs
2577 std::list<TGeomGroupData>::iterator dataIt = _geomGroupData.begin();
2578 for ( ; dataIt != _geomGroupData.end(); ++dataIt )
2580 TGeomGroupData* data = &(*dataIt);
2581 ii.reserve( data->_indices.size() );
2582 ii.assign( data->_indices.begin(), data->_indices.end() );
2583 TIndices2GroupData::iterator ii2gd = ii2grData.insert( std::make_pair( ii, data )).first;
2584 if ( ii2gd->second != data )
2586 data->_groupEntry = ii2gd->second->_groupEntry;
2587 data->_indices = ii2gd->second->_indices;
2590 const int oldNbSub = data->_indices.size();
2591 const int soleOldID = oldNbSub == 1 ? *data->_indices.begin() : 0;
2593 std::multimap< std::set<int>, int >::iterator ii2i = ii2iMap.find( data->_indices );
2594 if ( ii2i != ii2iMap.end() )
2596 oldID = ii2i->second;
2597 ii2iMap.erase( ii2i );
2599 if ( !oldID && oldNbSub == 1 )
2601 if ( old2newIDs.count( oldID ))
2604 int how = ( theIsBreakLink || !sameTopology ) ? IS_BREAK_LINK : MAIN_TRANSFORMED;
2605 newShape = newGroupShape( *data, how );
2607 if ( !newShape.IsNull() )
2609 if ( oldNbSub > 1 && meshDS->ShapeToIndex( newShape ) > 0 ) // group reduced to one sub-shape
2611 TopoDS_Compound compound;
2612 BRep_Builder().MakeCompound( compound );
2613 BRep_Builder().Add( compound, newShape );
2614 newShape = compound;
2616 int newID = _impl->GetSubMesh( newShape )->GetId();
2617 if ( oldID /*&& oldID != newID*/ )
2618 old2newIDs.insert( std::make_pair( oldID, newID ));
2619 if ( oldNbSub == 1 )
2620 old2newIDs.insert( std::make_pair( soleOldID, newID ));
2624 // re-assign hypotheses
2625 for ( size_t i = 0; i < ids2Hyps.size(); ++i )
2627 int sID = ids2Hyps[i].first;
2630 std::map< int, int >::iterator o2n = old2newIDs.find( sID );
2631 if ( o2n != old2newIDs.end() )
2633 else if ( !sameTopology )
2636 const TopoDS_Shape& s = meshDS->IndexToShape( sID );
2639 const THypList& hyps = ids2Hyps[i].second;
2640 THypList::const_iterator h = hyps.begin();
2641 for ( ; h != hyps.end(); ++h )
2642 _impl->AddHypothesis( s, (*h)->GetID() );
2646 // restore groups on geometry
2647 for ( size_t i = 0; i < groupsData.size(); ++i )
2649 const TGroupOnGeomData& data = groupsData[i];
2650 if ( data._shape.IsNull() )
2653 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
2654 if ( i2g == _mapGroups.end() ) continue;
2656 SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
2657 if ( !gr_i ) continue;
2659 SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape );
2661 _mapGroups.erase( i2g );
2663 g->GetGroupDS()->SetColor( data._color );
2666 if ( !sameTopology )
2668 std::map< int, int >::iterator o2n = old2newIDs.begin();
2669 for ( ; o2n != old2newIDs.end(); ++o2n )
2671 int newID = o2n->second, oldID = o2n->first;
2672 if ( newID == oldID || !_mapSubMesh.count( oldID ))
2676 _mapSubMesh [ newID ] = _impl->GetSubMeshContaining( newID );
2677 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2678 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2680 _mapSubMesh. erase(oldID);
2681 _mapSubMesh_i. erase(oldID);
2682 _mapSubMeshIor.erase(oldID);
2684 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2688 // update _mapSubMesh
2689 std::map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
2690 for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
2691 i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
2694 if ( !sameTopology )
2696 // remove invalid study sub-objects
2697 CheckGeomGroupModif();
2700 _gen_i->UpdateIcons( me );
2702 if ( !theIsBreakLink && isShaper )
2704 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2705 if ( !meshSO->_is_nil() )
2706 _gen_i->SetPixMap(meshSO, "ICON_SMESH_TREE_GEOM_MODIF");
2710 //=============================================================================
2712 * \brief Update objects depending on changed geom groups
2714 * NPAL16168: geometrical group edition from a submesh don't modify mesh computation
2715 * issue 0020210: Update of a smesh group after modification of the associated geom group
2717 //=============================================================================
2719 void SMESH_Mesh_i::CheckGeomGroupModif()
2721 // remove sub-meshes referring a removed sub-shapes (if main shape still exists)
2722 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2723 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2724 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() ));
2725 if ( !mainGO->_is_nil() && !meshSO->_is_nil() )
2727 SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO;
2728 for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag )
2729 if ( meshSO->FindSubObject( tag, rootSO.inout() ))
2731 int nbValid = 0, nbRemoved = 0;
2732 SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO );
2733 for ( ; chItr->More(); chItr->Next() )
2735 SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO
2736 if ( !smSO->_is_nil() &&
2737 smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2738 geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference
2740 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2741 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj );
2742 if ( !geom->_non_existent() )
2745 continue; // keep the sub-mesh
2748 CORBA::Object_var smObj = _gen_i->SObjectToObject( smSO );
2749 SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj );
2750 if ( !sm->_is_nil() && !sm->_non_existent() )
2752 GEOM::GEOM_Object_var smGeom = sm->GetSubShape();
2753 if ( smGeom->_is_nil() )
2755 RemoveSubMesh( sm );
2762 _preMeshInfo->ForgetAllData(); // unknown hypothesis modified
2763 builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH
2767 if ( /*nbRemoved > 0 &&*/ nbValid == 0 )
2768 builder->RemoveObjectWithChildren( rootSO );
2772 // check for removed sub-shapes and convert geom dependent groups into standalone ones
2773 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2774 while ( i_gr != _mapGroups.end())
2776 SMESH::SMESH_GroupBase_ptr group = i_gr->second;
2778 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( group ), refSO, geomSO;
2779 SMESH::SMESH_GroupOnGeom_var onGeom = SMESH::SMESH_GroupOnGeom::_narrow ( group );
2780 SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group );
2781 bool isValidGeom = false;
2782 if ( !onGeom->_is_nil() )
2784 isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() ); // check TopoDS
2785 if ( !isValidGeom ) // check reference
2787 isValidGeom = ( ! groupSO->_is_nil() &&
2788 groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ) &&
2789 refSO->ReferencedObject( geomSO.inout() ) &&
2790 ! geomSO->_is_nil() &&
2791 !CORBA::is_nil( CORBA::Object_var( geomSO->GetObject() )));
2794 else if ( !onFilt->_is_nil() )
2796 isValidGeom = isValidGeomFilter( onFilt->GetFilter() );
2800 isValidGeom = ( !groupSO->_is_nil() &&
2801 !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ));
2805 if ( !IsLoaded() || group->IsEmpty() )
2807 RemoveGroup( group );
2809 else if ( !onGeom->_is_nil() || !onFilt->_is_nil() )
2811 SMESH::SMESH_Group_var ( ConvertToStandalone( group ));
2813 else // is it possible?
2815 builder->RemoveObjectWithChildren( refSO );
2821 if ( !_impl->HasShapeToMesh() ) return;
2823 CORBA::Long nbEntities = NbNodes() + NbElements();
2825 // Check if group contents changed
2827 typedef map< string, TopoDS_Shape > TEntry2Geom;
2828 TEntry2Geom newGroupContents;
2830 list<TGeomGroupData>::iterator
2831 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2832 for ( ; data != dataEnd; ++data )
2834 pair< TEntry2Geom::iterator, bool > it_new =
2835 newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
2836 bool processedGroup = !it_new.second;
2837 TopoDS_Shape& newShape = it_new.first->second;
2838 if ( !processedGroup )
2839 newShape = newGroupShape( *data, ONLY_IF_CHANGED );
2840 if ( newShape.IsNull() )
2841 continue; // no changes
2844 _preMeshInfo->ForgetOrLoad();
2846 if ( processedGroup ) { // update group indices
2847 list<TGeomGroupData>::iterator data2 = data;
2848 for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
2849 data->_indices = data2->_indices;
2852 // Update SMESH objects according to new GEOM group contents
2854 SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2855 if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2857 int oldID = submesh->GetId();
2858 if ( !_mapSubMeshIor.count( oldID ))
2860 TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2862 // update hypotheses
2863 list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2864 list <const SMESHDS_Hypothesis * >::iterator hypIt;
2865 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2867 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2868 _impl->AddHypothesis ( newShape, (*hypIt)->GetID());
2870 // care of submeshes
2871 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2872 int newID = newSubmesh->GetId();
2873 if ( newID != oldID ) {
2874 _mapSubMesh [ newID ] = newSubmesh;
2875 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2876 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2877 _mapSubMesh. erase(oldID);
2878 _mapSubMesh_i. erase(oldID);
2879 _mapSubMeshIor.erase(oldID);
2880 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2885 SMESH::SMESH_GroupOnGeom_var smeshGroup =
2886 SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2887 if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2889 SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2891 ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2892 SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2893 ds->SetShape( newShape );
2898 SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2899 if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2901 // Remove groups and submeshes basing on removed sub-shapes
2903 TopTools_MapOfShape newShapeMap;
2904 TopoDS_Iterator shapeIt( newShape );
2905 for ( ; shapeIt.More(); shapeIt.Next() )
2906 newShapeMap.Add( shapeIt.Value() );
2908 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2909 for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2911 if ( newShapeMap.Contains( shapeIt.Value() ))
2913 TopTools_IndexedMapOfShape oldShapeMap;
2914 TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2915 for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2917 const TopoDS_Shape& oldShape = oldShapeMap(i);
2918 int oldInd = meshDS->ShapeToIndex( oldShape );
2920 map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2921 if ( i_smIor != _mapSubMeshIor.end() ) {
2922 RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2925 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2926 for ( ; i_grp != _mapGroups.end(); ++i_grp )
2928 // check if a group bases on oldInd shape
2929 SMESHDS_GroupOnGeom* grpOnGeom = 0;
2930 if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2931 grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2932 if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2934 RemoveGroup( i_grp->second ); // several groups can base on same shape
2935 i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2940 // Reassign hypotheses and update groups after setting the new shape to mesh
2942 // collect anassigned hypotheses
2943 typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2944 list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2945 TShapeHypList assignedHyps;
2946 for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2948 const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2949 list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2950 if ( !hyps.empty() ) {
2951 assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2952 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2953 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2956 // collect shapes supporting groups
2957 typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2958 TShapeTypeList groupData;
2959 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2960 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2961 for ( ; grIt != groups.end(); ++grIt )
2963 if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2965 ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2967 // set new shape to mesh -> DS of sub-meshes and geom groups is deleted
2969 _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
2970 _impl->ShapeToMesh( newShape );
2972 // reassign hypotheses
2973 TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2974 for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2976 TIndexedShape& geom = indS_hyps->first;
2977 list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2978 int oldID = geom._index;
2979 int newID = meshDS->ShapeToIndex( geom._shape );
2980 if ( oldID == 1 ) { // main shape
2982 geom._shape = newShape;
2986 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2987 _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2988 // care of sub-meshes
2989 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2990 if ( newID != oldID ) {
2991 _mapSubMesh [ newID ] = newSubmesh;
2992 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2993 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2994 _mapSubMesh. erase(oldID);
2995 _mapSubMesh_i. erase(oldID);
2996 _mapSubMeshIor.erase(oldID);
2997 _mapSubMesh_i [ newID ]->changeLocalId( newID );
3001 TShapeTypeList::iterator geomType = groupData.begin();
3002 for ( ; geomType != groupData.end(); ++geomType )
3004 const TIndexedShape& geom = geomType->first;
3005 int oldID = geom._index;
3006 if ( _mapGroups.find( oldID ) == _mapGroups.end() )
3009 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( _mapGroups[oldID] );
3010 CORBA::String_var name = groupSO->GetName();
3012 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID]))
3013 if ( SMESH_Group* group = _impl->AddGroup( geomType->second, name.in(),
3014 /*id=*/-1, geom._shape ))
3015 group_i->changeLocalId( group->GetID() );
3018 break; // everything has been updated
3021 } // loop on group data
3025 CORBA::Long newNbEntities = NbNodes() + NbElements();
3026 list< SALOMEDS::SObject_wrap > soToUpdateIcons;
3027 if ( newNbEntities != nbEntities )
3029 // Add all SObjects with icons to soToUpdateIcons
3030 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( _this() )); // mesh
3032 for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
3033 i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
3034 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_sm->second ));
3036 for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
3037 i_gr != _mapGroups.end(); ++i_gr ) // groups
3038 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_gr->second ));
3041 list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
3042 for ( ; so != soToUpdateIcons.end(); ++so )
3043 _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
3046 //=============================================================================
3048 * \brief Create standalone group from a group on geometry or filter
3050 //=============================================================================
3052 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
3053 throw (SALOME::SALOME_Exception)
3055 SMESH::SMESH_Group_var aGroup;
3060 _preMeshInfo->FullLoadFromFile();
3062 if ( theGroup->_is_nil() )
3063 return aGroup._retn();
3065 SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
3067 return aGroup._retn();
3069 const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
3071 const int anId = aGroupToRem->GetLocalID();
3072 if ( !_impl->ConvertToStandalone( anId ) )
3073 return aGroup._retn();
3074 removeGeomGroupData( theGroup );
3076 SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3078 // remove old instance of group from own map
3079 { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
3080 _mapGroups.erase( anId );
3082 SALOMEDS::StudyBuilder_var builder;
3083 SALOMEDS::SObject_wrap aGroupSO;
3084 SALOMEDS::Study_var aStudy = SMESH_Gen_i::getStudyServant();
3085 if ( !aStudy->_is_nil() ) {
3086 builder = aStudy->NewBuilder();
3087 aGroupSO = _gen_i->ObjectToSObject( theGroup );
3088 if ( !aGroupSO->_is_nil() )
3090 // remove reference to geometry
3091 SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
3092 for ( ; chItr->More(); chItr->Next() )
3094 // Remove group's child SObject
3095 SALOMEDS::SObject_wrap so = chItr->Value();
3096 builder->RemoveObject( so );
3098 // Update Python script
3099 TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
3100 << ".ConvertToStandalone( " << aGroupSO << " )";
3102 // change icon of Group on Filter
3105 // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
3106 // const int isEmpty = ( elemTypes->length() == 0 );
3109 SALOMEDS::GenericAttribute_wrap anAttr =
3110 builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
3111 SALOMEDS::AttributePixMap_wrap pm = anAttr;
3112 pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
3118 // remember new group in own map
3119 aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
3120 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3122 // register CORBA object for persistence
3123 _gen_i->RegisterObject( aGroup );
3125 CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
3126 builder->SetIOR( aGroupSO, ior.in() ); // == aGroup->Register();
3127 //aGroup->Register();
3128 aGroupToRem->UnRegister();
3130 SMESH_CATCH( SMESH::throwCorbaException );
3132 return aGroup._retn();
3135 //================================================================================
3137 * \brief Create a sub-mesh on a given sub-shape
3139 //================================================================================
3141 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
3143 if(MYDEBUG) MESSAGE( "createSubMesh" );
3144 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
3145 ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
3148 SMESH_subMesh_i * subMeshServant;
3151 subMeshId = mySubMesh->GetId();
3152 subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
3154 else // "invalid sub-mesh"
3156 // The invalid sub-mesh is created for the case where a valid sub-shape not found
3157 // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0.
3158 if ( _mapSubMesh.empty() )
3161 subMeshId = _mapSubMesh.begin()->first - 1;
3162 subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject);
3165 SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
3167 _mapSubMesh [subMeshId] = mySubMesh;
3168 _mapSubMesh_i [subMeshId] = subMeshServant;
3169 _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
3171 subMeshServant->Register();
3173 // register CORBA object for persistence
3174 int nextId = _gen_i->RegisterObject( subMesh );
3175 if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
3176 else { nextId = 0; } // avoid "unused variable" warning
3178 // to track changes of GEOM groups
3179 if ( subMeshId > 0 )
3180 addGeomGroupData( theSubShapeObject, subMesh );
3182 return subMesh._retn();
3185 //================================================================================
3187 * \brief Return an existing sub-mesh based on a sub-shape with the given ID
3189 //================================================================================
3191 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
3193 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
3194 if ( it == _mapSubMeshIor.end() )
3195 return SMESH::SMESH_subMesh::_nil();
3197 return SMESH::SMESH_subMesh::_duplicate( (*it).second );
3200 //================================================================================
3202 * \brief Remove a sub-mesh based on the given sub-shape
3204 //================================================================================
3206 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
3207 GEOM::GEOM_Object_ptr theSubShapeObject )
3209 bool isHypChanged = false;
3210 if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
3211 return isHypChanged;
3213 const int subMeshId = theSubMesh->GetId();
3215 if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
3218 if (( _mapSubMesh.count( subMeshId )) &&
3219 ( sm = _impl->GetSubMeshContaining( subMeshId )))
3221 TopoDS_Shape S = sm->GetSubShape();
3224 list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
3225 isHypChanged = !hyps.empty();
3226 if ( isHypChanged && _preMeshInfo )
3227 _preMeshInfo->ForgetOrLoad();
3228 list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
3229 for ( ; hyp != hyps.end(); ++hyp )
3230 _impl->RemoveHypothesis(S, (*hyp)->GetID());
3237 SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
3238 isHypChanged = ( aHypList->length() > 0 );
3239 for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
3240 removeHypothesis( theSubShapeObject, aHypList[i] );
3243 catch( const SALOME::SALOME_Exception& ) {
3244 INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
3246 removeGeomGroupData( theSubShapeObject );
3250 std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
3251 if ( id_smi != _mapSubMesh_i.end() )
3252 id_smi->second->UnRegister();
3254 // remove a CORBA object
3255 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
3256 if ( id_smptr != _mapSubMeshIor.end() )
3257 SMESH::SMESH_subMesh_var( id_smptr->second );
3259 _mapSubMesh.erase(subMeshId);
3260 _mapSubMesh_i.erase(subMeshId);
3261 _mapSubMeshIor.erase(subMeshId);
3263 return isHypChanged;
3266 //================================================================================
3268 * \brief Create a group. Group type depends on given arguments
3270 //================================================================================
3272 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
3273 const char* theName,
3275 const TopoDS_Shape& theShape,
3276 const SMESH_PredicatePtr& thePredicate )
3278 std::string newName;
3279 if ( !theName || !theName[0] )
3281 std::set< std::string > presentNames;
3282 std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
3283 for ( ; i_gr != _mapGroups.end(); ++i_gr )
3285 CORBA::String_var name = i_gr->second->GetName();
3286 presentNames.insert( name.in() );
3289 newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
3290 } while ( !presentNames.insert( newName ).second );
3291 theName = newName.c_str();
3293 SMESH::SMESH_GroupBase_var aGroup;
3294 if ( SMESH_Group* g = _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName,
3295 theID, theShape, thePredicate ))
3297 int anId = g->GetID();
3298 SMESH_GroupBase_i* aGroupImpl;
3299 if ( !theShape.IsNull() )
3300 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3301 else if ( thePredicate )
3302 aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
3304 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3306 aGroup = aGroupImpl->_this();
3307 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3308 aGroupImpl->Register();
3310 // register CORBA object for persistence
3311 int nextId = _gen_i->RegisterObject( aGroup );
3312 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
3313 else { nextId = ( nextId > 0 ); } // avoid "unused variable" warning in release mode
3315 // to track changes of GEOM groups
3316 if ( !theShape.IsNull() ) {
3317 GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
3318 addGeomGroupData( geom, aGroup );
3321 return aGroup._retn();
3324 //=============================================================================
3326 * SMESH_Mesh_i::removeGroup
3328 * Should be called by ~SMESH_Group_i()
3330 //=============================================================================
3332 void SMESH_Mesh_i::removeGroup( const int theId )
3334 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
3335 if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
3336 SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
3337 _mapGroups.erase( theId );
3338 removeGeomGroupData( group );
3339 if ( !_impl->RemoveGroup( theId ))
3341 // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
3342 RemoveGroup( group );
3344 group->UnRegister();
3348 //================================================================================
3350 * \brief Return a log that can be used to move another mesh to the same state as this one
3352 //================================================================================
3354 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
3355 throw(SALOME::SALOME_Exception)
3357 SMESH::log_array_var aLog;
3361 _preMeshInfo->FullLoadFromFile();
3363 list < SMESHDS_Command * >logDS = _impl->GetLog();
3364 aLog = new SMESH::log_array;
3366 int lg = logDS.size();
3368 list < SMESHDS_Command * >::iterator its = logDS.begin();
3369 while(its != logDS.end()){
3370 SMESHDS_Command *com = *its;
3371 int comType = com->GetType();
3372 int lgcom = com->GetNumber();
3373 const list < int >&intList = com->GetIndexes();
3374 int inum = intList.size();
3375 list < int >::const_iterator ii = intList.begin();
3376 const list < double >&coordList = com->GetCoords();
3377 int rnum = coordList.size();
3378 list < double >::const_iterator ir = coordList.begin();
3379 aLog[indexLog].commandType = comType;
3380 aLog[indexLog].number = lgcom;
3381 aLog[indexLog].coords.length(rnum);
3382 aLog[indexLog].indexes.length(inum);
3383 for(int i = 0; i < rnum; i++){
3384 aLog[indexLog].coords[i] = *ir;
3387 for(int i = 0; i < inum; i++){
3388 aLog[indexLog].indexes[i] = *ii;
3397 SMESH_CATCH( SMESH::throwCorbaException );
3399 return aLog._retn();
3402 //================================================================================
3404 * \brief Remove the log of commands
3406 //================================================================================
3408 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
3412 SMESH_CATCH( SMESH::throwCorbaException );
3415 //================================================================================
3417 * \brief Return a mesh ID
3419 //================================================================================
3421 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
3426 //=============================================================================
3429 //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
3430 // issue 0020918: groups removal is caused by hyp modification
3431 // issue 0021208: to forget not loaded mesh data at hyp modification
3432 struct TCallUp_i : public SMESH_Mesh::TCallUp
3434 SMESH_Mesh_i* _mesh;
3435 TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
3436 virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
3437 virtual void HypothesisModified( int hypID,
3438 bool updIcons) { _mesh->onHypothesisModified( hypID,
3440 virtual void Load () { _mesh->Load(); }
3441 virtual bool IsLoaded() { return _mesh->IsLoaded(); }
3445 //================================================================================
3447 * \brief callback from _impl to
3448 * 1) forget not loaded mesh data (issue 0021208)
3449 * 2) mark hypothesis as valid
3451 //================================================================================
3453 void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons)
3456 _preMeshInfo->ForgetOrLoad();
3458 if ( theUpdateIcons )
3460 SMESH::SMESH_Mesh_var mesh = _this();
3461 _gen_i->UpdateIcons( mesh );
3464 if ( _nbInvalidHypos != 0 )
3466 // mark a hypothesis as valid after edition
3468 SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
3469 SALOMEDS::SObject_wrap hypRoot;
3470 if ( !smeshComp->_is_nil() &&
3471 smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
3473 SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
3474 for ( ; anIter->More(); anIter->Next() )
3476 SALOMEDS::SObject_wrap hypSO = anIter->Value();
3477 CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO );
3478 SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
3479 if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
3480 _gen_i->HighLightInvalid( hyp, false );
3482 nbInvalid += _gen_i->IsInvalid( hypSO );
3485 _nbInvalidHypos = nbInvalid;
3489 //================================================================================
3491 * \brief Set mesh implementation
3493 //================================================================================
3495 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
3497 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
3500 _impl->SetCallUp( new TCallUp_i(this));
3503 //=============================================================================
3505 * Return a mesh implementation
3507 //=============================================================================
3509 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
3511 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
3515 //=============================================================================
3517 * Return mesh editor
3519 //=============================================================================
3521 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
3522 throw (SALOME::SALOME_Exception)
3524 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3528 _preMeshInfo->FullLoadFromFile();
3530 // Create MeshEditor
3532 _editor = new SMESH_MeshEditor_i( this, false );
3533 aMeshEdVar = _editor->_this();
3535 // Update Python script
3536 TPythonDump() << _editor << " = "
3537 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
3539 SMESH_CATCH( SMESH::throwCorbaException );
3541 return aMeshEdVar._retn();
3544 //=============================================================================
3546 * Return mesh edition previewer
3548 //=============================================================================
3550 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
3551 throw (SALOME::SALOME_Exception)
3553 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3557 _preMeshInfo->FullLoadFromFile();
3559 if ( !_previewEditor )
3560 _previewEditor = new SMESH_MeshEditor_i( this, true );
3561 aMeshEdVar = _previewEditor->_this();
3563 SMESH_CATCH( SMESH::throwCorbaException );
3565 return aMeshEdVar._retn();
3568 //================================================================================
3570 * \brief Return true if the mesh has been edited since a last total re-compute
3571 * and those modifications may prevent successful partial re-compute
3573 //================================================================================
3575 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
3577 Unexpect aCatch(SALOME_SalomeException);
3578 return _impl->HasModificationsToDiscard();
3581 //================================================================================
3583 * \brief Return a random unique color
3585 //================================================================================
3587 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
3589 const int MAX_ATTEMPTS = 100;
3591 double tolerance = 0.5;
3592 SALOMEDS::Color col;
3596 // generate random color
3597 double red = (double)rand() / RAND_MAX;
3598 double green = (double)rand() / RAND_MAX;
3599 double blue = (double)rand() / RAND_MAX;
3600 // check existence in the list of the existing colors
3601 bool matched = false;
3602 std::list<SALOMEDS::Color>::const_iterator it;
3603 for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
3604 SALOMEDS::Color color = *it;
3605 double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B - blue );
3606 matched = tol < tolerance;
3608 if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
3609 ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
3617 //=============================================================================
3619 * Set auto-color mode. If it is on, groups get unique random colors
3621 //=============================================================================
3623 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
3625 Unexpect aCatch(SALOME_SalomeException);
3626 _impl->SetAutoColor(theAutoColor);
3628 TPythonDump pyDump; // not to dump group->SetColor() from below code
3629 pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
3631 std::list<SALOMEDS::Color> aReservedColors;
3632 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
3633 for ( ; it != _mapGroups.end(); it++ ) {
3634 if ( CORBA::is_nil( it->second )) continue;
3635 SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
3636 it->second->SetColor( aColor );
3637 aReservedColors.push_back( aColor );
3641 //=============================================================================
3643 * Return true if auto-color mode is on
3645 //=============================================================================
3647 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
3649 Unexpect aCatch(SALOME_SalomeException);
3650 return _impl->GetAutoColor();
3653 //=============================================================================
3655 * Check if there are groups with equal names
3657 //=============================================================================
3659 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
3661 return _impl->HasDuplicatedGroupNamesMED();
3664 //================================================================================
3666 * \brief Care of a file before exporting mesh into it
3668 //================================================================================
3670 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
3672 SMESH_File aFile( file, false );
3674 if ( aFile.exists() ) {
3675 // existing filesystem node
3676 if ( !aFile.isDirectory() ) {
3677 if ( aFile.openForWriting() ) {
3678 if ( overwrite && ! aFile.remove()) {
3679 msg << "Can't replace " << aFile.getName();
3682 msg << "Can't write into " << aFile.getName();
3685 msg << "Location " << aFile.getName() << " is not a file";
3689 // nonexisting file; check if it can be created
3690 if ( !aFile.openForWriting() ) {
3691 msg << "You cannot create the file "
3693 << ". Check the directory existence and access rights";
3701 THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
3705 //================================================================================
3707 * \brief Prepare a file for export and pass names of mesh groups from study to mesh DS
3708 * \param file - file name
3709 * \param overwrite - to erase the file or not
3710 * \retval string - mesh name
3712 //================================================================================
3714 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char* file,
3715 CORBA::Boolean overwrite)
3718 PrepareForWriting(file, overwrite);
3719 string aMeshName = "Mesh";
3720 SALOMEDS::Study_var aStudy = SMESH_Gen_i::getStudyServant();
3721 if ( !aStudy->_is_nil() ) {
3722 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3723 if ( !aMeshSO->_is_nil() ) {
3724 CORBA::String_var name = aMeshSO->GetName();
3726 // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
3727 if ( !aStudy->GetProperties()->IsLocked() )
3729 SALOMEDS::GenericAttribute_wrap anAttr;
3730 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3731 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
3732 SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
3733 ASSERT(!aFileName->_is_nil());
3734 aFileName->SetValue(file);
3735 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
3736 SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
3737 ASSERT(!aFileType->_is_nil());
3738 aFileType->SetValue("FICHIERMED");
3742 // Update Python script
3743 // set name of mesh before export
3744 TPythonDump() << _gen_i << ".SetName("
3745 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
3747 // check names of groups
3753 //================================================================================
3755 * \brief Export to MED file
3757 //================================================================================
3759 void SMESH_Mesh_i::ExportMED(const char* file,
3760 CORBA::Boolean auto_groups,
3761 CORBA::Long version,
3762 CORBA::Boolean overwrite,
3763 CORBA::Boolean autoDimension)
3764 throw(SALOME::SALOME_Exception)
3766 //MESSAGE("MED minor version: "<< minor);
3769 _preMeshInfo->FullLoadFromFile();
3771 string aMeshName = prepareMeshNameAndGroups(file, overwrite);
3772 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, 0, autoDimension );
3774 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportMED( r'"
3776 << "auto_groups=" <<auto_groups << ", "
3777 << "minor=" << version << ", "
3778 << "overwrite=" << overwrite << ", "
3779 << "meshPart=None, "
3780 << "autoDimension=" << autoDimension << " )";
3782 SMESH_CATCH( SMESH::throwCorbaException );
3785 //================================================================================
3787 * \brief Export a mesh to a SAUV file
3789 //================================================================================
3791 void SMESH_Mesh_i::ExportSAUV (const char* file,
3792 CORBA::Boolean auto_groups)
3793 throw(SALOME::SALOME_Exception)
3795 Unexpect aCatch(SALOME_SalomeException);
3797 _preMeshInfo->FullLoadFromFile();
3799 string aMeshName = prepareMeshNameAndGroups(file, true);
3800 TPythonDump() << SMESH::SMESH_Mesh_var( _this())
3801 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
3802 _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
3806 //================================================================================
3808 * \brief Export a mesh to a DAT file
3810 //================================================================================
3812 void SMESH_Mesh_i::ExportDAT (const char *file)
3813 throw(SALOME::SALOME_Exception)
3815 Unexpect aCatch(SALOME_SalomeException);
3817 _preMeshInfo->FullLoadFromFile();
3819 // Update Python script
3820 // check names of groups
3822 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
3825 PrepareForWriting(file);
3826 _impl->ExportDAT(file);
3829 //================================================================================
3831 * \brief Export a mesh to an UNV file
3833 //================================================================================
3835 void SMESH_Mesh_i::ExportUNV (const char *file)
3836 throw(SALOME::SALOME_Exception)
3838 Unexpect aCatch(SALOME_SalomeException);
3840 _preMeshInfo->FullLoadFromFile();
3842 // Update Python script
3843 // check names of groups
3845 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
3848 PrepareForWriting(file);
3849 _impl->ExportUNV(file);
3852 //================================================================================
3854 * \brief Export a mesh to an STL file
3856 //================================================================================
3858 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3859 throw(SALOME::SALOME_Exception)
3861 Unexpect aCatch(SALOME_SalomeException);
3863 _preMeshInfo->FullLoadFromFile();
3865 // Update Python script
3866 // check names of groups
3868 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3869 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3871 CORBA::String_var name;
3872 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( _this() );
3873 if ( !so->_is_nil() )
3874 name = so->GetName();
3877 PrepareForWriting( file );
3878 _impl->ExportSTL( file, isascii, name.in() );
3881 //================================================================================
3883 * \brief Export a part of mesh to a med file
3885 //================================================================================
3887 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
3889 CORBA::Boolean auto_groups,
3890 CORBA::Long version,
3891 CORBA::Boolean overwrite,
3892 CORBA::Boolean autoDimension,
3893 const GEOM::ListOfFields& fields,
3894 const char* geomAssocFields,
3895 CORBA::Double ZTolerance)
3896 throw (SALOME::SALOME_Exception)
3898 MESSAGE("MED version: "<< version);
3901 _preMeshInfo->FullLoadFromFile();
3904 bool have0dField = false;
3905 if ( fields.length() > 0 )
3907 GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3908 if ( shapeToMesh->_is_nil() )
3909 THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3911 for ( size_t i = 0; i < fields.length(); ++i )
3913 if ( fields[i]->GetDataType() == GEOM::FDT_String )
3914 THROW_SALOME_CORBA_EXCEPTION
3915 ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3916 GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3917 if ( fieldShape->_is_nil() )
3918 THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3919 if ( !fieldShape->IsSame( shapeToMesh ) )
3920 THROW_SALOME_CORBA_EXCEPTION
3921 ( "Field defined not on shape", SALOME::BAD_PARAM);
3922 if ( fields[i]->GetDimension() == 0 )
3925 if ( geomAssocFields )
3926 for ( int i = 0; geomAssocFields[i]; ++i )
3927 switch ( geomAssocFields[i] ) {
3928 case 'v':case 'e':case 'f':case 's': break;
3929 case 'V':case 'E':case 'F':case 'S': break;
3930 default: THROW_SALOME_CORBA_EXCEPTION
3931 ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3935 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3939 string aMeshName = "Mesh";
3940 SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3941 if ( CORBA::is_nil( meshPart ) ||
3942 SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3944 aMeshName = prepareMeshNameAndGroups(file, overwrite);
3945 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3946 0, autoDimension, /*addODOnVertices=*/have0dField,
3948 meshDS = _impl->GetMeshDS();
3953 _preMeshInfo->FullLoadFromFile();
3955 PrepareForWriting(file, overwrite);
3957 SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( meshPart );
3958 if ( !SO->_is_nil() ) {
3959 CORBA::String_var name = SO->GetName();
3963 SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
3964 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3965 partDS, autoDimension, /*addODOnVertices=*/have0dField, ZTolerance);
3966 meshDS = tmpDSDeleter._obj = partDS;
3971 if ( _impl->HasShapeToMesh() )
3973 DriverMED_W_Field fieldWriter;
3974 fieldWriter.SetFile( file );
3975 fieldWriter.SetMeshName( aMeshName );
3976 fieldWriter.AddODOnVertices( have0dField );
3978 exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3982 GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
3983 goList->length( fields.length() );
3984 for ( size_t i = 0; i < fields.length(); ++i )
3986 GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
3989 TPythonDump() << _this() << ".ExportPartToMED( "
3990 << meshPart << ", r'"
3992 << auto_groups << ", "
3994 << overwrite << ", "
3995 << autoDimension << ", "
3997 << ( geomAssocFields ? geomAssocFields : "" ) << "',"
3998 << TVar( ZTolerance )
4001 SMESH_CATCH( SMESH::throwCorbaException );
4004 //================================================================================
4006 * Write GEOM fields to MED file
4008 //================================================================================
4010 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field& fieldWriter,
4011 SMESHDS_Mesh* meshDS,
4012 const GEOM::ListOfFields& fields,
4013 const char* geomAssocFields)
4015 #define METH "SMESH_Mesh_i::exportMEDFields() "
4017 if (( fields.length() < 1 ) &&
4018 ( !geomAssocFields || !geomAssocFields[0] ))
4021 std::vector< std::vector< double > > dblVals;
4022 std::vector< std::vector< int > > intVals;
4023 std::vector< int > subIdsByDim[ 4 ];
4024 const double noneDblValue = 0.;
4025 const double noneIntValue = 0;
4027 for ( size_t iF = 0; iF < fields.length(); ++iF )
4031 int dim = fields[ iF ]->GetDimension();
4032 SMDSAbs_ElementType elemType;
4033 TopAbs_ShapeEnum shapeType;
4035 case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
4036 case 1: elemType = SMDSAbs_Edge; shapeType = TopAbs_EDGE; break;
4037 case 2: elemType = SMDSAbs_Face; shapeType = TopAbs_FACE; break;
4038 case 3: elemType = SMDSAbs_Volume; shapeType = TopAbs_SOLID; break;
4040 continue; // skip fields on whole shape
4042 GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
4043 if ( dataType == GEOM::FDT_String )
4045 GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
4046 if ( stepIDs->length() < 1 )
4048 GEOM::string_array_var comps = fields[ iF ]->GetComponents();
4049 if ( comps->length() < 1 )
4051 CORBA::String_var name = fields[ iF ]->GetName();
4053 if ( !fieldWriter.Set( meshDS,
4057 /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
4060 for ( size_t iC = 0; iC < comps->length(); ++iC )
4061 fieldWriter.SetCompName( iC, comps[ iC ].in() );
4063 dblVals.resize( comps->length() );
4064 intVals.resize( comps->length() );
4066 // find sub-shape IDs
4068 std::vector< int >& subIds = subIdsByDim[ dim ];
4069 if ( subIds.empty() )
4070 for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
4071 if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
4072 subIds.push_back( id );
4076 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4080 for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
4082 GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
4083 if ( step->_is_nil() )
4086 CORBA::Long stamp = step->GetStamp();
4087 CORBA::Long id = step->GetID();
4088 fieldWriter.SetDtIt( int( stamp ), int( id ));
4090 // fill dblVals or intVals
4091 for ( size_t iC = 0; iC < comps->length(); ++iC )
4092 if ( dataType == GEOM::FDT_Double )
4094 dblVals[ iC ].clear();
4095 dblVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4099 intVals[ iC ].clear();
4100 intVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4104 case GEOM::FDT_Double:
4106 GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
4107 if ( dblStep->_is_nil() ) continue;
4108 GEOM::ListOfDouble_var vv = dblStep->GetValues();
4109 if ( vv->length() != subIds.size() * comps->length() )
4110 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4111 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4112 for ( size_t iC = 0; iC < comps->length(); ++iC )
4113 dblVals[ iC ][ subIds[ iS ]] = vv[ iV++ ];
4118 GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
4119 if ( intStep->_is_nil() ) continue;
4120 GEOM::ListOfLong_var vv = intStep->GetValues();
4121 if ( vv->length() != subIds.size() * comps->length() )
4122 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4123 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4124 for ( size_t iC = 0; iC < comps->length(); ++iC )
4125 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4128 case GEOM::FDT_Bool:
4130 GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
4131 if ( boolStep->_is_nil() ) continue;
4132 GEOM::short_array_var vv = boolStep->GetValues();
4133 if ( vv->length() != subIds.size() * comps->length() )
4134 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4135 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4136 for ( size_t iC = 0; iC < comps->length(); ++iC )
4137 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4143 // pass values to fieldWriter
4144 elemIt = fieldWriter.GetOrderedElems();
4145 if ( dataType == GEOM::FDT_Double )
4146 while ( elemIt->more() )
4148 const SMDS_MeshElement* e = elemIt->next();
4149 const int shapeID = e->getshapeId();
4150 if ( shapeID < 1 || shapeID >= (int) dblVals[0].size() )
4151 for ( size_t iC = 0; iC < comps->length(); ++iC )
4152 fieldWriter.AddValue( noneDblValue );
4154 for ( size_t iC = 0; iC < comps->length(); ++iC )
4155 fieldWriter.AddValue( dblVals[ iC ][ shapeID ]);
4158 while ( elemIt->more() )
4160 const SMDS_MeshElement* e = elemIt->next();
4161 const int shapeID = e->getshapeId();
4162 if ( shapeID < 1 || shapeID >= (int) intVals[0].size() )
4163 for ( size_t iC = 0; iC < comps->length(); ++iC )
4164 fieldWriter.AddValue( (double) noneIntValue );
4166 for ( size_t iC = 0; iC < comps->length(); ++iC )
4167 fieldWriter.AddValue( (double) intVals[ iC ][ shapeID ]);
4171 fieldWriter.Perform();
4172 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4173 if ( res && res->IsKO() )
4175 if ( res->myComment.empty() )
4176 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4178 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4184 if ( !geomAssocFields || !geomAssocFields[0] )
4187 // write geomAssocFields
4189 std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
4190 shapeDim[ TopAbs_COMPOUND ] = 3;
4191 shapeDim[ TopAbs_COMPSOLID ] = 3;
4192 shapeDim[ TopAbs_SOLID ] = 3;
4193 shapeDim[ TopAbs_SHELL ] = 2;
4194 shapeDim[ TopAbs_FACE ] = 2;
4195 shapeDim[ TopAbs_WIRE ] = 1;
4196 shapeDim[ TopAbs_EDGE ] = 1;
4197 shapeDim[ TopAbs_VERTEX ] = 0;
4198 shapeDim[ TopAbs_SHAPE ] = 3;
4200 for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
4202 std::vector< std::string > compNames;
4203 switch ( geomAssocFields[ iF ]) {
4205 fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
4206 compNames.push_back( "dim" );
4209 fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
4212 fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
4215 fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
4219 compNames.push_back( "id" );
4220 for ( size_t iC = 0; iC < compNames.size(); ++iC )
4221 fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
4223 fieldWriter.SetDtIt( -1, -1 );
4225 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4229 if ( compNames.size() == 2 ) // _vertices_
4230 while ( elemIt->more() )
4232 const SMDS_MeshElement* e = elemIt->next();
4233 const int shapeID = e->getshapeId();
4236 fieldWriter.AddValue( (double) -1 );
4237 fieldWriter.AddValue( (double) -1 );
4241 const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
4242 fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
4243 fieldWriter.AddValue( (double) shapeID );
4247 while ( elemIt->more() )
4249 const SMDS_MeshElement* e = elemIt->next();
4250 const int shapeID = e->getshapeId();
4252 fieldWriter.AddValue( (double) -1 );
4254 fieldWriter.AddValue( (double) shapeID );
4258 fieldWriter.Perform();
4259 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4260 if ( res && res->IsKO() )
4262 if ( res->myComment.empty() )
4263 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4265 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4268 } // loop on geomAssocFields
4273 //================================================================================
4275 * \brief Export a part of mesh to a DAT file
4277 //================================================================================
4279 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
4281 throw (SALOME::SALOME_Exception)
4283 Unexpect aCatch(SALOME_SalomeException);
4285 _preMeshInfo->FullLoadFromFile();
4287 PrepareForWriting(file);
4289 SMESH_MeshPartDS partDS( meshPart );
4290 _impl->ExportDAT(file,&partDS);
4292 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4293 << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
4295 //================================================================================
4297 * \brief Export a part of mesh to an UNV file
4299 //================================================================================
4301 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
4303 throw (SALOME::SALOME_Exception)
4305 Unexpect aCatch(SALOME_SalomeException);
4307 _preMeshInfo->FullLoadFromFile();
4309 PrepareForWriting(file);
4311 SMESH_MeshPartDS partDS( meshPart );
4312 _impl->ExportUNV(file, &partDS);
4314 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4315 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
4317 //================================================================================
4319 * \brief Export a part of mesh to an STL file
4321 //================================================================================
4323 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
4325 ::CORBA::Boolean isascii)
4326 throw (SALOME::SALOME_Exception)
4328 Unexpect aCatch(SALOME_SalomeException);
4330 _preMeshInfo->FullLoadFromFile();
4332 PrepareForWriting(file);
4334 CORBA::String_var name;
4335 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4336 if ( !so->_is_nil() )
4337 name = so->GetName();
4339 SMESH_MeshPartDS partDS( meshPart );
4340 _impl->ExportSTL( file, isascii, name.in(), &partDS );
4342 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
4343 << meshPart<< ", r'" << file << "', " << isascii << ")";
4346 //================================================================================
4348 * \brief Export a part of mesh to an STL file
4350 //================================================================================
4352 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
4354 CORBA::Boolean overwrite,
4355 CORBA::Boolean groupElemsByType)
4356 throw (SALOME::SALOME_Exception)
4359 Unexpect aCatch(SALOME_SalomeException);
4361 _preMeshInfo->FullLoadFromFile();
4363 PrepareForWriting(file,overwrite);
4365 std::string meshName("");
4366 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4367 if ( !so->_is_nil() )
4369 CORBA::String_var name = so->GetName();
4370 meshName = name.in();
4374 SMESH_MeshPartDS partDS( meshPart );
4375 _impl->ExportCGNS(file, &partDS, meshName.c_str(), groupElemsByType );
4377 SMESH_CATCH( SMESH::throwCorbaException );
4379 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
4380 << meshPart<< ", r'" << file << "', " << overwrite << ")";
4382 THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
4386 //================================================================================
4388 * \brief Export a part of mesh to a GMF file
4390 //================================================================================
4392 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
4394 bool withRequiredGroups)
4395 throw (SALOME::SALOME_Exception)
4397 Unexpect aCatch(SALOME_SalomeException);
4399 _preMeshInfo->FullLoadFromFile();
4401 PrepareForWriting(file,/*overwrite=*/true);
4403 SMESH_MeshPartDS partDS( meshPart );
4404 _impl->ExportGMF(file, &partDS, withRequiredGroups);
4406 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
4407 << meshPart<< ", r'"
4409 << withRequiredGroups << ")";
4412 //=============================================================================
4414 * Return computation progress [0.,1]
4416 //=============================================================================
4418 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
4422 return _impl->GetComputeProgress();
4424 SMESH_CATCH( SMESH::doNothing );
4428 //================================================================================
4430 * \brief Return nb of nodes
4432 //================================================================================
4434 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
4436 Unexpect aCatch(SALOME_SalomeException);
4438 return _preMeshInfo->NbNodes();
4440 return _impl->NbNodes();
4443 //================================================================================
4445 * \brief Return nb of elements
4447 //================================================================================
4449 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
4451 Unexpect aCatch(SALOME_SalomeException);
4453 return _preMeshInfo->NbElements();
4455 return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
4458 //================================================================================
4460 * \brief Return nb of 0D elements
4462 //================================================================================
4464 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
4466 Unexpect aCatch(SALOME_SalomeException);
4468 return _preMeshInfo->Nb0DElements();
4470 return _impl->Nb0DElements();
4473 //================================================================================
4475 * \brief Return nb of BALL elements
4477 //================================================================================
4479 CORBA::Long SMESH_Mesh_i::NbBalls() throw (SALOME::SALOME_Exception)
4481 Unexpect aCatch(SALOME_SalomeException);
4483 return _preMeshInfo->NbBalls();
4485 return _impl->NbBalls();
4488 //================================================================================
4490 * \brief Return nb of 1D elements
4492 //================================================================================
4494 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
4496 Unexpect aCatch(SALOME_SalomeException);
4498 return _preMeshInfo->NbEdges();
4500 return _impl->NbEdges();
4503 //================================================================================
4505 * \brief Return nb of edges
4507 //================================================================================
4509 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
4510 throw(SALOME::SALOME_Exception)
4512 Unexpect aCatch(SALOME_SalomeException);
4514 return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
4516 return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
4519 //================================================================================
4521 * \brief Return nb of faces
4523 //================================================================================
4525 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
4527 Unexpect aCatch(SALOME_SalomeException);
4529 return _preMeshInfo->NbFaces();
4531 return _impl->NbFaces();
4534 //================================================================================
4536 * \brief Return nb of tringles
4538 //================================================================================
4540 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
4542 Unexpect aCatch(SALOME_SalomeException);
4544 return _preMeshInfo->NbTriangles();
4546 return _impl->NbTriangles();
4549 //================================================================================
4551 * \brief Return nb of bi-quadratic triangles
4553 //================================================================================
4555 CORBA::Long SMESH_Mesh_i::NbBiQuadTriangles()throw(SALOME::SALOME_Exception)
4557 Unexpect aCatch(SALOME_SalomeException);
4559 return _preMeshInfo->NbBiQuadTriangles();
4561 return _impl->NbBiQuadTriangles();
4564 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
4566 Unexpect aCatch(SALOME_SalomeException);
4568 return _preMeshInfo->NbQuadrangles();
4570 return _impl->NbQuadrangles();
4573 CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
4575 Unexpect aCatch(SALOME_SalomeException);
4577 return _preMeshInfo->NbBiQuadQuadrangles();
4579 return _impl->NbBiQuadQuadrangles();
4582 CORBA::Long SMESH_Mesh_i::NbPolygons() throw(SALOME::SALOME_Exception)
4584 Unexpect aCatch(SALOME_SalomeException);
4586 return _preMeshInfo->NbPolygons();
4588 return _impl->NbPolygons();
4591 CORBA::Long SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order) throw(SALOME::SALOME_Exception)
4593 Unexpect aCatch(SALOME_SalomeException);
4595 return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
4597 return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
4600 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
4601 throw(SALOME::SALOME_Exception)
4603 Unexpect aCatch(SALOME_SalomeException);
4605 return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
4607 return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
4610 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
4611 throw(SALOME::SALOME_Exception)
4613 Unexpect aCatch(SALOME_SalomeException);
4615 return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
4617 return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
4620 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
4621 throw(SALOME::SALOME_Exception)
4623 Unexpect aCatch(SALOME_SalomeException);
4625 return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
4627 return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
4630 //=============================================================================
4632 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
4634 Unexpect aCatch(SALOME_SalomeException);
4636 return _preMeshInfo->NbVolumes();
4638 return _impl->NbVolumes();
4641 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
4643 Unexpect aCatch(SALOME_SalomeException);
4645 return _preMeshInfo->NbTetras();
4647 return _impl->NbTetras();
4650 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
4652 Unexpect aCatch(SALOME_SalomeException);
4654 return _preMeshInfo->NbHexas();
4656 return _impl->NbHexas();
4659 CORBA::Long SMESH_Mesh_i::NbTriQuadraticHexas()throw(SALOME::SALOME_Exception)
4661 Unexpect aCatch(SALOME_SalomeException);
4663 return _preMeshInfo->NbTriQuadHexas();
4665 return _impl->NbTriQuadraticHexas();
4668 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
4670 Unexpect aCatch(SALOME_SalomeException);
4672 return _preMeshInfo->NbPyramids();
4674 return _impl->NbPyramids();
4677 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
4679 Unexpect aCatch(SALOME_SalomeException);
4681 return _preMeshInfo->NbPrisms();
4683 return _impl->NbPrisms();
4686 CORBA::Long SMESH_Mesh_i::NbHexagonalPrisms()throw(SALOME::SALOME_Exception)
4688 Unexpect aCatch(SALOME_SalomeException);
4690 return _preMeshInfo->NbHexPrisms();
4692 return _impl->NbHexagonalPrisms();
4695 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
4697 Unexpect aCatch(SALOME_SalomeException);
4699 return _preMeshInfo->NbPolyhedrons();
4701 return _impl->NbPolyhedrons();
4704 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
4705 throw(SALOME::SALOME_Exception)
4707 Unexpect aCatch(SALOME_SalomeException);
4709 return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
4711 return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
4714 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
4715 throw(SALOME::SALOME_Exception)
4717 Unexpect aCatch(SALOME_SalomeException);
4719 return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
4721 return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
4724 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
4725 throw(SALOME::SALOME_Exception)
4727 Unexpect aCatch(SALOME_SalomeException);
4729 return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
4731 return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
4734 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
4735 throw(SALOME::SALOME_Exception)
4737 Unexpect aCatch(SALOME_SalomeException);
4739 return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
4741 return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
4744 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
4745 throw(SALOME::SALOME_Exception)
4747 Unexpect aCatch(SALOME_SalomeException);
4749 return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
4751 return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
4754 //=============================================================================
4756 * Return nb of published sub-meshes
4758 //=============================================================================
4760 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
4762 Unexpect aCatch(SALOME_SalomeException);
4763 return _mapSubMesh_i.size();
4766 //=============================================================================
4768 * Dumps mesh into a string
4770 //=============================================================================
4772 char* SMESH_Mesh_i::Dump()
4776 return CORBA::string_dup( os.str().c_str() );
4779 //=============================================================================
4781 * Method of SMESH_IDSource interface
4783 //=============================================================================
4785 SMESH::long_array* SMESH_Mesh_i::GetIDs()
4787 return GetElementsId();
4790 //=============================================================================
4792 * Return ids of all elements
4794 //=============================================================================
4796 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
4797 throw (SALOME::SALOME_Exception)
4799 Unexpect aCatch(SALOME_SalomeException);
4801 _preMeshInfo->FullLoadFromFile();
4803 SMESH::long_array_var aResult = new SMESH::long_array();
4804 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4806 if ( aSMESHDS_Mesh == NULL )
4807 return aResult._retn();
4809 long nbElements = NbElements();
4810 aResult->length( nbElements );
4811 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
4812 for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
4813 aResult[i] = anIt->next()->GetID();
4815 return aResult._retn();
4819 //=============================================================================
4821 * Return ids of all elements of given type
4823 //=============================================================================
4825 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
4826 throw (SALOME::SALOME_Exception)
4828 Unexpect aCatch(SALOME_SalomeException);
4830 _preMeshInfo->FullLoadFromFile();
4832 SMESH::long_array_var aResult = new SMESH::long_array();
4833 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4835 if ( aSMESHDS_Mesh == NULL )
4836 return aResult._retn();
4838 long nbElements = NbElements();
4840 // No sense in returning ids of elements along with ids of nodes:
4841 // when theElemType == SMESH::ALL, return node ids only if
4842 // there are no elements
4843 if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
4844 return GetNodesId();
4846 aResult->length( nbElements );
4850 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
4851 while ( i < nbElements && anIt->more() )
4852 aResult[i++] = anIt->next()->GetID();
4854 aResult->length( i );
4856 return aResult._retn();
4859 //=============================================================================
4861 * Return ids of all nodes
4863 //=============================================================================
4865 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
4866 throw (SALOME::SALOME_Exception)
4868 Unexpect aCatch(SALOME_SalomeException);
4870 _preMeshInfo->FullLoadFromFile();
4872 SMESH::long_array_var aResult = new SMESH::long_array();
4873 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4875 if ( aMeshDS == NULL )
4876 return aResult._retn();
4878 long nbNodes = NbNodes();
4879 aResult->length( nbNodes );
4880 SMDS_NodeIteratorPtr anIt = aMeshDS->nodesIterator();
4881 for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
4882 aResult[i] = anIt->next()->GetID();
4884 return aResult._retn();
4887 //=============================================================================
4889 * Return type of the given element
4891 //=============================================================================
4893 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
4894 throw (SALOME::SALOME_Exception)
4896 SMESH::ElementType type = SMESH::ALL;
4900 _preMeshInfo->FullLoadFromFile();
4902 type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
4904 SMESH_CATCH( SMESH::throwCorbaException );
4909 //=============================================================================
4911 * Return geometric type of the given element
4913 //=============================================================================
4915 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
4916 throw (SALOME::SALOME_Exception)
4919 _preMeshInfo->FullLoadFromFile();
4921 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4923 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4925 return ( SMESH::EntityType ) e->GetEntityType();
4928 //=============================================================================
4930 * Return type of the given element
4932 //=============================================================================
4934 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const CORBA::Long id )
4935 throw (SALOME::SALOME_Exception)
4938 _preMeshInfo->FullLoadFromFile();
4940 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4942 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4944 return ( SMESH::GeometryType ) e->GetGeomType();
4947 //=============================================================================
4949 * Return ID of elements for given submesh
4951 //=============================================================================
4953 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
4954 throw (SALOME::SALOME_Exception)
4956 SMESH::long_array_var aResult = new SMESH::long_array();
4960 _preMeshInfo->FullLoadFromFile();
4962 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4963 if(!SM) return aResult._retn();
4965 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4966 if(!SDSM) return aResult._retn();
4968 aResult->length(SDSM->NbElements());
4970 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4972 while ( eIt->more() ) {
4973 aResult[i++] = eIt->next()->GetID();
4976 SMESH_CATCH( SMESH::throwCorbaException );
4978 return aResult._retn();
4981 //=============================================================================
4983 * Return ID of nodes for given sub-mesh
4984 * If param all==true - return all nodes, else -
4985 * Return only nodes on shapes.
4987 //=============================================================================
4989 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
4991 throw (SALOME::SALOME_Exception)
4993 SMESH::long_array_var aResult = new SMESH::long_array();
4997 _preMeshInfo->FullLoadFromFile();
4999 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5000 if(!SM) return aResult._retn();
5002 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5003 if(!SDSM) return aResult._retn();
5006 if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
5007 SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
5008 while ( nIt->more() ) {
5009 const SMDS_MeshNode* elem = nIt->next();
5010 theElems.insert( elem->GetID() );
5013 else { // all nodes of submesh elements
5014 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5015 while ( eIt->more() ) {
5016 const SMDS_MeshElement* anElem = eIt->next();
5017 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
5018 while ( nIt->more() ) {
5019 const SMDS_MeshElement* elem = nIt->next();
5020 theElems.insert( elem->GetID() );
5025 aResult->length(theElems.size());
5026 set<int>::iterator itElem;
5028 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
5029 aResult[i++] = *itElem;
5031 SMESH_CATCH( SMESH::throwCorbaException );
5033 return aResult._retn();
5036 //=============================================================================
5038 * Return type of elements for given sub-mesh
5040 //=============================================================================
5042 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
5043 throw (SALOME::SALOME_Exception)
5045 SMESH::ElementType type = SMESH::ALL;
5049 _preMeshInfo->FullLoadFromFile();
5051 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5052 if(!SM) return SMESH::ALL;
5054 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5055 if(!SDSM) return SMESH::ALL;
5057 if(SDSM->NbElements()==0)
5058 return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
5060 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5061 const SMDS_MeshElement* anElem = eIt->next();
5063 type = ( SMESH::ElementType ) anElem->GetType();
5065 SMESH_CATCH( SMESH::throwCorbaException );
5071 //=============================================================================
5073 * Return pointer to _impl as an integer value. Is called from constructor of SMESH_Client
5075 //=============================================================================
5077 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
5080 _preMeshInfo->FullLoadFromFile();
5082 CORBA::LongLong pointeur = CORBA::LongLong(_impl);
5083 if ( MYDEBUG ) MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
5088 //=============================================================================
5090 * Get XYZ coordinates of node as list of double
5091 * If there is not node for given ID - return empty list
5093 //=============================================================================
5095 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
5098 _preMeshInfo->FullLoadFromFile();
5100 SMESH::double_array_var aResult = new SMESH::double_array();
5101 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5102 if ( aMeshDS == NULL )
5103 return aResult._retn();
5106 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5108 return aResult._retn();
5112 aResult[0] = aNode->X();
5113 aResult[1] = aNode->Y();
5114 aResult[2] = aNode->Z();
5115 return aResult._retn();
5119 //=============================================================================
5121 * For given node return list of IDs of inverse elements
5122 * If there is not node for given ID - return empty list
5124 //=============================================================================
5126 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id,
5127 SMESH::ElementType elemType)
5130 _preMeshInfo->FullLoadFromFile();
5132 SMESH::long_array_var aResult = new SMESH::long_array();
5133 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5134 if ( aMeshDS == NULL )
5135 return aResult._retn();
5138 const SMDS_MeshNode* aNode = aMeshDS->FindNode( id );
5140 return aResult._retn();
5142 // find inverse elements
5143 SMDSAbs_ElementType type = SMDSAbs_ElementType( elemType );
5144 SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator( type );
5145 aResult->length( aNode->NbInverseElements( type ));
5146 for( int i = 0; eIt->more(); ++i )
5148 const SMDS_MeshElement* elem = eIt->next();
5149 aResult[ i ] = elem->GetID();
5151 return aResult._retn();
5154 //=============================================================================
5156 * \brief Return position of a node on shape
5158 //=============================================================================
5160 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
5163 _preMeshInfo->FullLoadFromFile();
5165 SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
5166 aNodePosition->shapeID = 0;
5167 aNodePosition->shapeType = GEOM::SHAPE;
5169 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5170 if ( !mesh ) return aNodePosition;
5172 if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
5174 if ( SMDS_PositionPtr pos = aNode->GetPosition() )
5176 aNodePosition->shapeID = aNode->getshapeId();
5177 switch ( pos->GetTypeOfPosition() ) {
5179 aNodePosition->shapeType = GEOM::EDGE;
5180 aNodePosition->params.length(1);
5181 aNodePosition->params[0] = SMDS_EdgePositionPtr( pos )->GetUParameter();
5183 case SMDS_TOP_FACE: {
5184 SMDS_FacePositionPtr fPos = pos;
5185 aNodePosition->shapeType = GEOM::FACE;
5186 aNodePosition->params.length(2);
5187 aNodePosition->params[0] = fPos->GetUParameter();
5188 aNodePosition->params[1] = fPos->GetVParameter();
5191 case SMDS_TOP_VERTEX:
5192 aNodePosition->shapeType = GEOM::VERTEX;
5194 case SMDS_TOP_3DSPACE:
5195 if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
5196 aNodePosition->shapeType = GEOM::SOLID;
5197 else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
5198 aNodePosition->shapeType = GEOM::SHELL;
5204 return aNodePosition;
5207 //=============================================================================
5209 * \brief Return position of an element on shape
5211 //=============================================================================
5213 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
5216 _preMeshInfo->FullLoadFromFile();
5218 SMESH::ElementPosition anElementPosition;
5219 anElementPosition.shapeID = 0;
5220 anElementPosition.shapeType = GEOM::SHAPE;
5222 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5223 if ( !mesh ) return anElementPosition;
5225 if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
5227 anElementPosition.shapeID = anElem->getshapeId();
5228 const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
5229 if ( !aSp.IsNull() ) {
5230 switch ( aSp.ShapeType() ) {
5232 anElementPosition.shapeType = GEOM::EDGE;
5235 anElementPosition.shapeType = GEOM::FACE;
5238 anElementPosition.shapeType = GEOM::VERTEX;
5241 anElementPosition.shapeType = GEOM::SOLID;
5244 anElementPosition.shapeType = GEOM::SHELL;
5250 return anElementPosition;
5253 //=============================================================================
5255 * If given element is node return IDs of shape from position
5256 * If there is not node for given ID - return -1
5258 //=============================================================================
5260 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
5263 _preMeshInfo->FullLoadFromFile();
5265 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5266 if ( aMeshDS == NULL )
5270 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5272 return aNode->getshapeId();
5279 //=============================================================================
5281 * For given element return ID of result shape after
5282 * ::FindShape() from SMESH_MeshEditor
5283 * If there is not element for given ID - return -1
5285 //=============================================================================
5287 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
5290 _preMeshInfo->FullLoadFromFile();
5292 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5293 if ( aMeshDS == NULL )
5296 // try to find element
5297 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5301 ::SMESH_MeshEditor aMeshEditor(_impl);
5302 int index = aMeshEditor.FindShape( elem );
5310 //=============================================================================
5312 * Return number of nodes for given element
5313 * If there is not element for given ID - return -1
5315 //=============================================================================
5317 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
5320 _preMeshInfo->FullLoadFromFile();
5322 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5323 if ( aMeshDS == NULL ) return -1;
5324 // try to find element
5325 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5326 if(!elem) return -1;
5327 return elem->NbNodes();
5331 //=============================================================================
5333 * Return ID of node by given index for given element
5334 * If there is not element for given ID - return -1
5335 * If there is not node for given index - return -2
5337 //=============================================================================
5339 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
5342 _preMeshInfo->FullLoadFromFile();
5344 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5345 if ( aMeshDS == NULL ) return -1;
5346 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5347 if(!elem) return -1;
5348 if( index>=elem->NbNodes() || index<0 ) return -1;
5349 return elem->GetNode(index)->GetID();
5352 //=============================================================================
5354 * Return IDs of nodes of given element
5356 //=============================================================================
5358 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
5361 _preMeshInfo->FullLoadFromFile();
5363 SMESH::long_array_var aResult = new SMESH::long_array();
5364 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5366 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(id) )
5368 aResult->length( elem->NbNodes() );
5369 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5370 if ( const SMDS_MeshNode* n = elem->GetNode( i ))
5371 aResult[ i ] = n->GetID();
5374 return aResult._retn();
5377 //=============================================================================
5379 * Return true if given node is medium node
5380 * in given quadratic element
5382 //=============================================================================
5384 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
5387 _preMeshInfo->FullLoadFromFile();
5389 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5390 if ( aMeshDS == NULL ) return false;
5392 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5393 if(!aNode) return false;
5394 // try to find element
5395 const SMDS_MeshElement* elem = aMeshDS->FindElement(ide);
5396 if(!elem) return false;
5398 return elem->IsMediumNode(aNode);
5402 //=============================================================================
5404 * Return true if given node is medium node
5405 * in one of quadratic elements
5407 //=============================================================================
5409 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
5410 SMESH::ElementType theElemType)
5413 _preMeshInfo->FullLoadFromFile();
5415 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5416 if ( aMeshDS == NULL ) return false;
5419 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5420 if(!aNode) return false;
5422 SMESH_MesherHelper aHelper( *(_impl) );
5424 SMDSAbs_ElementType aType;
5425 if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
5426 else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
5427 else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
5428 else aType = SMDSAbs_All;
5430 return aHelper.IsMedium(aNode,aType);
5434 //=============================================================================
5436 * Return number of edges for given element
5438 //=============================================================================
5440 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
5443 _preMeshInfo->FullLoadFromFile();
5445 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5446 if ( aMeshDS == NULL ) return -1;
5447 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5448 if(!elem) return -1;
5449 return elem->NbEdges();
5453 //=============================================================================
5455 * Return number of faces for given element
5457 //=============================================================================
5459 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
5462 _preMeshInfo->FullLoadFromFile();
5464 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5465 if ( aMeshDS == NULL ) return -1;
5466 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5467 if(!elem) return -1;
5468 return elem->NbFaces();
5471 //================================================================================
5473 * \brief Return nodes of given face (counted from zero) for given element.
5475 //================================================================================
5477 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long elemId,
5478 CORBA::Short faceIndex)
5481 _preMeshInfo->FullLoadFromFile();
5483 SMESH::long_array_var aResult = new SMESH::long_array();
5484 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5486 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) )
5488 SMDS_VolumeTool vtool( elem, /*skipCentralNodes = */false );
5489 if ( faceIndex < vtool.NbFaces() )
5491 aResult->length( vtool.NbFaceNodes( faceIndex ));
5492 const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
5493 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5494 aResult[ i ] = nn[ i ]->GetID();
5498 return aResult._retn();
5501 //================================================================================
5503 * \brief Return three components of normal of given mesh face.
5505 //================================================================================
5507 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long elemId,
5508 CORBA::Boolean normalized)
5511 _preMeshInfo->FullLoadFromFile();
5513 SMESH::double_array_var aResult = new SMESH::double_array();
5515 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5518 if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
5520 aResult->length( 3 );
5521 aResult[ 0 ] = normal.X();
5522 aResult[ 1 ] = normal.Y();
5523 aResult[ 2 ] = normal.Z();
5526 return aResult._retn();
5529 //================================================================================
5531 * \brief Return an element based on all given nodes.
5533 //================================================================================
5535 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
5538 _preMeshInfo->FullLoadFromFile();
5540 CORBA::Long elemID(0);
5541 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5543 vector< const SMDS_MeshNode * > nn( nodes.length() );
5544 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5545 if ( !( nn[i] = mesh->FindNode( nodes[i] )))
5548 const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
5549 if ( !elem && ( _impl->NbEdges ( ORDER_QUADRATIC ) ||
5550 _impl->NbFaces ( ORDER_QUADRATIC ) ||
5551 _impl->NbVolumes( ORDER_QUADRATIC )))
5552 elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
5554 if ( elem ) elemID = CORBA::Long( elem->GetID() );
5559 //================================================================================
5561 * \brief Return elements including all given nodes.
5563 //================================================================================
5565 SMESH::long_array* SMESH_Mesh_i::GetElementsByNodes(const SMESH::long_array& nodes,
5566 SMESH::ElementType elemType)
5569 _preMeshInfo->FullLoadFromFile();
5571 SMESH::long_array_var result = new SMESH::long_array();
5573 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5575 vector< const SMDS_MeshNode * > nn( nodes.length() );
5576 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5577 nn[i] = mesh->FindNode( nodes[i] );
5579 std::vector<const SMDS_MeshElement *> elems;
5580 mesh->GetElementsByNodes( nn, elems, (SMDSAbs_ElementType) elemType );
5581 result->length( elems.size() );
5582 for ( size_t i = 0; i < elems.size(); ++i )
5583 result[i] = elems[i]->GetID();
5585 return result._retn();
5588 //=============================================================================
5590 * Return true if given element is polygon
5592 //=============================================================================
5594 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
5597 _preMeshInfo->FullLoadFromFile();
5599 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5600 if ( aMeshDS == NULL ) return false;
5601 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5602 if(!elem) return false;
5603 return elem->IsPoly();
5607 //=============================================================================
5609 * Return true if given element is quadratic
5611 //=============================================================================
5613 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
5616 _preMeshInfo->FullLoadFromFile();
5618 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5619 if ( aMeshDS == NULL ) return false;
5620 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5621 if(!elem) return false;
5622 return elem->IsQuadratic();
5625 //=============================================================================
5627 * Return diameter of ball discrete element or zero in case of an invalid \a id
5629 //=============================================================================
5631 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
5634 _preMeshInfo->FullLoadFromFile();
5636 if ( const SMDS_BallElement* ball =
5637 SMDS_Mesh::DownCast<SMDS_BallElement>( _impl->GetMeshDS()->FindElement( id )))
5638 return ball->GetDiameter();
5643 //=============================================================================
5645 * Return bary center for given element
5647 //=============================================================================
5649 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
5652 _preMeshInfo->FullLoadFromFile();
5654 SMESH::double_array_var aResult = new SMESH::double_array();
5655 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5656 if ( aMeshDS == NULL )
5657 return aResult._retn();
5659 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5661 return aResult._retn();
5663 if(elem->GetType()==SMDSAbs_Volume) {
5664 SMDS_VolumeTool aTool;
5665 if(aTool.Set(elem)) {
5667 if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
5672 SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
5674 double x=0., y=0., z=0.;
5675 for(; anIt->more(); ) {
5677 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
5691 return aResult._retn();
5694 //================================================================================
5696 * \brief Create a group of elements preventing computation of a sub-shape
5698 //================================================================================
5700 SMESH::ListOfGroups*
5701 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int theSubShapeID,
5702 const char* theGroupName )
5703 throw ( SALOME::SALOME_Exception )
5705 Unexpect aCatch(SALOME_SalomeException);
5707 if ( !theGroupName || strlen( theGroupName) == 0 )
5708 THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
5710 SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
5711 ::SMESH_MeshEditor::ElemFeatures elemType;
5713 // submesh by subshape id
5714 if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
5715 if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
5718 SMESH_ComputeErrorPtr error = sm->GetComputeError();
5719 if ( error && error->HasBadElems() )
5721 // sort bad elements by type
5722 vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
5723 const list<const SMDS_MeshElement*>& badElems =
5724 static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
5725 list<const SMDS_MeshElement*>::const_iterator elemIt = badElems.begin();
5726 list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
5727 for ( ; elemIt != elemEnd; ++elemIt )
5729 const SMDS_MeshElement* elem = *elemIt;
5730 if ( !elem ) continue;
5732 if ( elem->GetID() < 1 )
5734 // elem is a temporary element, make a real element
5735 vector< const SMDS_MeshNode* > nodes;
5736 SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
5737 while ( nIt->more() && elem )
5739 nodes.push_back( nIt->next() );
5740 if ( nodes.back()->GetID() < 1 )
5741 elem = 0; // a temporary element on temporary nodes
5745 ::SMESH_MeshEditor editor( _impl );
5746 elem = editor.AddElement( nodes, elemType.Init( elem ));
5750 elemsByType[ elem->GetType() ].push_back( elem );
5753 // how many groups to create?
5755 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5756 nbTypes += int( !elemsByType[ i ].empty() );
5757 groups->length( nbTypes );
5760 for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
5762 vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
5763 if ( elems.empty() ) continue;
5765 groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
5766 if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
5768 SMESH::SMESH_Mesh_var mesh = _this();
5769 SALOMEDS::SObject_wrap aSO =
5770 _gen_i->PublishGroup( mesh, groups[ iG ],
5771 GEOM::GEOM_Object::_nil(), theGroupName);
5773 SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
5774 if ( !grp_i ) continue;
5776 if ( SMESHDS_Group* grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
5777 for ( size_t iE = 0; iE < elems.size(); ++iE )
5778 grpDS->SMDSGroup().Add( elems[ iE ]);
5783 return groups._retn();
5786 //=============================================================================
5788 * Create and publish group servants if any groups were imported or created anyhow
5790 //=============================================================================
5792 void SMESH_Mesh_i::CreateGroupServants()
5794 SMESH::SMESH_Mesh_var aMesh = _this();
5797 ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
5798 while ( groupIt->more() )
5800 ::SMESH_Group* group = groupIt->next();
5801 int anId = group->GetID();
5803 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
5804 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5806 addedIDs.insert( anId );
5808 SMESH_GroupBase_i* aGroupImpl;
5810 if ( SMESHDS_GroupOnGeom* groupOnGeom =
5811 dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
5813 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
5814 shape = groupOnGeom->GetShape();
5817 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
5820 SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
5821 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
5822 aGroupImpl->Register();
5824 // register CORBA object for persistence
5825 int nextId = _gen_i->RegisterObject( groupVar );
5826 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
5827 else { nextId = 0; } // avoid "unused variable" warning in release mode
5829 // publishing the groups in the study
5830 GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
5831 _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName());
5834 if ( !addedIDs.empty() )
5837 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
5838 for ( int index = 0; i_grp != _mapGroups.end(); ++index, ++i_grp )
5840 set<int>::iterator it = addedIDs.find( i_grp->first );
5841 if ( it != addedIDs.end() )
5843 TPythonDump() << i_grp->second << " = " << aMesh << ".GetGroups()[ "<< index << " ]";
5844 addedIDs.erase( it );
5845 if ( addedIDs.empty() )
5852 //=============================================================================
5854 * \brief Return true if all sub-meshes are computed OK - to update an icon
5856 //=============================================================================
5858 bool SMESH_Mesh_i::IsComputedOK()
5860 return _impl->IsComputedOK();
5863 //=============================================================================
5865 * \brief Return groups cantained in _mapGroups by their IDs
5867 //=============================================================================
5869 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
5871 int nbGroups = groupIDs.size();
5872 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
5873 aList->length( nbGroups );
5875 list<int>::const_iterator ids = groupIDs.begin();
5876 for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
5878 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
5879 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5880 aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
5882 aList->length( nbGroups );
5883 return aList._retn();
5886 //=============================================================================
5888 * \brief Return information about imported file
5890 //=============================================================================
5892 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
5894 SMESH::MedFileInfo_var res( _medFileInfo );
5895 if ( !res.operator->() ) {
5896 res = new SMESH::MedFileInfo;
5898 res->fileSize = res->major = res->minor = res->release = -1;
5903 //=======================================================================
5904 //function : FileInfoToString
5905 //purpose : Persistence of file info
5906 //=======================================================================
5908 std::string SMESH_Mesh_i::FileInfoToString()
5911 if ( &_medFileInfo.in() && _medFileInfo->fileName[0] )
5913 s = SMESH_Comment( _medFileInfo->fileSize )
5914 << " " << _medFileInfo->major
5915 << " " << _medFileInfo->minor
5916 << " " << _medFileInfo->release
5917 << " " << _medFileInfo->fileName;
5922 //=======================================================================
5923 //function : FileInfoFromString
5924 //purpose : Persistence of file info
5925 //=======================================================================
5927 void SMESH_Mesh_i::FileInfoFromString(const std::string& info)
5929 std::string size, major, minor, release, fileName;
5930 std::istringstream is(info);
5931 is >> size >> major >> minor >> release;
5932 fileName = info.data() + ( size.size() + 1 +
5935 release.size()+ 1 );
5937 _medFileInfo = new SMESH::MedFileInfo();
5938 _medFileInfo->fileName = fileName.c_str();
5939 _medFileInfo->fileSize = atoi( size.c_str() );
5940 _medFileInfo->major = atoi( major.c_str() );
5941 _medFileInfo->minor = atoi( minor.c_str() );
5942 _medFileInfo->release = atoi( release.c_str() );
5945 //=============================================================================
5947 * \brief Pass names of mesh groups from study to mesh DS
5949 //=============================================================================
5951 void SMESH_Mesh_i::checkGroupNames()
5953 int nbGrp = NbGroups();
5957 SMESH::ListOfGroups* grpList = 0;
5958 // avoid dump of "GetGroups"
5960 // store python dump into a local variable inside local scope
5961 SMESH::TPythonDump pDump; // do not delete this line of code
5962 grpList = GetGroups();
5965 for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
5966 SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
5969 SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aGrp );
5970 if ( aGrpSO->_is_nil() )
5972 // correct name of the mesh group if necessary
5973 const char* guiName = aGrpSO->GetName();
5974 if ( strcmp(guiName, aGrp->GetName()) )
5975 aGrp->SetName( guiName );
5979 //=============================================================================
5981 * \brief Set list of notebook variables used for Mesh operations separated by ":" symbol
5983 //=============================================================================
5984 void SMESH_Mesh_i::SetParameters(const char* theParameters)
5986 SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
5990 //=============================================================================
5992 * \brief Return list of notebook variables used for Mesh operations separated by ":" symbol
5994 //=============================================================================
5996 char* SMESH_Mesh_i::GetParameters()
5998 return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
6001 //=============================================================================
6003 * \brief Return list of notebook variables used for last Mesh operation
6005 //=============================================================================
6006 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
6008 SMESH::string_array_var aResult = new SMESH::string_array();
6009 SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
6011 CORBA::String_var aParameters = GetParameters();
6012 SALOMEDS::ListOfListOfStrings_var aSections = SMESH_Gen_i::getStudyServant()->ParseVariables(aParameters);
6013 if ( aSections->length() > 0 ) {
6014 SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
6015 aResult->length( aVars.length() );
6016 for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
6017 aResult[i] = CORBA::string_dup( aVars[i] );
6020 return aResult._retn();
6023 //================================================================================
6025 * \brief Return types of elements it contains
6027 //================================================================================
6029 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
6032 return _preMeshInfo->GetTypes();
6034 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
6038 if (_impl->NbEdges()) types[nbTypes++] = SMESH::EDGE;
6039 if (_impl->NbFaces()) types[nbTypes++] = SMESH::FACE;
6040 if (_impl->NbVolumes()) types[nbTypes++] = SMESH::VOLUME;
6041 if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
6042 if (_impl->NbBalls()) types[nbTypes++] = SMESH::BALL;
6043 if (_impl->NbNodes() &&
6044 nbTypes == 0 ) types[nbTypes++] = SMESH::NODE;
6045 types->length( nbTypes );
6047 return types._retn();
6050 //================================================================================
6052 * \brief Return self
6054 //================================================================================
6056 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
6058 return SMESH::SMESH_Mesh::_duplicate( _this() );
6061 //================================================================================
6063 * \brief Return false if GetMeshInfo() return incorrect information that may
6064 * happen if mesh data is not yet fully loaded from the file of study.
6068 //================================================================================
6070 bool SMESH_Mesh_i::IsMeshInfoCorrect()
6072 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
6075 //=============================================================================
6077 * \brief Return number of mesh elements per each \a EntityType
6079 //=============================================================================
6081 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
6084 return _preMeshInfo->GetMeshInfo();
6086 SMESH::long_array_var aRes = new SMESH::long_array();
6087 aRes->length(SMESH::Entity_Last);
6088 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6090 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6092 return aRes._retn();
6093 const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
6094 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6095 aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
6096 return aRes._retn();
6099 //=============================================================================
6101 * \brief Return number of mesh elements per each \a ElementType
6103 //=============================================================================
6105 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
6107 SMESH::long_array_var aRes = new SMESH::long_array();
6108 aRes->length(SMESH::NB_ELEMENT_TYPES);
6109 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6112 const SMDS_MeshInfo* meshInfo = 0;
6114 meshInfo = _preMeshInfo;
6115 else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
6116 meshInfo = & meshDS->GetMeshInfo();
6119 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6120 aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
6122 return aRes._retn();
6125 //=============================================================================
6127 * Collect statistic of mesh elements given by iterator
6129 //=============================================================================
6131 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
6132 SMESH::long_array& theInfo)
6134 if (!theItr) return;
6135 while (theItr->more())
6136 theInfo[ theItr->next()->GetEntityType() ]++;
6138 //=============================================================================
6140 * Return mesh unstructed grid information.
6142 //=============================================================================
6144 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
6146 SALOMEDS::TMPFile_var SeqFile;
6147 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
6148 SMDS_UnstructuredGrid* aGrid = aMeshDS->GetGrid();
6150 vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
6151 aWriter->WriteToOutputStringOn();
6152 aWriter->SetInputData(aGrid);
6153 aWriter->SetFileTypeToBinary();
6155 char* str = aWriter->GetOutputString();
6156 int size = aWriter->GetOutputStringLength();
6158 //Allocate octet buffer of required size
6159 CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
6160 //Copy ostrstream content to the octet buffer
6161 memcpy(OctetBuf, str, size);
6162 //Create and return TMPFile
6163 SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
6167 return SeqFile._retn();
6170 //=============================================================================
6171 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
6172 * SMESH::ElementType type) */
6174 using namespace SMESH::Controls;
6175 //-----------------------------------------------------------------------------
6176 struct PredicateIterator : public SMDS_ElemIterator
6178 SMDS_ElemIteratorPtr _elemIter;
6179 PredicatePtr _predicate;
6180 const SMDS_MeshElement* _elem;
6181 SMDSAbs_ElementType _type;
6183 PredicateIterator( SMDS_ElemIteratorPtr iterator,
6184 PredicatePtr predicate,
6185 SMDSAbs_ElementType type):
6186 _elemIter(iterator), _predicate(predicate), _type(type)
6194 virtual const SMDS_MeshElement* next()
6196 const SMDS_MeshElement* res = _elem;
6198 while ( _elemIter->more() && !_elem )
6200 if ((_elem = _elemIter->next()) &&
6201 (( _type != SMDSAbs_All && _type != _elem->GetType() ) ||
6202 ( !_predicate->IsSatisfy( _elem->GetID() ))))
6209 //-----------------------------------------------------------------------------
6210 struct IDSourceIterator : public SMDS_ElemIterator
6212 const CORBA::Long* _idPtr;
6213 const CORBA::Long* _idEndPtr;
6214 SMESH::long_array_var _idArray;
6215 const SMDS_Mesh* _mesh;
6216 const SMDSAbs_ElementType _type;
6217 const SMDS_MeshElement* _elem;
6219 IDSourceIterator( const SMDS_Mesh* mesh,
6220 const CORBA::Long* ids,
6222 SMDSAbs_ElementType type):
6223 _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
6225 if ( _idPtr && nbIds && _mesh )
6228 IDSourceIterator( const SMDS_Mesh* mesh,
6229 SMESH::long_array* idArray,
6230 SMDSAbs_ElementType type):
6231 _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
6233 if ( idArray && _mesh )
6235 _idPtr = &_idArray[0];
6236 _idEndPtr = _idPtr + _idArray->length();
6244 virtual const SMDS_MeshElement* next()
6246 const SMDS_MeshElement* res = _elem;
6248 while ( _idPtr < _idEndPtr && !_elem )
6250 if ( _type == SMDSAbs_Node )
6252 _elem = _mesh->FindNode( *_idPtr++ );
6254 else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
6255 (_elem->GetType() != _type && _type != SMDSAbs_All ))
6263 //-----------------------------------------------------------------------------
6265 struct NodeOfElemIterator : public SMDS_ElemIterator
6267 TColStd_MapOfInteger _checkedNodeIDs;
6268 SMDS_ElemIteratorPtr _elemIter;
6269 SMDS_ElemIteratorPtr _nodeIter;
6270 const SMDS_MeshElement* _node;
6272 NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
6274 if ( _elemIter && _elemIter->more() )
6276 _nodeIter = _elemIter->next()->nodesIterator();
6284 virtual const SMDS_MeshElement* next()
6286 const SMDS_MeshElement* res = _node;
6288 while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
6290 if ( _nodeIter->more() )
6292 _node = _nodeIter->next();
6293 if ( !_checkedNodeIDs.Add( _node->GetID() ))
6298 _nodeIter = _elemIter->next()->nodesIterator();
6306 //=============================================================================
6308 * Return iterator on elements of given type in given object
6310 //=============================================================================
6312 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
6313 SMESH::ElementType theType)
6315 SMDS_ElemIteratorPtr elemIt;
6316 bool typeOK = ( theType == SMESH::ALL );
6317 SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
6319 SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
6320 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
6321 if ( !mesh_i ) return elemIt;
6322 SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
6324 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
6326 elemIt = meshDS->elementsIterator( elemType );
6329 else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
6331 SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
6334 elemIt = sm->GetElements();
6335 if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6337 typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
6338 elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
6342 else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
6344 SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
6345 if ( groupDS && ( elemType == groupDS->GetType() ||
6346 elemType == SMDSAbs_Node ||
6347 elemType == SMDSAbs_All ))
6349 elemIt = groupDS->GetElements();
6350 typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
6353 else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
6355 if ( filter_i->GetElementType() == theType ||
6356 filter_i->GetElementType() == SMESH::ALL ||
6357 elemType == SMDSAbs_Node ||
6358 elemType == SMDSAbs_All)
6360 SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
6361 if ( pred_i && pred_i->GetPredicate() )
6363 SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
6364 SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
6365 SMDSAbs_ElementType iterType = elemType == SMDSAbs_Node ? filterType : elemType;
6366 elemIt = SMDS_ElemIteratorPtr
6367 ( new PredicateIterator( allElemIt, pred_i->GetPredicate(), iterType ));
6368 typeOK = ( elemType == SMDSAbs_Node ? filterType == SMDSAbs_Node : elemIt->more() );
6374 SMESH::array_of_ElementType_var types = theObject->GetTypes();
6375 const bool isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
6376 if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6378 SMDSAbs_ElementType iterType = isNodes ? SMDSAbs_Node : elemType;
6379 if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
6382 if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
6383 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, iterType ));
6387 SMESH::long_array_var ids = theObject->GetIDs();
6388 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), iterType ));
6390 typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
6393 if ( elemIt && elemIt->more() && !typeOK )
6395 if ( elemType == SMDSAbs_Node )
6397 elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
6401 elemIt = SMDS_ElemIteratorPtr();
6407 //=============================================================================
6408 namespace // Finding concurrent hypotheses
6409 //=============================================================================
6413 * \brief mapping of mesh dimension into shape type
6415 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
6417 TopAbs_ShapeEnum aType = TopAbs_SOLID;
6419 case 0: aType = TopAbs_VERTEX; break;
6420 case 1: aType = TopAbs_EDGE; break;
6421 case 2: aType = TopAbs_FACE; break;
6423 default:aType = TopAbs_SOLID; break;
6428 //-----------------------------------------------------------------------------
6430 * \brief Internal structure used to find concurrent submeshes
6432 * It represents a pair < submesh, concurrent dimension >, where
6433 * 'concurrent dimension' is dimension of shape where the submesh can concurrent
6434 * with another submesh. In other words, it is dimension of a hypothesis assigned
6441 int _dim; //!< a dimension the algo can build (concurrent dimension)
6442 int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
6443 TopTools_MapOfShape _shapeMap; //!< [sub-]shapes of dimension == _dim
6444 const SMESH_subMesh* _subMesh;
6445 list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
6447 //-----------------------------------------------------------------------------
6448 // Return the algorithm
6449 const SMESH_Algo* GetAlgo() const
6450 { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
6452 //-----------------------------------------------------------------------------
6454 SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
6456 const TopoDS_Shape& theShape)
6458 _subMesh = theSubMesh;
6459 SetShape( theDim, theShape );
6462 //-----------------------------------------------------------------------------
6464 void SetShape(const int theDim,
6465 const TopoDS_Shape& theShape)
6468 _ownDim = SMESH_Gen::GetShapeDim(theShape);
6469 if (_dim >= _ownDim)
6470 _shapeMap.Add( theShape );
6472 TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
6473 for( ; anExp.More(); anExp.Next() )
6474 _shapeMap.Add( anExp.Current() );
6478 //-----------------------------------------------------------------------------
6479 //! Check sharing of sub-shapes
6480 static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
6481 const TopTools_MapOfShape& theToFind,
6482 const TopAbs_ShapeEnum theType)
6484 bool isShared = false;
6485 TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
6486 for (; !isShared && anItr.More(); anItr.Next() )
6488 const TopoDS_Shape aSubSh = anItr.Key();
6489 // check for case when concurrent dimensions are same
6490 isShared = theToFind.Contains( aSubSh );
6491 // check for sub-shape with concurrent dimension
6492 TopExp_Explorer anExp( aSubSh, theType );
6493 for ( ; !isShared && anExp.More(); anExp.Next() )
6494 isShared = theToFind.Contains( anExp.Current() );
6499 //-----------------------------------------------------------------------------
6500 //! check algorithms
6501 static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
6502 const SMESHDS_Hypothesis* theA2)
6504 if ( !theA1 || !theA2 ||
6505 theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
6506 theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
6507 return false; // one of the hypothesis is not algorithm
6508 // check algorithm names (should be equal)
6509 return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
6513 //-----------------------------------------------------------------------------
6514 //! Check if sub-shape hypotheses are concurrent
6515 bool IsConcurrent(const SMESH_DimHyp* theOther) const
6517 if ( _subMesh == theOther->_subMesh )
6518 return false; // same sub-shape - should not be
6520 // if ( <own dim of either of submeshes> == <concurrent dim> &&
6521 // any of the two submeshes is not on COMPOUND shape )
6522 // -> no concurrency
6523 bool meIsCompound = (_subMesh->GetSubMeshDS() &&
6524 _subMesh->GetSubMeshDS()->IsComplexSubmesh());
6525 bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
6526 theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
6527 if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
6530 bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
6531 if ( !checkSubShape )
6534 // check algorithms to be same
6535 const SMESH_Algo* a1 = this->GetAlgo();
6536 const SMESH_Algo* a2 = theOther->GetAlgo();
6537 bool isSame = checkAlgo( a1, a2 );
6541 // commented off for IPAL54678
6542 // if ( !a1 || !a2 )
6543 // return false; // pb?
6544 // return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency !
6547 // check hypothesises for concurrence (skip first as algorithm)
6549 // pointers should be same, because it is referened from mesh hypothesis partition
6550 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
6551 list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
6552 for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
6553 if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
6555 // the submeshes are concurrent if their algorithms has different parameters
6556 return nbSame != theOther->_hypotheses.size() - 1;
6559 // Return true if algorithm of this SMESH_DimHyp is used if no
6560 // sub-mesh order is imposed by the user
6561 bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
6563 // NeedDiscreteBoundary() algo has a higher priority
6564 if ( this ->GetAlgo()->NeedDiscreteBoundary() !=
6565 theOther->GetAlgo()->NeedDiscreteBoundary() )
6566 return !this->GetAlgo()->NeedDiscreteBoundary();
6568 return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
6571 }; // end of SMESH_DimHyp
6572 //-----------------------------------------------------------------------------
6574 typedef list<const SMESH_DimHyp*> TDimHypList;
6576 //-----------------------------------------------------------------------------
6578 void addDimHypInstance(const int theDim,
6579 const TopoDS_Shape& theShape,
6580 const SMESH_Algo* theAlgo,
6581 const SMESH_subMesh* theSubMesh,
6582 const list <const SMESHDS_Hypothesis*>& theHypList,
6583 TDimHypList* theDimHypListArr )
6585 if ( !theAlgo->NeedDiscreteBoundary() &&
6586 theAlgo->NeedLowerHyps( theDim )) // IPAL54678
6588 TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
6589 if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh )
6591 SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
6592 dimHyp->_hypotheses.push_front(theAlgo);
6593 listOfdimHyp.push_back( dimHyp );
6596 SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
6597 dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
6598 theHypList.begin(), theHypList.end() );
6601 //-----------------------------------------------------------------------------
6602 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
6603 TDimHypList& theListOfConcurr)
6605 if ( theListOfConcurr.empty() )
6607 theListOfConcurr.push_back( theDimHyp );
6611 TDimHypList::iterator hypIt = theListOfConcurr.begin();
6612 while ( hypIt != theListOfConcurr.end() &&
6613 !theDimHyp->IsHigherPriorityThan( *hypIt ))
6615 theListOfConcurr.insert( hypIt, theDimHyp );
6619 //-----------------------------------------------------------------------------
6620 void findConcurrents(const SMESH_DimHyp* theDimHyp,
6621 const TDimHypList& theListOfDimHyp,
6622 TDimHypList& theListOfConcurrHyp,
6623 set<int>& theSetOfConcurrId )
6625 TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
6626 for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
6628 const SMESH_DimHyp* curDimHyp = *rIt;
6629 if ( curDimHyp == theDimHyp )
6630 break; // meet own dimHyp pointer in same dimension
6632 if ( theDimHyp->IsConcurrent( curDimHyp ) &&
6633 theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
6635 addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
6640 //-----------------------------------------------------------------------------
6641 void unionLists(TListOfInt& theListOfId,
6642 TListOfListOfInt& theListOfListOfId,
6645 TListOfListOfInt::iterator it = theListOfListOfId.begin();
6646 for ( int i = 0; it != theListOfListOfId.end(); it++, i++ )
6649 continue; //skip already treated lists
6650 // check if other list has any same submesh object
6651 TListOfInt& otherListOfId = *it;
6652 if ( find_first_of( theListOfId.begin(), theListOfId.end(),
6653 otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
6656 // union two lists (from source into target)
6657 TListOfInt::iterator it2 = otherListOfId.begin();
6658 for ( ; it2 != otherListOfId.end(); it2++ ) {
6659 if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
6660 theListOfId.push_back(*it2);
6662 // clear source list
6663 otherListOfId.clear();
6666 //-----------------------------------------------------------------------------
6668 //! free memory allocated for dimension-hypothesis objects
6669 void removeDimHyps( TDimHypList* theArrOfList )
6671 for (int i = 0; i < 4; i++ ) {
6672 TDimHypList& listOfdimHyp = theArrOfList[i];
6673 TDimHypList::const_iterator it = listOfdimHyp.begin();
6674 for ( ; it != listOfdimHyp.end(); it++ )
6679 //-----------------------------------------------------------------------------
6681 * \brief find common submeshes with given submesh
6682 * \param theSubMeshList list of already collected submesh to check
6683 * \param theSubMesh given submesh to intersect with other
6684 * \param theCommonSubMeshes collected common submeshes
6686 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
6687 const SMESH_subMesh* theSubMesh,
6688 set<const SMESH_subMesh*>& theCommon )
6692 list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
6693 for ( ; it != theSubMeshList.end(); it++ )
6694 theSubMesh->FindIntersection( *it, theCommon );
6695 theSubMeshList.push_back( theSubMesh );
6696 //theCommon.insert( theSubMesh );
6699 //-----------------------------------------------------------------------------
6700 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
6702 TListOfListOfInt::const_iterator listsIt = smLists.begin();
6703 for ( ; listsIt != smLists.end(); ++listsIt )
6705 const TListOfInt& smIDs = *listsIt;
6706 if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
6714 //=============================================================================
6716 * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
6718 //=============================================================================
6720 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
6722 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6723 if ( isSubMeshInList( submeshID, anOrder ))
6726 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6727 return isSubMeshInList( submeshID, allConurrent );
6730 //=============================================================================
6732 * \brief Return sub-mesh objects list in meshing order
6734 //=============================================================================
6736 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
6738 SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
6740 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6742 return aResult._retn();
6744 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6745 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6746 anOrder.splice( anOrder.end(), allConurrent );
6749 TListOfListOfInt::iterator listIt = anOrder.begin();
6750 for(; listIt != anOrder.end(); listIt++, listIndx++ )
6751 unionLists( *listIt, anOrder, listIndx + 1 );
6753 // convert submesh ids into interface instances
6754 // and dump command into python
6755 convertMeshOrder( anOrder, aResult, false );
6757 return aResult._retn();
6760 //=============================================================================
6762 * \brief Finds concurrent sub-meshes
6764 //=============================================================================
6766 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
6768 TListOfListOfInt anOrder;
6769 ::SMESH_Mesh& mesh = GetImpl();
6771 // collect submeshes and detect concurrent algorithms and hypothesises
6772 TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
6774 map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
6775 for ( ; i_sm != _mapSubMesh.end(); i_sm++ )
6777 ::SMESH_subMesh* sm = (*i_sm).second;
6779 const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
6781 // list of assigned hypothesises
6782 const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
6783 // Find out dimensions where the submesh can be concurrent.
6784 // We define the dimensions by algo of each of hypotheses in hypList
6785 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
6786 for( ; hypIt != hypList.end(); hypIt++ )
6788 SMESH_Algo* anAlgo = 0;
6789 const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
6790 if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
6791 // hyp it-self is algo
6792 anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
6794 // try to find algorithm with help of sub-shapes
6795 TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
6796 for ( ; !anAlgo && anExp.More(); anExp.Next() )
6797 anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
6800 continue; // no algorithm assigned to a current submesh
6802 int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
6803 // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary()
6804 // and !anAlgo->NeedLowerHyps( dim ))
6806 // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
6807 for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
6808 addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
6810 } // end iterations on submesh
6812 // iterate on created dimension-hypotheses and check for concurrents
6813 for ( int i = 0; i < 4; i++ )
6815 const TDimHypList& listOfDimHyp = dimHypListArr[i];
6816 // check for concurrents in own and other dimensions (step-by-step)
6817 TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
6818 for ( ; dhIt != listOfDimHyp.end(); dhIt++ )
6820 const SMESH_DimHyp* dimHyp = *dhIt;
6821 TDimHypList listOfConcurr;
6822 set<int> setOfConcurrIds;
6823 // looking for concurrents and collect into own list
6824 for ( int j = i; j < 4; j++ )
6825 findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
6826 // check if any concurrents found
6827 if ( listOfConcurr.size() > 0 )
6829 // add own submesh to list of concurrent
6830 addInOrderOfPriority( dimHyp, listOfConcurr );
6831 list<int> listOfConcurrIds;
6832 TDimHypList::iterator hypIt = listOfConcurr.begin();
6833 for ( ; hypIt != listOfConcurr.end(); ++hypIt )
6834 listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
6835 anOrder.push_back( listOfConcurrIds );
6840 removeDimHyps(dimHypListArr);
6842 // now, minimize the number of concurrent groups
6843 // Here we assume that lists of submeshes can have same submesh
6844 // in case of multi-dimension algorithms, as result
6845 // list with common submesh has to be united into one list
6847 TListOfListOfInt::iterator listIt = anOrder.begin();
6848 for(; listIt != anOrder.end(); listIt++, listIndx++ )
6849 unionLists( *listIt, anOrder, listIndx + 1 );
6854 //=============================================================================
6856 * \brief Set submesh object order
6857 * \param theSubMeshArray submesh array order
6859 //=============================================================================
6861 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
6864 _preMeshInfo->ForgetOrLoad();
6867 ::SMESH_Mesh& mesh = GetImpl();
6869 TPythonDump aPythonDump; // prevent dump of called methods
6870 aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
6872 TListOfListOfInt subMeshOrder;
6873 for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
6875 const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
6876 TListOfInt subMeshIds;
6878 aPythonDump << ", ";
6879 aPythonDump << "[ ";
6880 // Collect subMeshes which should be clear
6881 // do it list-by-list, because modification of submesh order
6882 // take effect between concurrent submeshes only
6883 set<const SMESH_subMesh*> subMeshToClear;
6884 list<const SMESH_subMesh*> subMeshList;
6885 for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
6887 const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
6889 aPythonDump << ", ";
6890 aPythonDump << subMesh;
6891 subMeshIds.push_back( subMesh->GetId() );
6892 // detect common parts of submeshes
6893 if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
6894 findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
6896 aPythonDump << " ]";
6897 subMeshOrder.push_back( subMeshIds );
6899 // clear collected sub-meshes
6900 set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
6901 for ( ; clrIt != subMeshToClear.end(); clrIt++ )
6902 if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
6904 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
6905 if ( SMESH_Algo* algo = sm->GetAlgo() ) // #16748
6906 sm->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, algo ); // to clear a cached algo
6909 aPythonDump << " ])";
6911 mesh.SetMeshOrder( subMeshOrder );
6914 SMESH::SMESH_Mesh_var me = _this();
6915 _gen_i->UpdateIcons( me );
6920 //=============================================================================
6922 * \brief Convert submesh ids into submesh interfaces
6924 //=============================================================================
6926 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt& theIdsOrder,
6927 SMESH::submesh_array_array& theResOrder,
6928 const bool theIsDump)
6930 int nbSet = theIdsOrder.size();
6931 TPythonDump aPythonDump; // prevent dump of called methods
6933 aPythonDump << "[ ";
6934 theResOrder.length(nbSet);
6935 TListOfListOfInt::const_iterator it = theIdsOrder.begin();
6937 for( ; it != theIdsOrder.end(); it++ )
6939 // translate submesh identificators into submesh objects
6940 // takeing into account real number of concurrent lists
6941 const TListOfInt& aSubOrder = (*it);
6942 if (!aSubOrder.size())
6945 aPythonDump << "[ ";
6946 // convert shape indices into interfaces
6947 SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
6948 aResSubSet->length(aSubOrder.size());
6949 TListOfInt::const_iterator subIt = aSubOrder.begin();
6951 for( j = 0; subIt != aSubOrder.end(); subIt++ )
6953 if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
6955 SMESH::SMESH_subMesh_var subMesh =
6956 SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
6959 aPythonDump << ", ";
6960 aPythonDump << subMesh;
6962 aResSubSet[ j++ ] = subMesh;
6965 aPythonDump << " ]";
6967 theResOrder[ listIndx++ ] = aResSubSet;
6969 // correct number of lists
6970 theResOrder.length( listIndx );
6973 // finilise python dump
6974 aPythonDump << " ]";
6975 aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
6979 namespace // utils used by SMESH_MeshPartDS
6982 * \brief Class used to access to protected data of SMDS_MeshInfo
6984 struct TMeshInfo : public SMDS_MeshInfo
6986 void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
6989 * \brief Element holing its ID only
6991 struct TElemID : public SMDS_LinearEdge
6993 TElemID(int ID) : SMDS_LinearEdge(0,0) { setID( ID ); }
6997 //================================================================================
6999 // Implementation of SMESH_MeshPartDS
7001 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
7002 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
7004 SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
7005 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
7008 _meshDS = mesh_i->GetImpl().GetMeshDS();
7010 SetPersistentId( _meshDS->GetPersistentId() );
7012 if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
7014 // <meshPart> is the whole mesh
7015 myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
7017 set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
7018 myGroupSet = _meshDS->GetGroups();
7023 SMESH::long_array_var anIDs = meshPart->GetIDs();
7024 SMESH::array_of_ElementType_var types = meshPart->GetTypes();
7025 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
7027 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7028 if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
7029 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7034 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7035 if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
7036 if ( _elements[ e->GetType() ].insert( e ).second )
7039 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7040 while ( nIt->more() )
7042 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7043 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7050 ShapeToMesh( _meshDS->ShapeToMesh() );
7052 _meshDS = 0; // to enforce iteration on _elements and _nodes
7055 // -------------------------------------------------------------------------------------
7056 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
7057 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
7060 list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
7061 for ( ; partIt != meshPart.end(); ++partIt )
7062 if ( const SMDS_MeshElement * e = *partIt )
7063 if ( _elements[ e->GetType() ].insert( e ).second )
7066 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7067 while ( nIt->more() )
7069 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7070 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7076 // -------------------------------------------------------------------------------------
7077 const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const
7079 if ( _meshDS ) return _meshDS->FindElement( IDelem );
7081 TElemID elem( IDelem );
7082 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7083 if ( !_elements[ iType ].empty() )
7085 TIDSortedElemSet::const_iterator it = _elements[ iType ].find( &elem );
7086 if ( it != _elements[ iType ].end() )
7091 // -------------------------------------------------------------------------------------
7092 bool SMESH_MeshPartDS::HasNumerationHoles()
7094 if ( _meshDS ) return _meshDS->HasNumerationHoles();
7096 return ( MinNodeID() != 1 ||
7097 MaxNodeID() != NbNodes() ||
7098 MinElementID() != 1 ||
7099 MaxElementID() != NbElements() );
7101 // -------------------------------------------------------------------------------------
7102 int SMESH_MeshPartDS::MaxNodeID() const
7104 if ( _meshDS ) return _meshDS->MaxNodeID();
7105 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].rbegin())->GetID();
7107 // -------------------------------------------------------------------------------------
7108 int SMESH_MeshPartDS::MinNodeID() const
7110 if ( _meshDS ) return _meshDS->MinNodeID();
7111 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].begin())->GetID();
7113 // -------------------------------------------------------------------------------------
7114 int SMESH_MeshPartDS::MaxElementID() const
7116 if ( _meshDS ) return _meshDS->MaxElementID();
7118 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7119 if ( !_elements[ iType ].empty() )
7120 maxID = Max( maxID, (*_elements[ iType ].rbegin())->GetID() );
7123 // -------------------------------------------------------------------------------------
7124 int SMESH_MeshPartDS::MinElementID() const
7126 if ( _meshDS ) return _meshDS->MinElementID();
7128 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7129 if ( !_elements[ iType ].empty() )
7130 minID = Min( minID, (*_elements[ iType ].begin())->GetID() );
7133 // -------------------------------------------------------------------------------------
7134 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
7136 if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
7138 typedef SMDS_SetIterator
7139 <const SMDS_MeshElement*,
7140 TIDSortedElemSet::const_iterator,
7141 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7142 SMDS_MeshElement::GeomFilter
7145 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( geomType );
7147 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7148 _elements[type].end(),
7149 SMDS_MeshElement::GeomFilter( geomType )));
7151 // -------------------------------------------------------------------------------------
7152 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
7154 if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
7156 typedef SMDS_SetIterator
7157 <const SMDS_MeshElement*,
7158 TIDSortedElemSet::const_iterator,
7159 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7160 SMDS_MeshElement::EntityFilter
7163 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( entity );
7165 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7166 _elements[type].end(),
7167 SMDS_MeshElement::EntityFilter( entity )));
7169 // -------------------------------------------------------------------------------------
7170 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
7172 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
7173 if ( type == SMDSAbs_All && !_meshDS )
7175 typedef vector< SMDS_ElemIteratorPtr > TIterVec;
7177 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
7178 if ( !_elements[i].empty() && i != SMDSAbs_Node )
7180 ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
7182 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
7183 return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
7185 return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
7186 ( new TIter( _elements[type].begin(), _elements[type].end() ));
7188 // -------------------------------------------------------------------------------------
7189 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType) \
7190 iterType SMESH_MeshPartDS::methName() const \
7192 typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
7193 return _meshDS ? _meshDS->methName() : iterType \
7194 ( new TIter( _elements[elemType].begin(), _elements[elemType].end() )); \
7196 // -------------------------------------------------------------------------------------
7197 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
7198 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
7199 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
7200 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
7201 #undef _GET_ITER_DEFINE
7203 // END Implementation of SMESH_MeshPartDS
7205 //================================================================================