1 // Copyright (C) 2007-2021 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 and TooLargeForExport exception through SMESH_TRY
88 #define SMY_OWN_CATCH \
89 catch( SALOME::SALOME_Exception& se ) { throw se; } \
90 catch( ::SMESH_Mesh::TooLargeForExport& ex ) \
91 { SALOME::ExceptionStruct se = { \
93 CORBA::string_dup(SMESH_Comment("Mesh is too large for export in format ") << ex.what()), \
94 CORBA::string_dup(SMESH_Comment("format=") << ex.what() ), 0 }; \
95 throw SALOME::SALOME_Exception( se ); }
97 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
100 static int MYDEBUG = 0;
102 static int MYDEBUG = 0;
106 using SMESH::TPythonDump;
109 int SMESH_Mesh_i::_idGenerator = 0;
111 //=============================================================================
115 //=============================================================================
117 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
119 : SALOME::GenericObj_i( thePOA )
123 _id = _idGenerator++;
126 _previewEditor = NULL;
131 //=============================================================================
135 //=============================================================================
137 SMESH_Mesh_i::~SMESH_Mesh_i()
140 map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
141 for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
142 if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
144 aGroup->UnRegister();
145 SMESH::SMESH_GroupBase_var( itGr->second );
150 map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
151 for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
152 if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
154 aSubMesh->UnRegister();
155 SMESH::SMESH_subMesh_var( itSM->second );
157 _mapSubMeshIor.clear();
159 // destroy hypotheses. _mapHypo contains all hyps ever been assigned
160 map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
161 for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
162 if ( SMESH_Hypothesis_i* hyp_i = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
163 if ( SMESH_Hypothesis * smHyp = _impl->GetHypothesis( itH->first ))
164 if ( _impl->GetMeshDS()->IsUsedHypothesis( smHyp ))
167 SMESH::SMESH_Hypothesis_var( itH->second ); // decref CORBA object
171 // clear cached shapes if no more meshes remain; (the cache is blame,
172 // together with publishing, of spent time increasing in issue 22874)
173 if ( _impl->NbMeshes() == 1 )
174 _gen_i->GetShapeReader()->ClearClientBuffer();
176 delete _editor; _editor = NULL;
177 delete _previewEditor; _previewEditor = NULL;
178 delete _impl; _impl = NULL;
179 delete _preMeshInfo; _preMeshInfo = NULL;
182 //=============================================================================
186 * Associate <this> mesh with <theShape> and put a reference
187 * to <theShape> into the current study;
188 * the previous shape is substituted by the new one.
190 //=============================================================================
192 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
194 Unexpect aCatch(SALOME_SalomeException);
196 _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
198 catch(SALOME_Exception & S_ex) {
199 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
201 // to track changes of GEOM groups
202 SMESH::SMESH_Mesh_var mesh = _this();
203 addGeomGroupData( theShapeObject, mesh );
204 if ( !CORBA::is_nil( theShapeObject ))
205 _mainShapeTick = theShapeObject->GetTick();
208 //================================================================================
210 * \brief Return true if mesh has a shape to build a shape on
212 //================================================================================
214 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
216 Unexpect aCatch(SALOME_SalomeException);
219 res = _impl->HasShapeToMesh();
221 catch(SALOME_Exception & S_ex) {
222 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
227 //================================================================================
229 * \brief Return the shape to mesh
231 //================================================================================
233 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
235 Unexpect aCatch(SALOME_SalomeException);
236 GEOM::GEOM_Object_var aShapeObj;
238 TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
241 aShapeObj = _gen_i->ShapeToGeomObject( S );
242 if ( aShapeObj->_is_nil() )
244 // S was removed from GEOM_Client by newGroupShape() called by other mesh;
245 // find GEOM_Object by entry (IPAL52735)
246 list<TGeomGroupData>::iterator data = _geomGroupData.begin();
247 for ( ; data != _geomGroupData.end(); ++data )
248 if ( data->_smeshObject->_is_equivalent( _this() ))
250 SALOMEDS::SObject_wrap so = _gen_i->getStudyServant()->FindObjectID( data->_groupEntry.c_str() );
251 CORBA::Object_var obj = _gen_i->SObjectToObject( so );
252 aShapeObj = GEOM::GEOM_Object::_narrow( obj );
258 catch(SALOME_Exception & S_ex) {
259 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
261 return aShapeObj._retn();
264 //================================================================================
266 * \brief Return false if the mesh is not yet fully loaded from the study file
268 //================================================================================
270 CORBA::Boolean SMESH_Mesh_i::IsLoaded()
272 Unexpect aCatch(SALOME_SalomeException);
273 return !_preMeshInfo;
276 //================================================================================
278 * \brief Load full mesh data from the study file
280 //================================================================================
282 void SMESH_Mesh_i::Load()
284 Unexpect aCatch(SALOME_SalomeException);
286 _preMeshInfo->FullLoadFromFile();
289 //================================================================================
291 * \brief Remove all nodes and elements
293 //================================================================================
295 void SMESH_Mesh_i::Clear()
297 Unexpect aCatch(SALOME_SalomeException);
299 _preMeshInfo->ForgetOrLoad(); // load in case if !HasShapeToMesh()
303 //CheckGeomGroupModif(); // issue 20145
305 catch(SALOME_Exception & S_ex) {
306 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
309 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".Clear()";
311 SMESH::SMESH_Mesh_var mesh = _this();
312 _gen_i->UpdateIcons( mesh );
315 //================================================================================
317 * \brief Remove all nodes and elements for indicated shape
319 //================================================================================
321 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
323 Unexpect aCatch(SALOME_SalomeException);
325 _preMeshInfo->FullLoadFromFile();
328 _impl->ClearSubMesh( ShapeID );
330 catch(SALOME_Exception & S_ex) {
331 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
333 _impl->GetMeshDS()->Modified();
335 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ClearSubMesh( " << ShapeID << " )";
338 //=============================================================================
340 * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
342 //=============================================================================
344 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
346 SMESH::DriverMED_ReadStatus res;
349 case DriverMED_R_SMESHDS_Mesh::DRS_OK:
350 res = SMESH::DRS_OK; break;
351 case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
352 res = SMESH::DRS_EMPTY; break;
353 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
354 res = SMESH::DRS_WARN_RENUMBER; break;
355 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
356 res = SMESH::DRS_WARN_SKIP_ELEM; break;
357 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_DESCENDING:
358 res = SMESH::DRS_WARN_DESCENDING; break;
359 case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
361 res = SMESH::DRS_FAIL; break;
366 //=============================================================================
368 * Convert ::SMESH_ComputeError to SMESH::ComputeError
370 //=============================================================================
372 static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr )
374 SMESH::ComputeError_var errVar = new SMESH::ComputeError();
375 errVar->subShapeID = -1;
376 errVar->hasBadMesh = false;
378 if ( !errorPtr || errorPtr->IsOK() )
380 errVar->code = SMESH::COMPERR_OK;
384 errVar->code = ConvertDriverMEDReadStatus( errorPtr->myName );
385 errVar->comment = errorPtr->myComment.c_str();
387 return errVar._retn();
390 //=============================================================================
394 * Import mesh data from MED file
396 //=============================================================================
398 SMESH::DriverMED_ReadStatus
399 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
401 Unexpect aCatch(SALOME_SalomeException);
404 status = _impl->MEDToMesh( theFileName, theMeshName );
406 catch( SALOME_Exception& S_ex ) {
407 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
410 THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
413 CreateGroupServants();
415 int major, minor, release;
416 major = minor = release = 0;
417 MED::GetMEDVersion(theFileName, major, minor, release);
418 _medFileInfo = new SMESH::MedFileInfo();
419 _medFileInfo->fileName = theFileName;
420 _medFileInfo->fileSize = 0;
421 _medFileInfo->major = major;
422 _medFileInfo->minor = minor;
423 _medFileInfo->release = release;
424 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
426 return ConvertDriverMEDReadStatus(status);
429 //================================================================================
431 * \brief Import mesh data from the CGNS file
433 //================================================================================
435 SMESH::DriverMED_ReadStatus SMESH_Mesh_i::ImportCGNSFile( const char* theFileName,
436 const int theMeshIndex,
437 std::string& theMeshName )
439 Unexpect aCatch(SALOME_SalomeException);
442 status = _impl->CGNSToMesh( theFileName, theMeshIndex, theMeshName );
444 catch( SALOME_Exception& S_ex ) {
445 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
448 THROW_SALOME_CORBA_EXCEPTION("ImportCGNSFile(): unknown exception", SALOME::BAD_PARAM);
451 CreateGroupServants();
453 _medFileInfo = new SMESH::MedFileInfo();
454 _medFileInfo->fileName = theFileName;
455 _medFileInfo->major = 0;
456 _medFileInfo->minor = 0;
457 _medFileInfo->release = 0;
458 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
460 return ConvertDriverMEDReadStatus(status);
463 //================================================================================
465 * \brief Return string representation of a MED file version comprising nbDigits
467 //================================================================================
469 char* SMESH_Mesh_i::GetVersionString(CORBA::Long minor, CORBA::Short nbDigits)
471 string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(minor, nbDigits);
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 )
505 // Read mesh with name = <theMeshName> into SMESH_Mesh
506 _impl->UNVToMesh( theFileName );
508 CreateGroupServants();
510 _medFileInfo = new SMESH::MedFileInfo();
511 _medFileInfo->fileName = theFileName;
512 _medFileInfo->major = 0;
513 _medFileInfo->minor = 0;
514 _medFileInfo->release = 0;
515 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
517 SMESH_CATCH( SMESH::throwCorbaException );
522 //=============================================================================
526 * Import mesh data from STL file
528 //=============================================================================
530 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
534 // Read mesh with name = <theMeshName> into SMESH_Mesh
535 std::string name = _impl->STLToMesh( theFileName );
538 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( _this() );
539 _gen_i->SetName( meshSO, name.c_str() );
541 _medFileInfo = new SMESH::MedFileInfo();
542 _medFileInfo->fileName = theFileName;
543 _medFileInfo->major = 0;
544 _medFileInfo->minor = 0;
545 _medFileInfo->release = 0;
546 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
548 SMESH_CATCH( SMESH::throwCorbaException );
553 //================================================================================
555 * \brief Function used in SMESH_CATCH by ImportGMFFile()
557 //================================================================================
561 SMESH_ComputeErrorPtr exceptionToComputeError(const char* excText)
563 return SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, excText );
567 //================================================================================
569 * \brief Import data from a GMF file and return an error description
571 //================================================================================
573 SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName,
574 bool theMakeRequiredGroups )
576 SMESH_ComputeErrorPtr error;
579 #define SMESH_CAUGHT error =
582 error = _impl->GMFToMesh( theFileName, theMakeRequiredGroups );
584 _medFileInfo = new SMESH::MedFileInfo();
585 _medFileInfo->fileName = theFileName;
586 _medFileInfo->major = 0;
587 _medFileInfo->minor = 0;
588 _medFileInfo->release = 0;
589 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
591 SMESH_CATCH( exceptionToComputeError );
595 CreateGroupServants();
597 return ConvertComputeError( error );
600 //=============================================================================
602 * \brief Convert SMESH_Hypothesis::Hypothesis_Status into SMESH::Hypothesis_Status
604 //=============================================================================
606 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
608 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
609 (SMESH_Hypothesis::Hypothesis_Status theStatus)
612 RETURNCASE( HYP_OK );
613 RETURNCASE( HYP_MISSING );
614 RETURNCASE( HYP_CONCURRENT );
615 RETURNCASE( HYP_BAD_PARAMETER );
616 RETURNCASE( HYP_HIDDEN_ALGO );
617 RETURNCASE( HYP_HIDING_ALGO );
618 RETURNCASE( HYP_UNKNOWN_FATAL );
619 RETURNCASE( HYP_INCOMPATIBLE );
620 RETURNCASE( HYP_NOTCONFORM );
621 RETURNCASE( HYP_ALREADY_EXIST );
622 RETURNCASE( HYP_BAD_DIM );
623 RETURNCASE( HYP_BAD_SUBSHAPE );
624 RETURNCASE( HYP_BAD_GEOMETRY );
625 RETURNCASE( HYP_NEED_SHAPE );
626 RETURNCASE( HYP_INCOMPAT_HYPS );
629 return SMESH::HYP_UNKNOWN_FATAL;
632 //=============================================================================
636 * Call internal addHypothesis() and then add a reference to <anHyp> under
637 * the SObject actually having a reference to <aSubShape>.
638 * NB: For this method to work, it is necessary to add a reference to sub-shape first.
640 //=============================================================================
642 SMESH::Hypothesis_Status
643 SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShape,
644 SMESH::SMESH_Hypothesis_ptr anHyp,
645 CORBA::String_out anErrorText)
647 Unexpect aCatch(SALOME_SalomeException);
649 const smIdType prevNbMeshEnt = NbNodes() + NbElements();
652 _preMeshInfo->ForgetOrLoad();
655 SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
656 anErrorText = error.c_str();
658 SMESH::SMESH_Mesh_var mesh( _this() );
659 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
661 _gen_i->AddHypothesisToShape( mesh, aSubShape, anHyp );
663 //int newNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements();
664 if ( prevNbMeshEnt > 0 /*newNbMeshEnt != prevNbMeshEnt*/ )
665 _gen_i->UpdateIcons( mesh );
667 if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
669 // Update Python script
670 TPythonDump() << "status = " << mesh << ".AddHypothesis( "
671 << aSubShape << ", " << anHyp << " )";
673 return ConvertHypothesisStatus(status);
676 //================================================================================
678 * \brief Create a sub-mesh and add a hypothesis to it
680 //================================================================================
682 SMESH_Hypothesis::Hypothesis_Status
683 SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShape,
684 SMESH::SMESH_Hypothesis_ptr anHyp,
685 std::string* anErrorText)
687 if(MYDEBUG) MESSAGE("addHypothesis");
689 if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
690 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
692 if (CORBA::is_nil( anHyp ))
693 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",SALOME::BAD_PARAM);
695 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
698 TopoDS_Shape myLocSubShape;
699 //use PseudoShape in case if mesh has no shape
701 myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
703 myLocSubShape = _impl->GetShapeToMesh();
705 const int hypId = anHyp->GetId();
707 status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
708 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
710 _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
712 // assure there is a corresponding submesh
713 if ( !_impl->IsMainShape( myLocSubShape )) {
714 int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
715 if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
716 SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
719 else if ( anErrorText )
721 *anErrorText = error;
724 catch(SALOME_Exception & S_ex)
726 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
731 //================================================================================
733 * \brief Un-assign a hypothesis from a sub-mesh dedicate to the given sub-shape
735 //================================================================================
737 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
738 SMESH::SMESH_Hypothesis_ptr anHyp)
740 Unexpect aCatch(SALOME_SalomeException);
742 _preMeshInfo->ForgetOrLoad();
744 SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
745 SMESH::SMESH_Mesh_var mesh = _this();
747 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
749 _gen_i->RemoveHypothesisFromShape( mesh, aSubShape, anHyp );
750 _gen_i->UpdateIcons( mesh );
752 // Update Python script
753 if(_impl->HasShapeToMesh())
754 TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
755 << aSubShape << ", " << anHyp << " )";
757 TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
760 return ConvertHypothesisStatus(status);
763 //=============================================================================
765 * \brief Un-assign a hypothesis from a sub-mesh dedicate to the given sub-shape
767 //=============================================================================
769 SMESH_Hypothesis::Hypothesis_Status
770 SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShape,
771 SMESH::SMESH_Hypothesis_ptr anHyp)
773 if(MYDEBUG) MESSAGE("removeHypothesis()");
775 if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
776 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
778 if (CORBA::is_nil( anHyp ))
779 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
782 _preMeshInfo->ForgetOrLoad();
784 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
787 TopoDS_Shape myLocSubShape;
788 //use PseudoShape in case if mesh has no shape
789 if( _impl->HasShapeToMesh() )
790 myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
792 myLocSubShape = _impl->GetShapeToMesh();
794 const int hypId = anHyp->GetId();
795 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
796 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
798 // _mapHypo.erase( hypId ); EAP: hyp can be used on many sub-shapes
802 catch(SALOME_Exception & S_ex)
804 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
809 //================================================================================
811 * \brief Return hypotheses assigned to a given sub-shape
813 //================================================================================
815 SMESH::ListOfHypothesis *
816 SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
818 Unexpect aCatch(SALOME_SalomeException);
819 if (MYDEBUG) MESSAGE("GetHypothesisList");
820 if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
821 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
823 SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
826 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
827 if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
828 myLocSubShape = _impl->GetShapeToMesh();
829 const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
830 int i = 0, n = aLocalList.size();
833 list<const SMESHDS_Hypothesis*>::const_iterator aHyp = aLocalList.begin();
834 std::map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id_hypptr;
835 for ( ; i < n && aHyp != aLocalList.end(); aHyp++ )
837 id_hypptr = _mapHypo.find( (*aHyp)->GetID() );
838 if ( id_hypptr != _mapHypo.end() )
839 aList[i++] = SMESH::SMESH_Hypothesis::_narrow( id_hypptr->second );
843 catch(SALOME_Exception & S_ex) {
844 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
847 return aList._retn();
850 //================================================================================
852 * \brief Return sub-meshes
854 //================================================================================
856 SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes()
858 Unexpect aCatch(SALOME_SalomeException);
859 if (MYDEBUG) MESSAGE("GetSubMeshes");
861 SMESH::submesh_array_var aList = new SMESH::submesh_array();
864 TPythonDump aPythonDump;
865 if ( !_mapSubMeshIor.empty() )
869 aList->length( _mapSubMeshIor.size() );
871 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.begin();
872 for ( ; it != _mapSubMeshIor.end(); it++ ) {
873 if ( CORBA::is_nil( it->second )) continue;
874 aList[i++] = SMESH::SMESH_subMesh::_duplicate( it->second );
876 if (i > 1) aPythonDump << ", ";
877 aPythonDump << it->second;
881 catch(SALOME_Exception & S_ex) {
882 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
885 // Update Python script
886 if ( !_mapSubMeshIor.empty() )
887 aPythonDump << " ] = " << SMESH::SMESH_Mesh_var( _this() ) << ".GetSubMeshes()";
889 return aList._retn();
892 //================================================================================
894 * \brief Create and return a sub-mesh on the given sub-shape
896 //================================================================================
898 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
899 const char* theName )
901 Unexpect aCatch(SALOME_SalomeException);
902 if (CORBA::is_nil(aSubShape))
903 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
905 SMESH::SMESH_subMesh_var subMesh;
906 SMESH::SMESH_Mesh_var aMesh = _this();
908 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
910 //Get or Create the SMESH_subMesh object implementation
912 TopoDS_Iterator it( myLocSubShape );
913 int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
914 bool isValidSub = ( subMeshId || _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape ));
915 if ( isValidSub && myLocSubShape.ShapeType() == TopAbs_COMPOUND )
916 isValidSub = !it.Value().IsSame( _impl->GetShapeToMesh() );
920 THROW_SALOME_CORBA_EXCEPTION("Not a sub-shape of the main shape", SALOME::BAD_PARAM);
922 subMesh = getSubMesh( subMeshId );
924 // create a new subMesh object servant if there is none for the shape
925 if ( subMesh->_is_nil() )
926 subMesh = createSubMesh( aSubShape );
927 if ( _gen_i->CanPublishInStudy( subMesh ))
929 SALOMEDS::SObject_wrap aSO =
930 _gen_i->PublishSubMesh( aMesh, subMesh, aSubShape, theName );
931 if ( !aSO->_is_nil()) {
932 // Update Python script
933 TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
934 << aSubShape << ", '" << theName << "' )";
938 catch(SALOME_Exception & S_ex) {
939 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
941 return subMesh._retn();
944 //================================================================================
946 * \brief Remove a sub-mesh
948 //================================================================================
950 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
954 if ( theSubMesh->_is_nil() )
957 GEOM::GEOM_Object_var aSubShape;
958 // Remove submesh's SObject
959 SALOMEDS::SObject_wrap anSO = _gen_i->ObjectToSObject( theSubMesh );
960 if ( !anSO->_is_nil() ) {
961 long aTag = SMESH_Gen_i::GetRefOnShapeTag();
962 SALOMEDS::SObject_wrap anObj, aRef;
963 if ( anSO->FindSubObject( aTag, anObj.inout() ) &&
964 anObj->ReferencedObject( aRef.inout() ))
966 CORBA::Object_var obj = aRef->GetObject();
967 aSubShape = GEOM::GEOM_Object::_narrow( obj );
969 // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
970 // aSubShape = theSubMesh->GetSubShape();
972 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
973 builder->RemoveObjectWithChildren( anSO );
975 // Update Python script
976 TPythonDump() << SMESH::SMESH_Mesh_var( _this() ) << ".RemoveSubMesh( " << anSO << " )";
979 if ( removeSubMesh( theSubMesh, aSubShape.in() ))
981 _preMeshInfo->ForgetOrLoad();
983 SMESH_CATCH( SMESH::throwCorbaException );
986 //================================================================================
988 * \brief Create a standalone group
990 //================================================================================
992 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
993 const char* theName )
995 Unexpect aCatch(SALOME_SalomeException);
997 _preMeshInfo->FullLoadFromFile();
999 SMESH::SMESH_Group_var aNewGroup =
1000 SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
1002 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1004 SMESH::SMESH_Mesh_var mesh = _this();
1005 SALOMEDS::SObject_wrap aSO =
1006 _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName);
1007 if ( !aSO->_is_nil())
1008 // Update Python script
1009 TPythonDump() << aSO << " = " << mesh << ".CreateGroup( "
1010 << theElemType << ", '" << theName << "' )";
1012 return aNewGroup._retn();
1015 //================================================================================
1017 * \brief Create a group based on the given geometry
1019 //================================================================================
1021 SMESH::SMESH_GroupOnGeom_ptr
1022 SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType theElemType,
1023 const char* theName,
1024 GEOM::GEOM_Object_ptr theGeomObj)
1026 Unexpect aCatch(SALOME_SalomeException);
1028 _preMeshInfo->FullLoadFromFile();
1030 SMESH::SMESH_GroupOnGeom_var aNewGroup;
1032 TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
1033 if ( !aShape.IsNull() )
1036 SMESH::SMESH_GroupOnGeom::_narrow( createGroup( theElemType, theName, /*id=*/-1, aShape ));
1038 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1040 SMESH::SMESH_Mesh_var mesh = _this();
1041 SALOMEDS::SObject_wrap aSO =
1042 _gen_i->PublishGroup( mesh, aNewGroup, theGeomObj, theName );
1043 if ( !aSO->_is_nil())
1044 TPythonDump() << aSO << " = " << mesh << ".CreateGroupFromGEOM( "
1045 << theElemType << ", '" << theName << "', " << theGeomObj << " )";
1049 return aNewGroup._retn();
1052 //================================================================================
1054 * \brief Creates a group whose contents is defined by filter
1055 * \param theElemType - group type
1056 * \param theName - group name
1057 * \param theFilter - the filter
1058 * \retval SMESH::SMESH_GroupOnFilter_ptr - group defined by filter
1060 //================================================================================
1062 SMESH::SMESH_GroupOnFilter_ptr
1063 SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
1064 const char* theName,
1065 SMESH::Filter_ptr theFilter )
1067 Unexpect aCatch(SALOME_SalomeException);
1069 _preMeshInfo->FullLoadFromFile();
1071 if ( CORBA::is_nil( theFilter ))
1072 THROW_SALOME_CORBA_EXCEPTION("NULL filter", SALOME::BAD_PARAM);
1074 SMESH_PredicatePtr predicate = SMESH_GroupOnFilter_i::GetPredicate( theFilter );
1076 THROW_SALOME_CORBA_EXCEPTION("Invalid filter", SALOME::BAD_PARAM);
1078 SMESH::SMESH_GroupOnFilter_var aNewGroup = SMESH::SMESH_GroupOnFilter::_narrow
1079 ( createGroup( theElemType, theName, /*id=*/-1, TopoDS_Shape(), predicate ));
1082 if ( !aNewGroup->_is_nil() )
1083 aNewGroup->SetFilter( theFilter );
1085 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1087 SMESH::SMESH_Mesh_var mesh = _this();
1088 SALOMEDS::SObject_wrap aSO =
1089 _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName );
1091 if ( !aSO->_is_nil())
1092 pd << aSO << " = " << mesh << ".CreateGroupFromFilter( "
1093 << theElemType << ", '" << theName << "', " << theFilter << " )";
1095 return aNewGroup._retn();
1098 //================================================================================
1100 * \brief Remove a group
1102 //================================================================================
1104 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
1106 if ( theGroup->_is_nil() )
1111 SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
1115 if ( aGroup->GetMeshServant() != this )
1116 THROW_SALOME_CORBA_EXCEPTION( "RemoveGroup(): group does not belong to this mesh",
1117 SALOME::BAD_PARAM );
1119 SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( theGroup );
1120 if ( !aGroupSO->_is_nil() )
1122 // Update Python script
1123 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroup( " << aGroupSO << " )";
1125 // Remove group's SObject
1126 SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->NewBuilder();
1127 builder->RemoveObjectWithChildren( aGroupSO );
1129 aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
1131 // Remove the group from SMESH data structures
1132 removeGroup( aGroup->GetLocalID() );
1134 SMESH_CATCH( SMESH::throwCorbaException );
1137 //=============================================================================
1139 * Remove group with its contents
1141 //=============================================================================
1143 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
1147 _preMeshInfo->FullLoadFromFile();
1149 if ( theGroup->_is_nil() )
1152 SMESH_GroupBase_i* groupImpl = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup );
1153 if ( !groupImpl || groupImpl->GetMeshServant() != this )
1154 THROW_SALOME_CORBA_EXCEPTION( "RemoveGroupWithContents(): group does not belong to this mesh",
1157 vector<smIdType> nodeIds; // to remove nodes becoming free
1158 bool isNodal = ( theGroup->GetType() == SMESH::NODE );
1159 if ( !isNodal && !theGroup->IsEmpty() )
1161 SMESH::smIdType elemID = theGroup->GetID( 1 );
1162 int nbElemNodes = GetElemNbNodes( elemID );
1163 if ( nbElemNodes > 0 )
1164 nodeIds.reserve( theGroup->Size() * nbElemNodes );
1167 // Retrieve contents
1168 SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );
1169 SMDS_ElemIteratorPtr elemIt = GetElements( idSrc, theGroup->GetType() );
1170 SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > elemBeg( elemIt ), elemEnd;
1171 std::vector< const SMDS_MeshElement* > elems( theGroup->Size() );
1172 elems.assign( elemBeg, elemEnd );
1174 TPythonDump pyDump; // Suppress dump from RemoveGroup()
1177 RemoveGroup( theGroup );
1180 for ( size_t i = 0; i < elems.size(); ++i )
1182 // if ( !_impl->GetMeshDS()->Contains( elems[i] ))
1186 for ( SMDS_ElemIteratorPtr nIt = elems[i]->nodesIterator(); nIt->more(); )
1187 nodeIds.push_back( nIt->next()->GetID() );
1189 _impl->GetMeshDS()->RemoveFreeElement( elems[i], /*sm=*/0 );
1193 _impl->GetMeshDS()->RemoveElement( elems[i] );
1197 // Remove free nodes
1198 for ( size_t i = 0 ; i < nodeIds.size(); ++i )
1199 if ( const SMDS_MeshNode* n = _impl->GetMeshDS()->FindNode( nodeIds[i] ))
1200 if ( n->NbInverseElements() == 0 )
1201 _impl->GetMeshDS()->RemoveFreeNode( n, /*sm=*/0 );
1203 _impl->GetMeshDS()->Modified();
1204 _impl->SetIsModified( true );
1206 // Update Python script (theGroup must be alive for this)
1207 pyDump << SMESH::SMESH_Mesh_var(_this())
1208 << ".RemoveGroupWithContents( " << theGroup << " )";
1210 SMESH_CATCH( SMESH::throwCorbaException );
1213 //================================================================================
1215 * \brief Get the list of groups existing in the mesh
1216 * \retval SMESH::ListOfGroups * - list of groups
1218 //================================================================================
1220 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups()
1222 Unexpect aCatch(SALOME_SalomeException);
1223 if (MYDEBUG) MESSAGE("GetGroups");
1225 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
1228 TPythonDump aPythonDump;
1229 if ( !_mapGroups.empty() )
1231 aPythonDump << "[ ";
1233 aList->length( _mapGroups.size() );
1235 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
1236 for ( ; it != _mapGroups.end(); it++ ) {
1237 if ( CORBA::is_nil( it->second )) continue;
1238 aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
1240 if (i > 1) aPythonDump << ", ";
1241 aPythonDump << it->second;
1245 catch(SALOME_Exception & S_ex) {
1246 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1248 aPythonDump << " ] = " << SMESH::SMESH_Mesh_var(_this()) << ".GetGroups()";
1250 return aList._retn();
1253 //=============================================================================
1255 * Get number of groups existing in the mesh
1257 //=============================================================================
1259 CORBA::Long SMESH_Mesh_i::NbGroups()
1261 Unexpect aCatch(SALOME_SalomeException);
1262 return _mapGroups.size();
1265 //=============================================================================
1267 * New group including all mesh elements present in initial groups is created.
1269 //=============================================================================
1271 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1272 SMESH::SMESH_GroupBase_ptr theGroup2,
1273 const char* theName )
1275 SMESH::SMESH_Group_var aResGrp;
1279 _preMeshInfo->FullLoadFromFile();
1281 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1282 THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): NULL Group",
1284 if ( theGroup1->GetType() != theGroup2->GetType() )
1285 THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): different group types",
1290 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1291 if ( aResGrp->_is_nil() )
1292 return SMESH::SMESH_Group::_nil();
1294 aResGrp->AddFrom( theGroup1 );
1295 aResGrp->AddFrom( theGroup2 );
1297 // Update Python script
1298 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this())
1299 << ".UnionGroups( " << theGroup1 << ", " << theGroup2 << ", '" << theName << "' )";
1301 SMESH_CATCH( SMESH::throwCorbaException );
1303 return aResGrp._retn();
1306 //=============================================================================
1308 * \brief New group including all mesh elements present in initial groups is created.
1309 * \param theGroups list of groups
1310 * \param theName name of group to be created
1311 * \return pointer to the new group
1313 //=============================================================================
1315 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
1316 const char* theName )
1318 SMESH::SMESH_Group_var aResGrp;
1321 _preMeshInfo->FullLoadFromFile();
1324 return SMESH::SMESH_Group::_nil();
1329 SMESH::ElementType aType = SMESH::ALL;
1330 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1332 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1333 if ( CORBA::is_nil( aGrp ) )
1335 if ( aType == SMESH::ALL )
1336 aType = aGrp->GetType();
1337 else if ( aType != aGrp->GetType() )
1338 THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1341 if ( aType == SMESH::ALL )
1342 return SMESH::SMESH_Group::_nil();
1347 aResGrp = CreateGroup( aType, theName );
1348 if ( aResGrp->_is_nil() )
1349 return SMESH::SMESH_Group::_nil();
1351 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".UnionListOfGroups([ ";
1352 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1354 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1355 if ( !CORBA::is_nil( aGrp ) )
1357 aResGrp->AddFrom( aGrp );
1358 if ( g > 0 ) pyDump << ", ";
1362 pyDump << " ], '" << theName << "' )";
1364 SMESH_CATCH( SMESH::throwCorbaException );
1366 return aResGrp._retn();
1369 //=============================================================================
1371 * New group is created. All mesh elements that are
1372 * present in both initial groups are added to the new one.
1374 //=============================================================================
1376 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1377 SMESH::SMESH_GroupBase_ptr theGroup2,
1378 const char* theName )
1380 SMESH::SMESH_Group_var aResGrp;
1385 _preMeshInfo->FullLoadFromFile();
1387 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1388 THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): NULL Group",
1390 if ( theGroup1->GetType() != theGroup2->GetType() )
1391 THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): different group types",
1395 // Create Intersection
1396 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1397 if ( aResGrp->_is_nil() )
1398 return aResGrp._retn();
1400 SMESHDS_GroupBase* groupDS1 = 0;
1401 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1402 groupDS1 = grp_i->GetGroupDS();
1404 SMESHDS_GroupBase* groupDS2 = 0;
1405 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1406 groupDS2 = grp_i->GetGroupDS();
1408 SMESHDS_Group* resGroupDS = 0;
1409 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1410 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1412 if ( groupDS1 && groupDS2 && resGroupDS && !groupDS2->IsEmpty() )
1414 SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1415 while ( elemIt1->more() )
1417 const SMDS_MeshElement* e = elemIt1->next();
1418 if ( groupDS2->Contains( e ))
1419 resGroupDS->SMDSGroup().Add( e );
1422 // Update Python script
1423 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".IntersectGroups( "
1424 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1426 SMESH_CATCH( SMESH::throwCorbaException );
1428 return aResGrp._retn();
1431 //=============================================================================
1433 \brief Intersect list of groups. New group is created. All mesh elements that
1434 are present in all initial groups simultaneously are added to the new one.
1435 \param theGroups list of groups
1436 \param theName name of group to be created
1437 \return pointer on the group
1439 //=============================================================================
1441 SMESH::SMESH_Group_ptr
1442 SMESH_Mesh_i::IntersectListOfGroups(const SMESH::ListOfGroups& theGroups,
1443 const char* theName )
1445 SMESH::SMESH_Group_var aResGrp;
1450 _preMeshInfo->FullLoadFromFile();
1453 return SMESH::SMESH_Group::_nil();
1455 // check types and get SMESHDS_GroupBase's
1456 SMESH::ElementType aType = SMESH::ALL;
1457 vector< SMESHDS_GroupBase* > groupVec;
1458 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1460 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1461 if ( CORBA::is_nil( aGrp ) )
1463 if ( aType == SMESH::ALL )
1464 aType = aGrp->GetType();
1465 else if ( aType != aGrp->GetType() )
1466 THROW_SALOME_CORBA_EXCEPTION("IntersectListOfGroups(): different group types",
1469 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1470 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1472 if ( grpDS->IsEmpty() )
1477 groupVec.push_back( grpDS );
1480 if ( aType == SMESH::ALL ) // all groups are nil
1481 return SMESH::SMESH_Group::_nil();
1486 aResGrp = CreateGroup( aType, theName );
1488 SMESHDS_Group* resGroupDS = 0;
1489 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1490 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1491 if ( !resGroupDS || groupVec.empty() )
1492 return aResGrp._retn();
1495 size_t i, nb = groupVec.size();
1496 SMDS_ElemIteratorPtr elemIt1 = groupVec[0]->GetElements();
1497 while ( elemIt1->more() )
1499 const SMDS_MeshElement* e = elemIt1->next();
1501 for ( i = 1; ( i < nb && inAll ); ++i )
1502 inAll = groupVec[i]->Contains( e );
1505 resGroupDS->SMDSGroup().Add( e );
1508 // Update Python script
1509 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1510 << ".IntersectListOfGroups( " << theGroups << ", '" << theName << "' )";
1512 SMESH_CATCH( SMESH::throwCorbaException );
1514 return aResGrp._retn();
1517 //=============================================================================
1519 * New group is created. All mesh elements that are present in
1520 * a main group but is not present in a tool group are added to the new one
1522 //=============================================================================
1524 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1525 SMESH::SMESH_GroupBase_ptr theGroup2,
1526 const char* theName )
1528 SMESH::SMESH_Group_var aResGrp;
1533 _preMeshInfo->FullLoadFromFile();
1535 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1536 THROW_SALOME_CORBA_EXCEPTION("CutGroups(): NULL Group",
1538 if ( theGroup1->GetType() != theGroup2->GetType() )
1539 THROW_SALOME_CORBA_EXCEPTION("CutGroups(): different group types",
1543 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1544 if ( aResGrp->_is_nil() )
1545 return aResGrp._retn();
1547 SMESHDS_GroupBase* groupDS1 = 0;
1548 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1549 groupDS1 = grp_i->GetGroupDS();
1551 SMESHDS_GroupBase* groupDS2 = 0;
1552 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1553 groupDS2 = grp_i->GetGroupDS();
1555 SMESHDS_Group* resGroupDS = 0;
1556 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1557 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1559 if ( groupDS1 && groupDS2 && resGroupDS )
1561 SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1562 while ( elemIt1->more() )
1564 const SMDS_MeshElement* e = elemIt1->next();
1565 if ( !groupDS2->Contains( e ))
1566 resGroupDS->SMDSGroup().Add( e );
1569 // Update Python script
1570 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".CutGroups( "
1571 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1573 SMESH_CATCH( SMESH::throwCorbaException );
1575 return aResGrp._retn();
1578 //=============================================================================
1580 \brief Cut lists of groups. New group is created. All mesh elements that are
1581 present in main groups but do not present in tool groups are added to the new one
1582 \param theMainGroups list of main groups
1583 \param theToolGroups list of tool groups
1584 \param theName name of group to be created
1585 \return pointer on the group
1587 //=============================================================================
1589 SMESH::SMESH_Group_ptr
1590 SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
1591 const SMESH::ListOfGroups& theToolGroups,
1592 const char* theName )
1594 SMESH::SMESH_Group_var aResGrp;
1599 _preMeshInfo->FullLoadFromFile();
1602 return SMESH::SMESH_Group::_nil();
1604 // check types and get SMESHDS_GroupBase's
1605 SMESH::ElementType aType = SMESH::ALL;
1606 vector< SMESHDS_GroupBase* > toolGroupVec;
1607 vector< SMDS_ElemIteratorPtr > mainIterVec;
1609 for ( int g = 0, n = theMainGroups.length(); g < n; g++ )
1611 SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1612 if ( CORBA::is_nil( aGrp ) )
1614 if ( aType == SMESH::ALL )
1615 aType = aGrp->GetType();
1616 else if ( aType != aGrp->GetType() )
1617 THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1619 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1620 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1621 if ( !grpDS->IsEmpty() )
1622 mainIterVec.push_back( grpDS->GetElements() );
1624 if ( aType == SMESH::ALL ) // all main groups are nil
1625 return SMESH::SMESH_Group::_nil();
1626 if ( mainIterVec.empty() ) // all main groups are empty
1627 return aResGrp._retn();
1629 for ( int g = 0, n = theToolGroups.length(); g < n; g++ )
1631 SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1632 if ( CORBA::is_nil( aGrp ) )
1634 if ( aType != aGrp->GetType() )
1635 THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1637 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1638 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1639 toolGroupVec.push_back( grpDS );
1645 aResGrp = CreateGroup( aType, theName );
1647 SMESHDS_Group* resGroupDS = 0;
1648 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1649 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1651 return aResGrp._retn();
1654 size_t i, nb = toolGroupVec.size();
1655 SMDS_ElemIteratorPtr mainElemIt
1656 ( new SMDS_IteratorOnIterators
1657 < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > >( mainIterVec ));
1658 while ( mainElemIt->more() )
1660 const SMDS_MeshElement* e = mainElemIt->next();
1662 for ( i = 0; ( i < nb && !isIn ); ++i )
1663 isIn = toolGroupVec[i]->Contains( e );
1666 resGroupDS->SMDSGroup().Add( e );
1669 // Update Python script
1670 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1671 << ".CutListOfGroups( " << theMainGroups << ", "
1672 << theToolGroups << ", '" << theName << "' )";
1674 SMESH_CATCH( SMESH::throwCorbaException );
1676 return aResGrp._retn();
1679 namespace // functions making checks according to SMESH::NB_COMMON_NODES_ENUM
1681 bool isAllNodesCommon(int nbChecked, int nbCommon, int nbNodes, int /*nbCorners*/,
1682 bool & toStopChecking )
1684 toStopChecking = ( nbCommon < nbChecked );
1685 return nbCommon == nbNodes;
1687 bool isMainNodesCommon(int nbChecked, int nbCommon, int /*nbNodes*/, int nbCorners,
1688 bool & toStopChecking )
1690 toStopChecking = ( nbCommon < nbChecked || nbChecked >= nbCorners );
1691 return nbCommon == nbCorners;
1693 bool isAtLeastOneNodeCommon(int /*nbChecked*/, int nbCommon, int /*nbNodes*/, int /*nbCorners*/,
1694 bool & /*toStopChecking*/ )
1696 return nbCommon > 0;
1698 bool isMajorityOfNodesCommon(int /*nbChecked*/, int nbCommon, int nbNodes, int /*nbCorners*/,
1699 bool & /*toStopChecking*/ )
1701 return nbCommon >= (nbNodes+1) / 2;
1705 //=============================================================================
1707 * Create a group of entities basing on nodes of other groups.
1708 * \param [in] theGroups - list of either groups, sub-meshes or filters.
1709 * \param [in] anElemType - a type of elements to include to the new group.
1710 * \param [in] theName - a name of the new group.
1711 * \param [in] theNbCommonNodes - criterion of inclusion of an element to the new group.
1712 * \param [in] theUnderlyingOnly - if \c True, an element is included to the
1713 * new group provided that it is based on nodes of an element of \a aListOfGroups
1714 * \return SMESH_Group - the created group
1716 // IMP 19939, bug 22010, IMP 22635
1717 //=============================================================================
1719 SMESH::SMESH_Group_ptr
1720 SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfIDSources& theGroups,
1721 SMESH::ElementType theElemType,
1722 const char* theName,
1723 SMESH::NB_COMMON_NODES_ENUM theNbCommonNodes,
1724 CORBA::Boolean theUnderlyingOnly)
1726 SMESH::SMESH_Group_var aResGrp;
1730 _preMeshInfo->FullLoadFromFile();
1732 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1734 if ( !theName || !aMeshDS )
1735 return SMESH::SMESH_Group::_nil();
1737 SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1739 bool (*isToInclude)(int nbChecked, int nbCommon, int nbNodes, int nbCorners, bool & toStop);
1740 SMESH_Comment nbCoNoStr( "SMESH.");
1741 switch ( theNbCommonNodes ) {
1742 case SMESH::ALL_NODES : isToInclude = isAllNodesCommon; nbCoNoStr<<"ALL_NODES" ;break;
1743 case SMESH::MAIN : isToInclude = isMainNodesCommon; nbCoNoStr<<"MAIN" ;break;
1744 case SMESH::AT_LEAST_ONE: isToInclude = isAtLeastOneNodeCommon; nbCoNoStr<<"AT_LEAST_ONE";break;
1745 case SMESH::MAJORITY : isToInclude = isMajorityOfNodesCommon; nbCoNoStr<<"MAJORITY" ;break;
1746 default: return aResGrp._retn();
1748 int nbChecked, nbCommon, nbNodes, nbCorners;
1754 aResGrp = CreateGroup( theElemType, theName );
1755 if ( aResGrp->_is_nil() )
1756 return SMESH::SMESH_Group::_nil();
1758 SMESHDS_GroupBase* groupBaseDS =
1759 SMESH::DownCast<SMESH_GroupBase_i*>( aResGrp )->GetGroupDS();
1760 SMDS_MeshGroup& resGroupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1762 vector<bool> isNodeInGroups;
1764 for ( int g = 0, n = theGroups.length(); g < n; g++ ) // loop on theGroups
1766 SMESH::SMESH_IDSource_var aGrp = theGroups[ g ];
1767 if ( CORBA::is_nil( aGrp ) )
1769 SMESH::SMESH_Mesh_var mesh = aGrp->GetMesh();
1770 if ( mesh->_is_nil() || mesh->GetId() != this->GetId() )
1773 SMDS_ElemIteratorPtr elIt = GetElements( aGrp, SMESH::ALL );
1774 if ( !elIt ) continue;
1776 if ( theElemType == SMESH::NODE ) // get all nodes of elements
1778 while ( elIt->more() ) {
1779 const SMDS_MeshElement* el = elIt->next();
1780 SMDS_ElemIteratorPtr nIt = el->nodesIterator();
1781 while ( nIt->more() )
1782 resGroupCore.Add( nIt->next() );
1785 // get elements of theElemType based on nodes of every element of group
1786 else if ( theUnderlyingOnly )
1788 while ( elIt->more() )
1790 const SMDS_MeshElement* el = elIt->next(); // an element of ref group
1791 TIDSortedElemSet elNodes( el->begin_nodes(), el->end_nodes() );
1792 TIDSortedElemSet checkedElems;
1793 SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1794 while ( nIt->more() )
1796 const SMDS_MeshNode* n = nIt->next();
1797 SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1798 // check nodes of elements of theElemType around el
1799 while ( elOfTypeIt->more() )
1801 const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1802 if ( !checkedElems.insert( elOfType ).second ) continue;
1803 nbNodes = elOfType->NbNodes();
1804 nbCorners = elOfType->NbCornerNodes();
1806 bool toStopChecking = false;
1807 SMDS_ElemIteratorPtr nIt2 = elOfType->nodesIterator();
1808 for ( nbChecked = 1; nIt2->more() && !toStopChecking; ++nbChecked )
1809 if ( elNodes.count( nIt2->next() ) &&
1810 isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1812 resGroupCore.Add( elOfType );
1819 // get all nodes of elements of groups
1822 while ( elIt->more() )
1824 const SMDS_MeshElement* el = elIt->next(); // an element of group
1825 SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1826 while ( nIt->more() )
1828 const SMDS_MeshNode* n = nIt->next();
1829 if ( n->GetID() >= (int) isNodeInGroups.size() )
1830 isNodeInGroups.resize( n->GetID() + 1, false );
1831 isNodeInGroups[ n->GetID() ] = true;
1837 // Get elements of theElemType based on a certain number of nodes of elements of groups
1838 if ( !theUnderlyingOnly && !isNodeInGroups.empty() )
1840 const SMDS_MeshNode* n;
1841 vector<bool> isElemChecked( aMeshDS->MaxElementID() + 1 );
1842 const int isNodeInGroupsSize = isNodeInGroups.size();
1843 for ( int iN = 0; iN < isNodeInGroupsSize; ++iN )
1845 if ( !isNodeInGroups[ iN ] ||
1846 !( n = aMeshDS->FindNode( iN )))
1849 // check nodes of elements of theElemType around n
1850 SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1851 while ( elOfTypeIt->more() )
1853 const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1854 vector<bool>::reference isChecked = isElemChecked[ elOfType->GetID() ];
1859 nbNodes = elOfType->NbNodes();
1860 nbCorners = elOfType->NbCornerNodes();
1862 bool toStopChecking = false;
1863 SMDS_ElemIteratorPtr nIt = elOfType->nodesIterator();
1864 for ( nbChecked = 1; nIt->more() && !toStopChecking; ++nbChecked )
1866 const smIdType nID = nIt->next()->GetID();
1867 if ( nID < isNodeInGroupsSize && isNodeInGroups[ nID ] &&
1868 isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1870 resGroupCore.Add( elOfType );
1878 // Update Python script
1879 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this())
1880 << ".CreateDimGroup( "
1881 << theGroups << ", " << theElemType << ", '" << theName << "', "
1882 << nbCoNoStr << ", " << theUnderlyingOnly << ")";
1884 SMESH_CATCH( SMESH::throwCorbaException );
1886 return aResGrp._retn();
1889 //================================================================================
1891 * \brief Distribute all faces of the mesh between groups using sharp edges and optionally
1892 * existing 1D elements as group boundaries.
1893 * \param [in] theSharpAngle - edge is considered sharp if an angle between normals of
1894 * adjacent faces is more than \a sharpAngle in degrees.
1895 * \param [in] theCreateEdges - to create 1D elements for detected sharp edges.
1896 * \param [in] theUseExistingEdges - to use existing edges as group boundaries
1897 * \return ListOfGroups - the created groups
1899 //================================================================================
1901 SMESH::ListOfGroups*
1902 SMESH_Mesh_i::FaceGroupsSeparatedByEdges( CORBA::Double theSharpAngle,
1903 CORBA::Boolean theCreateEdges,
1904 CORBA::Boolean theUseExistingEdges )
1906 if ( theSharpAngle < 0 || theSharpAngle > 180 )
1907 THROW_SALOME_CORBA_EXCEPTION("Invalid sharp angle, it must be between 0 and 180 degrees",
1910 SMESH::ListOfGroups_var resultGroups = new SMESH::ListOfGroups;
1916 _preMeshInfo->FullLoadFromFile();
1918 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1920 std::vector< SMESH_MeshAlgos::Edge > edges =
1921 SMESH_MeshAlgos::FindSharpEdges( meshDS, theSharpAngle, theUseExistingEdges );
1923 if ( theCreateEdges )
1925 std::vector<const SMDS_MeshNode *> nodes(2);
1926 for ( size_t i = 0; i < edges.size(); ++i )
1928 nodes[0] = edges[i]._node1;
1929 nodes[1] = edges[i]._node2;
1930 if ( meshDS->FindElement( nodes, SMDSAbs_Edge ))
1932 if ( edges[i]._medium )
1933 meshDS->AddEdge( edges[i]._node1, edges[i]._node2, edges[i]._medium );
1935 meshDS->AddEdge( edges[i]._node1, edges[i]._node2 );
1939 std::vector< std::vector< const SMDS_MeshElement* > > faceGroups =
1940 SMESH_MeshAlgos::SeparateFacesByEdges( meshDS, edges );
1942 SMESH::SMESH_MeshEditor_var editor = GetMeshEditor(); // create _editor
1944 resultGroups->length( faceGroups.size() );
1945 for ( size_t iG = 0; iG < faceGroups.size(); ++iG )
1947 SMESH::SMESH_Group_var group = CreateGroup( SMESH::FACE,
1948 _editor->GenerateGroupName("Group").c_str());
1949 resultGroups[iG] = SMESH::SMESH_Group::_duplicate( group );
1951 SMESHDS_GroupBase* groupBaseDS =
1952 SMESH::DownCast<SMESH_GroupBase_i*>( group )->GetGroupDS();
1953 SMDS_MeshGroup& groupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1955 std::vector< const SMDS_MeshElement* >& faces = faceGroups[ iG ];
1956 for ( size_t i = 0; i < faces.size(); ++i )
1957 groupCore.Add( faces[i] );
1960 pyDump << resultGroups << " = " << SMESH::SMESH_Mesh_var(_this())
1961 << ".FaceGroupsSeparatedByEdges( "
1962 << TVar( theSharpAngle ) << ", "
1963 << theCreateEdges << ", "
1964 << theUseExistingEdges << " )";
1966 SMESH_CATCH( SMESH::throwCorbaException );
1967 return resultGroups._retn();
1971 //================================================================================
1973 * \brief Remember GEOM group data
1975 //================================================================================
1977 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1978 CORBA::Object_ptr theSmeshObj)
1980 if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1983 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( theGeomObj );
1984 if ( groupSO->_is_nil() )
1987 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( theGeomObj );
1988 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
1989 GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
1992 _geomGroupData.push_back( TGeomGroupData() );
1993 TGeomGroupData & groupData = _geomGroupData.back();
1995 CORBA::String_var entry = groupSO->GetID();
1996 groupData._groupEntry = entry.in();
1998 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
1999 groupData._indices.insert( ids[i] );
2001 groupData._smeshObject = CORBA::Object::_duplicate( theSmeshObj );
2002 // shape index in SMESHDS
2003 // TopoDS_Shape shape = _gen_i->GeomObjectToShape( theGeomObj );
2004 // groupData._dsID = shape.IsNull() ? 0 : _impl->GetSubMesh( shape )->GetId();
2007 //================================================================================
2009 * Remove GEOM group data relating to removed smesh object
2011 //================================================================================
2013 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
2015 list<TGeomGroupData>::iterator
2016 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2017 for ( ; data != dataEnd; ++data ) {
2018 if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
2019 _geomGroupData.erase( data );
2025 //================================================================================
2027 * \brief Replace a shape in the mesh upon Break Link
2029 //================================================================================
2031 void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom)
2033 // check if geometry changed
2034 bool geomChanged = true;
2035 GEOM::GEOM_Object_var oldGeom = GetShapeToMesh();
2036 if ( !theNewGeom->_is_nil() && !oldGeom->_is_nil() )
2037 geomChanged = ( oldGeom->GetTick() != theNewGeom->GetTick() );
2039 TopoDS_Shape S = _impl->GetShapeToMesh();
2040 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2041 TCollection_AsciiString aIOR;
2042 if ( geomClient->Find( S, aIOR ))
2043 geomClient->RemoveShapeFromBuffer( aIOR );
2045 // clear buffer also for sub-groups
2046 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2047 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2048 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2049 for (; g != groups.end(); ++g)
2050 if (const SMESHDS_GroupOnGeom* group = dynamic_cast<SMESHDS_GroupOnGeom*>(*g))
2052 const TopoDS_Shape& s = group->GetShape();
2053 if ( geomClient->Find( s, aIOR ))
2054 geomClient->RemoveShapeFromBuffer( aIOR );
2057 // clear buffer also for sub-meshes
2058 std::map<int, SMESH_subMesh_i*>::const_iterator aSubMeshIter = _mapSubMesh_i.cbegin();
2059 for(; aSubMeshIter != _mapSubMesh_i.cend(); aSubMeshIter++) {
2060 int aShapeID = aSubMeshIter->first;
2061 const TopoDS_Shape& aSubShape = meshDS->IndexToShape(aShapeID);
2062 TCollection_AsciiString aShapeIOR;
2063 if ( geomClient->Find( aSubShape, aShapeIOR ))
2064 geomClient->RemoveShapeFromBuffer( aShapeIOR );
2068 int shapeID; smIdType fromID, toID; // indices of elements of a sub-mesh
2070 std::vector< TRange > elemRanges, nodeRanges; // elements of sub-meshes
2071 std::vector< SMDS_PositionPtr > positions; // node positions
2074 // store positions of elements on geometry
2076 if ( meshDS->MaxNodeID() > meshDS->NbNodes() ||
2077 meshDS->MaxElementID() > meshDS->NbElements() )
2080 meshDS->CompactMesh();
2082 positions.resize( meshDS->NbNodes() + 1 );
2083 for ( SMDS_NodeIteratorPtr nodeIt = meshDS->nodesIterator(); nodeIt->more(); )
2085 const SMDS_MeshNode* n = nodeIt->next();
2086 positions[ n->GetID() ] = n->GetPosition();
2089 // remove elements from sub-meshes to avoid their removal at hypotheses addition
2090 for ( int isNode = 0; isNode < 2; ++isNode )
2092 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2093 ranges.reserve( meshDS->MaxShapeIndex() + 10 );
2094 ranges.push_back( TRange{ 0,0,0 });
2095 SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
2096 while ( elemIt->more() )
2098 const SMDS_MeshElement* e = elemIt->next();
2099 const smIdType elemID = e->GetID();
2100 const int shapeID = e->GetShapeID();
2101 TRange & lastRange = ranges.back();
2102 if ( lastRange.shapeID != shapeID ||
2103 lastRange.toID != elemID )
2104 ranges.push_back( TRange{ shapeID, elemID, elemID + 1 });
2106 lastRange.toID = elemID + 1;
2108 if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( shapeID ))
2110 if ( isNode ) sm->RemoveNode( static_cast< const SMDS_MeshNode *>( e ));
2111 else sm->RemoveElement( e );
2118 // update the reference to theNewGeom (needed for correct execution of a dumped python script)
2119 SMESH::SMESH_Mesh_var me = _this();
2120 SALOMEDS::SObject_wrap aSO = _gen_i->ObjectToSObject( me );
2121 CORBA::String_var entry = theNewGeom->GetStudyEntry();
2122 if ( !aSO->_is_nil() )
2124 SALOMEDS::SObject_wrap aShapeRefSO;
2125 if ( aSO->FindSubObject( _gen_i->GetRefOnShapeTag(), aShapeRefSO.inout() ))
2127 SALOMEDS::SObject_wrap aShapeSO = _gen_i->getStudyServant()->FindObjectID( entry );
2128 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2129 builder->Addreference( aShapeRefSO, aShapeSO );
2133 // re-assign global hypotheses to the new shape
2134 _mainShapeTick = geomChanged ? -1 : theNewGeom->GetTick();
2135 CheckGeomModif( true );
2139 // restore positions of elements on geometry
2140 for ( int isNode = 0; isNode < 2; ++isNode )
2142 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2143 for ( size_t i = 1; i < ranges.size(); ++i )
2145 int elemID = ranges[ i ].fromID;
2146 int toID = ranges[ i ].toID;
2147 SMESHDS_SubMesh * smDS = meshDS->NewSubMesh( ranges[ i ].shapeID );
2149 for ( ; elemID < toID; ++elemID )
2150 smDS->AddNode( meshDS->FindNode( elemID ));
2152 for ( ; elemID < toID; ++elemID )
2153 smDS->AddElement( meshDS->FindElement( elemID ));
2155 if ( SMESH_subMesh* sm = _impl->GetSubMeshContaining( ranges[ i ].shapeID ))
2156 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
2159 for ( unsigned int nodeID = 1; nodeID < positions.size(); ++nodeID )
2160 if ( positions[ nodeID ])
2161 if ( SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( meshDS->FindNode( nodeID )))
2162 n->SetPosition( positions[ nodeID ], n->GetShapeID() );
2165 _gen_i->UpdateIcons( SMESH::SMESH_Mesh_var( _this() ));
2168 TPythonDump() << "SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject("
2169 << me <<".GetMesh()), " << entry.in() << ")";
2171 TPythonDump() << me << ".ReplaceShape( " << entry.in() << " )";
2175 //================================================================================
2177 * \brief Return new group contents if it has been changed and update group data
2179 //================================================================================
2181 enum { ONLY_IF_CHANGED, IS_BREAK_LINK, MAIN_TRANSFORMED };
2183 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData, int how )
2185 TopoDS_Shape newShape;
2186 SALOMEDS::SObject_wrap groupSO;
2188 if ( how == IS_BREAK_LINK )
2190 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( groupData._smeshObject );
2191 SALOMEDS::SObject_wrap geomRefSO;
2192 if ( !meshSO->_is_nil() &&
2193 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ))
2195 geomRefSO->ReferencedObject( groupSO.inout() );
2201 groupSO = _gen_i->getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
2204 if ( groupSO->_is_nil() )
2207 CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
2208 GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
2209 if ( geomGroup->_is_nil() )
2212 // get indices of group items
2213 set<int> curIndices;
2214 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( geomGroup );
2215 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
2216 GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
2217 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2218 curIndices.insert( ids[i] );
2220 bool sameIndices = ( groupData._indices == curIndices );
2221 if ( how == ONLY_IF_CHANGED && sameIndices )
2222 return newShape; // group not changed
2225 CORBA::String_var entry = geomGroup->GetStudyEntry();
2226 groupData._groupEntry = entry.in();
2227 groupData._indices = curIndices;
2229 newShape = _gen_i->GeomObjectToShape( geomGroup );
2231 // check if newShape is up-to-date
2232 if ( !newShape.IsNull() && ids->length() > 0 )
2234 bool toUpdate = ! _impl->GetMeshDS()->IsGroupOfSubShapes( newShape );
2237 TopExp_Explorer exp( newShape, (TopAbs_ShapeEnum)( groupOp->GetType( geomGroup )));
2238 for ( ; exp.More() && !toUpdate; exp.Next() )
2240 int ind = _impl->GetMeshDS()->ShapeToIndex( exp.Current() );
2241 toUpdate = ( curIndices.erase( ind ) == 0 );
2243 if ( !curIndices.empty() )
2248 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2249 CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
2250 geomClient->RemoveShapeFromBuffer( groupIOR.in() );
2251 newShape = _gen_i->GeomObjectToShape( geomGroup );
2256 // geom group becomes empty - return empty compound
2257 TopoDS_Compound compound;
2258 BRep_Builder().MakeCompound(compound);
2259 newShape = compound;
2267 //-----------------------------------------------------------------------------
2269 * \brief Storage of shape and index used in CheckGeomGroupModif()
2271 struct TIndexedShape
2274 TopoDS_Shape _shape;
2275 TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
2277 //-----------------------------------------------------------------------------
2279 * \brief Data to re-create a group on geometry
2281 struct TGroupOnGeomData
2284 TopoDS_Shape _shape;
2285 SMDSAbs_ElementType _type;
2287 Quantity_Color _color;
2289 TGroupOnGeomData( const SMESHDS_GroupOnGeom* group )
2291 _oldID = group->GetID();
2292 _type = group->GetType();
2293 _name = group->GetStoreName();
2294 _color = group->GetColor();
2298 //-----------------------------------------------------------------------------
2300 * \brief Check if a filter is still valid after geometry removal
2302 bool isValidGeomFilter( SMESH::Filter_var theFilter )
2304 if ( theFilter->_is_nil() )
2306 SMESH::Filter::Criteria_var criteria;
2307 theFilter->GetCriteria( criteria.out() );
2309 for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
2311 const char* thresholdID = criteria[ iCr ].ThresholdID.in();
2313 switch ( criteria[ iCr ].Type )
2315 case SMESH::FT_BelongToGeom:
2316 case SMESH::FT_BelongToPlane:
2317 case SMESH::FT_BelongToCylinder:
2318 case SMESH::FT_BelongToGenSurface:
2319 case SMESH::FT_LyingOnGeom:
2320 entry = thresholdID;
2322 case SMESH::FT_ConnectedElements:
2325 entry = thresholdID;
2331 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
2332 SALOMEDS::SObject_wrap so = gen->getStudyServant()->FindObjectID( entry.c_str() );
2333 if ( so->_is_nil() )
2335 CORBA::Object_var obj = so->GetObject();
2336 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj );
2337 if ( gen->GeomObjectToShape( geom ).IsNull() )
2340 } // loop on criteria
2346 //=============================================================================
2348 * \brief Update data if geometry changes
2352 //=============================================================================
2354 void SMESH_Mesh_i::CheckGeomModif( bool theIsBreakLink )
2356 SMESH::SMESH_Mesh_var me = _this();
2357 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2359 TPythonDump dumpNothing; // prevent any dump
2361 //bool removedFromClient = false;
2363 if ( mainGO->_is_nil() ) // GEOM_Client cleared or geometry removed? (IPAL52735, PAL23636)
2365 //removedFromClient = _impl->HasShapeToMesh();
2367 // try to find geometry by study reference
2368 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2369 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2370 if ( !meshSO->_is_nil() &&
2371 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2372 geomRefSO->ReferencedObject( geomSO.inout() ))
2374 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2375 mainGO = GEOM::GEOM_Object::_narrow( geomObj );
2378 if ( mainGO->_is_nil() && // geometry removed ==>
2379 !geomRefSO->_is_nil() ) // remove geom dependent data: sub-meshes etc.
2381 // convert geom dependent groups into standalone ones
2382 CheckGeomGroupModif();
2384 _impl->ShapeToMesh( TopoDS_Shape() );
2386 // remove sub-meshes
2387 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2388 while ( i_sm != _mapSubMeshIor.end() )
2390 SMESH::SMESH_subMesh_ptr sm = i_sm->second;
2392 RemoveSubMesh( sm );
2394 // remove all children except groups in the study
2395 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2396 SALOMEDS::SObject_wrap so;
2397 for ( CORBA::Long tag = SMESH::Tag_RefOnShape; tag <= SMESH::Tag_LastSubMesh; ++tag )
2398 if ( meshSO->FindSubObject( tag, so.inout() ))
2399 builder->RemoveObjectWithChildren( so );
2401 _gen_i->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED" );
2407 if ( !_impl->HasShapeToMesh() ) return;
2410 // Update after group modification
2412 const bool geomChanged = ( mainGO->GetTick() != _mainShapeTick );
2413 if ( !theIsBreakLink )
2414 if ( mainGO->GetType() == GEOM_GROUP || !geomChanged ) // is group or not modified
2416 smIdType nb = NbNodes() + NbElements();
2417 CheckGeomGroupModif();
2418 bool updated = ( nb != NbNodes() + NbElements() );
2419 if ( updated ) // something removed due to hypotheses change
2420 _gen_i->UpdateIcons( me );
2421 if ( updated == geomChanged || nb == 0 )
2425 // Update after shape modification or breakLink w/o geometry change
2427 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2428 if ( !geomClient ) return;
2429 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( mainGO );
2430 if ( geomGen->_is_nil() ) return;
2431 CORBA::String_var geomComponentType = geomGen->ComponentDataType();
2432 bool isShaper = ( strcmp( geomComponentType.in(), "SHAPERSTUDY" ) == 0 );
2434 SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
2436 TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
2437 if ( meshDS->ShapeToIndex( newShape ) == 1 ) // not yet updated
2439 CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
2440 geomClient->RemoveShapeFromBuffer( ior.in() );
2441 newShape = _gen_i->GeomObjectToShape( mainGO );
2444 // Update data taking into account that if topology doesn't change
2445 // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
2448 _preMeshInfo->ForgetAllData();
2450 if ( geomChanged || !isShaper )
2452 if ( newShape.IsNull() )
2455 _mainShapeTick = mainGO->GetTick();
2457 // store data of groups on geometry including new TopoDS_Shape's
2458 std::vector< TGroupOnGeomData > groupsData;
2459 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2460 groupsData.reserve( groups.size() );
2461 TopTools_DataMapOfShapeShape old2newShapeMap;
2462 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2463 for ( ; g != groups.end(); ++g )
2465 if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
2467 groupsData.push_back( TGroupOnGeomData( group ));
2470 SMESH::SMESH_GroupOnGeom_var gog;
2471 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.find( group->GetID() );
2472 if ( i_grp != _mapGroups.end() )
2473 gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second );
2475 GEOM::GEOM_Object_var geom;
2476 if ( !gog->_is_nil() )
2478 if ( !theIsBreakLink )
2479 geom = gog->GetShape();
2481 if ( theIsBreakLink || geom->_is_nil() )
2483 SALOMEDS::SObject_wrap grpSO = _gen_i->ObjectToSObject( gog );
2484 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2485 if ( !grpSO->_is_nil() &&
2486 grpSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2487 geomRefSO->ReferencedObject( geomSO.inout() ))
2489 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2490 geom = GEOM::GEOM_Object::_narrow( geomObj );
2494 if ( old2newShapeMap.IsBound( group->GetShape() ))
2496 groupsData.back()._shape = old2newShapeMap( group->GetShape() );
2498 else if ( !geom->_is_nil() )
2500 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2501 if ( meshDS->IsGroupOfSubShapes( groupsData.back()._shape ))
2503 CORBA::String_var ior = geomGen->GetStringFromIOR( geom );
2504 geomClient->RemoveShapeFromBuffer( ior.in() );
2505 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2507 old2newShapeMap.Bind( group->GetShape(), groupsData.back()._shape );
2512 // store assigned hypotheses
2513 std::vector< pair< int, THypList > > ids2Hyps;
2514 const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
2515 for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
2517 const TopoDS_Shape& s = s2hyps.Key();
2518 const THypList& hyps = s2hyps.ChangeValue();
2519 ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
2522 std::multimap< std::set<int>, int > ii2iMap; // group sub-ids to group id in SMESHDS
2524 // count shapes excluding compounds corresponding to geom groups
2525 int oldNbSubShapes = meshDS->MaxShapeIndex();
2526 for ( ; oldNbSubShapes > 0; --oldNbSubShapes )
2528 const TopoDS_Shape& s = meshDS->IndexToShape( oldNbSubShapes );
2529 if ( s.IsNull() || s.ShapeType() != TopAbs_COMPOUND )
2532 std::set<int> subIds;
2533 for ( TopoDS_Iterator it( s ); it.More(); it.Next() )
2534 subIds.insert( meshDS->ShapeToIndex( it.Value() ));
2535 ii2iMap.insert( std::make_pair( subIds, oldNbSubShapes ));
2538 // check if shape topology changes - save shape type per shape ID
2539 std::vector< TopAbs_ShapeEnum > shapeTypes( Max( oldNbSubShapes + 1, 1 ));
2540 for ( int shapeID = oldNbSubShapes; shapeID > 0; --shapeID )
2541 shapeTypes[ shapeID ] = meshDS->IndexToShape( shapeID ).ShapeType();
2543 // change shape to mesh
2544 _impl->ShapeToMesh( TopoDS_Shape() );
2545 _impl->ShapeToMesh( newShape );
2547 // check if shape topology changes - check new shape types
2548 bool sameTopology = ( oldNbSubShapes == meshDS->MaxShapeIndex() );
2549 for ( int shapeID = oldNbSubShapes; shapeID > 0 && sameTopology; --shapeID )
2551 const TopoDS_Shape& s = meshDS->IndexToShape( shapeID );
2552 sameTopology = ( !s.IsNull() && s.ShapeType() == shapeTypes[ shapeID ]);
2555 // re-add shapes (compounds) of geom groups
2556 typedef std::map< std::vector< int >, TGeomGroupData* > TIndices2GroupData;
2557 TIndices2GroupData ii2grData;
2558 std::vector< int > ii;
2559 std::map< int, int > old2newIDs; // group IDs
2560 std::list<TGeomGroupData>::iterator dataIt = _geomGroupData.begin();
2561 for ( ; dataIt != _geomGroupData.end(); ++dataIt )
2563 TGeomGroupData* data = &(*dataIt);
2564 ii.reserve( data->_indices.size() );
2565 ii.assign( data->_indices.begin(), data->_indices.end() );
2566 TIndices2GroupData::iterator ii2gd = ii2grData.insert( std::make_pair( ii, data )).first;
2567 if ( ii2gd->second != data )
2569 data->_groupEntry = ii2gd->second->_groupEntry;
2570 data->_indices = ii2gd->second->_indices;
2573 const int oldNbSub = data->_indices.size();
2574 const int soleOldID = oldNbSub == 1 ? *data->_indices.begin() : 0;
2576 std::multimap< std::set<int>, int >::iterator ii2i = ii2iMap.find( data->_indices );
2577 if ( ii2i != ii2iMap.end() )
2579 oldID = ii2i->second;
2580 ii2iMap.erase( ii2i );
2582 if ( !oldID && oldNbSub == 1 )
2584 if ( old2newIDs.count( oldID ))
2587 int how = ( theIsBreakLink || !sameTopology ) ? IS_BREAK_LINK : MAIN_TRANSFORMED;
2588 newShape = newGroupShape( *data, how );
2590 if ( !newShape.IsNull() )
2592 if ( oldNbSub > 1 && meshDS->ShapeToIndex( newShape ) > 0 ) // group reduced to one sub-shape
2594 TopoDS_Compound compound;
2595 BRep_Builder().MakeCompound( compound );
2596 BRep_Builder().Add( compound, newShape );
2597 newShape = compound;
2599 int newID = _impl->GetSubMesh( newShape )->GetId();
2600 if ( oldID /*&& oldID != newID*/ )
2601 old2newIDs.insert( std::make_pair( oldID, newID ));
2602 if ( oldNbSub == 1 )
2603 old2newIDs.insert( std::make_pair( soleOldID, newID ));
2607 // re-assign hypotheses
2608 for ( size_t i = 0; i < ids2Hyps.size(); ++i )
2610 int sID = ids2Hyps[i].first;
2613 std::map< int, int >::iterator o2n = old2newIDs.find( sID );
2614 if ( o2n != old2newIDs.end() )
2616 else if ( !sameTopology )
2619 const TopoDS_Shape& s = meshDS->IndexToShape( sID );
2622 const THypList& hyps = ids2Hyps[i].second;
2623 THypList::const_iterator h = hyps.begin();
2624 for ( ; h != hyps.end(); ++h )
2625 _impl->AddHypothesis( s, (*h)->GetID() );
2629 // restore groups on geometry
2630 for ( size_t i = 0; i < groupsData.size(); ++i )
2632 const TGroupOnGeomData& data = groupsData[i];
2633 if ( data._shape.IsNull() )
2636 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
2637 if ( i2g == _mapGroups.end() ) continue;
2639 SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
2640 if ( !gr_i ) continue;
2642 SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape );
2644 _mapGroups.erase( i2g );
2646 g->GetGroupDS()->SetColor( data._color );
2649 if ( !sameTopology )
2651 std::map< int, int >::iterator o2n = old2newIDs.begin();
2652 for ( ; o2n != old2newIDs.end(); ++o2n )
2654 int newID = o2n->second, oldID = o2n->first;
2655 if ( newID == oldID || !_mapSubMesh.count( oldID ))
2659 _mapSubMesh [ newID ] = _impl->GetSubMeshContaining( newID );
2660 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2661 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2663 _mapSubMesh. erase(oldID);
2664 _mapSubMesh_i. erase(oldID);
2665 _mapSubMeshIor.erase(oldID);
2667 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2671 // update _mapSubMesh
2672 std::map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
2673 for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
2674 i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
2677 if ( !sameTopology )
2679 // remove invalid study sub-objects
2680 CheckGeomGroupModif();
2683 _gen_i->UpdateIcons( me );
2685 if ( !theIsBreakLink && isShaper )
2687 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2688 if ( !meshSO->_is_nil() )
2689 _gen_i->SetPixMap(meshSO, "ICON_SMESH_TREE_GEOM_MODIF");
2693 //=============================================================================
2695 * \brief Update objects depending on changed geom groups
2697 * NPAL16168: geometrical group edition from a submesh don't modify mesh computation
2698 * issue 0020210: Update of a smesh group after modification of the associated geom group
2700 //=============================================================================
2702 void SMESH_Mesh_i::CheckGeomGroupModif()
2704 // remove sub-meshes referring a removed sub-shapes (if main shape still exists)
2705 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2706 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2707 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() ));
2708 if ( !mainGO->_is_nil() && !meshSO->_is_nil() )
2710 SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO;
2711 for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag )
2712 if ( meshSO->FindSubObject( tag, rootSO.inout() ))
2714 int nbValid = 0, nbRemoved = 0;
2715 SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO );
2716 for ( ; chItr->More(); chItr->Next() )
2718 SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO
2719 if ( !smSO->_is_nil() &&
2720 smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2721 geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference
2723 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2724 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj );
2725 if ( !geom->_non_existent() )
2728 continue; // keep the sub-mesh
2731 CORBA::Object_var smObj = _gen_i->SObjectToObject( smSO );
2732 SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj );
2733 if ( !sm->_is_nil() && !sm->_non_existent() )
2735 GEOM::GEOM_Object_var smGeom = sm->GetSubShape();
2736 if ( smGeom->_is_nil() )
2738 RemoveSubMesh( sm );
2745 _preMeshInfo->ForgetAllData(); // unknown hypothesis modified
2746 builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH
2750 if ( /*nbRemoved > 0 &&*/ nbValid == 0 )
2751 builder->RemoveObjectWithChildren( rootSO );
2755 // check for removed sub-shapes and convert geom dependent groups into standalone ones
2756 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2757 while ( i_gr != _mapGroups.end())
2759 SMESH::SMESH_GroupBase_ptr group = i_gr->second;
2761 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( group ), refSO, geomSO;
2762 SMESH::SMESH_GroupOnGeom_var onGeom = SMESH::SMESH_GroupOnGeom::_narrow ( group );
2763 SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group );
2764 bool isValidGeom = false;
2765 if ( !onGeom->_is_nil() )
2767 isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() ); // check TopoDS
2768 if ( !isValidGeom ) // check reference
2770 isValidGeom = ( ! groupSO->_is_nil() &&
2771 groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ) &&
2772 refSO->ReferencedObject( geomSO.inout() ) &&
2773 ! geomSO->_is_nil() &&
2774 !CORBA::is_nil( CORBA::Object_var( geomSO->GetObject() )));
2777 else if ( !onFilt->_is_nil() )
2779 isValidGeom = isValidGeomFilter( onFilt->GetFilter() );
2783 isValidGeom = ( !groupSO->_is_nil() &&
2784 !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ));
2788 if ( !IsLoaded() || group->IsEmpty() )
2790 RemoveGroup( group );
2792 else if ( !onGeom->_is_nil() || !onFilt->_is_nil() )
2794 SMESH::SMESH_Group_var ( ConvertToStandalone( group ));
2796 else // is it possible?
2798 builder->RemoveObjectWithChildren( refSO );
2804 if ( !_impl->HasShapeToMesh() ) return;
2806 SMESH::smIdType nbEntities = NbNodes() + NbElements();
2808 // Check if group contents changed
2810 typedef map< string, TopoDS_Shape > TEntry2Geom;
2811 TEntry2Geom newGroupContents;
2813 list<TGeomGroupData>::iterator
2814 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2815 for ( ; data != dataEnd; ++data )
2817 pair< TEntry2Geom::iterator, bool > it_new =
2818 newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
2819 bool processedGroup = !it_new.second;
2820 TopoDS_Shape& newShape = it_new.first->second;
2821 if ( !processedGroup )
2822 newShape = newGroupShape( *data, ONLY_IF_CHANGED );
2823 if ( newShape.IsNull() )
2824 continue; // no changes
2827 _preMeshInfo->ForgetOrLoad();
2829 if ( processedGroup ) { // update group indices
2830 list<TGeomGroupData>::iterator data2 = data;
2831 for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
2832 data->_indices = data2->_indices;
2835 // Update SMESH objects according to new GEOM group contents
2837 SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2838 if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2840 int oldID = submesh->GetId();
2841 if ( !_mapSubMeshIor.count( oldID ))
2843 TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2845 // update hypotheses
2846 list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2847 list <const SMESHDS_Hypothesis * >::iterator hypIt;
2848 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2850 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2851 _impl->AddHypothesis ( newShape, (*hypIt)->GetID());
2853 // care of submeshes
2854 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2855 int newID = newSubmesh->GetId();
2856 if ( newID != oldID ) {
2857 _mapSubMesh [ newID ] = newSubmesh;
2858 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2859 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2860 _mapSubMesh. erase(oldID);
2861 _mapSubMesh_i. erase(oldID);
2862 _mapSubMeshIor.erase(oldID);
2863 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2868 SMESH::SMESH_GroupOnGeom_var smeshGroup =
2869 SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2870 if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2872 SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2874 ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2875 SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2876 ds->SetShape( newShape );
2881 SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2882 if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2884 // Remove groups and submeshes basing on removed sub-shapes
2886 TopTools_MapOfShape newShapeMap;
2887 TopoDS_Iterator shapeIt( newShape );
2888 for ( ; shapeIt.More(); shapeIt.Next() )
2889 newShapeMap.Add( shapeIt.Value() );
2891 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2892 for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2894 if ( newShapeMap.Contains( shapeIt.Value() ))
2896 TopTools_IndexedMapOfShape oldShapeMap;
2897 TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2898 for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2900 const TopoDS_Shape& oldShape = oldShapeMap(i);
2901 int oldInd = meshDS->ShapeToIndex( oldShape );
2903 map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2904 if ( i_smIor != _mapSubMeshIor.end() ) {
2905 RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2908 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2909 for ( ; i_grp != _mapGroups.end(); ++i_grp )
2911 // check if a group bases on oldInd shape
2912 SMESHDS_GroupOnGeom* grpOnGeom = 0;
2913 if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2914 grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2915 if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2917 RemoveGroup( i_grp->second ); // several groups can base on same shape
2918 i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2923 // Reassign hypotheses and update groups after setting the new shape to mesh
2925 // collect anassigned hypotheses
2926 typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2927 list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2928 TShapeHypList assignedHyps;
2929 for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2931 const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2932 list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2933 if ( !hyps.empty() ) {
2934 assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2935 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2936 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2939 // collect shapes supporting groups
2940 typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2941 TShapeTypeList groupData;
2942 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2943 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2944 for ( ; grIt != groups.end(); ++grIt )
2946 if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2948 ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2950 // set new shape to mesh -> DS of sub-meshes and geom groups is deleted
2952 _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
2953 _impl->ShapeToMesh( newShape );
2955 // reassign hypotheses
2956 TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2957 for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2959 TIndexedShape& geom = indS_hyps->first;
2960 list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2961 int oldID = geom._index;
2962 int newID = meshDS->ShapeToIndex( geom._shape );
2963 if ( oldID == 1 ) { // main shape
2965 geom._shape = newShape;
2969 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2970 _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2971 // care of sub-meshes
2972 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2973 if ( newID != oldID ) {
2974 _mapSubMesh [ newID ] = newSubmesh;
2975 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2976 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2977 _mapSubMesh. erase(oldID);
2978 _mapSubMesh_i. erase(oldID);
2979 _mapSubMeshIor.erase(oldID);
2980 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2984 TShapeTypeList::iterator geomType = groupData.begin();
2985 for ( ; geomType != groupData.end(); ++geomType )
2987 const TIndexedShape& geom = geomType->first;
2988 int oldID = geom._index;
2989 if ( _mapGroups.find( oldID ) == _mapGroups.end() )
2992 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( _mapGroups[oldID] );
2993 CORBA::String_var name = groupSO->GetName();
2995 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID]))
2996 if ( SMESH_Group* group = _impl->AddGroup( geomType->second, name.in(),
2997 /*id=*/-1, geom._shape ))
2998 group_i->changeLocalId( group->GetID() );
3001 break; // everything has been updated
3004 } // loop on group data
3008 SMESH::smIdType newNbEntities = NbNodes() + NbElements();
3009 list< SALOMEDS::SObject_wrap > soToUpdateIcons;
3010 if ( newNbEntities != nbEntities )
3012 // Add all SObjects with icons to soToUpdateIcons
3013 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( _this() )); // mesh
3015 for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
3016 i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
3017 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_sm->second ));
3019 for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
3020 i_gr != _mapGroups.end(); ++i_gr ) // groups
3021 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_gr->second ));
3024 list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
3025 for ( ; so != soToUpdateIcons.end(); ++so )
3026 _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
3029 //=============================================================================
3031 * \brief Create standalone group from a group on geometry or filter
3033 //=============================================================================
3035 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
3037 SMESH::SMESH_Group_var aGroup;
3042 _preMeshInfo->FullLoadFromFile();
3044 if ( theGroup->_is_nil() )
3045 return aGroup._retn();
3047 SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
3049 return aGroup._retn();
3051 const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
3053 const int anId = aGroupToRem->GetLocalID();
3054 if ( !_impl->ConvertToStandalone( anId ) )
3055 return aGroup._retn();
3056 removeGeomGroupData( theGroup );
3058 SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3060 // remove old instance of group from own map
3061 { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
3062 _mapGroups.erase( anId );
3064 SALOMEDS::StudyBuilder_var builder;
3065 SALOMEDS::SObject_wrap aGroupSO;
3066 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3067 if ( !aStudy->_is_nil() ) {
3068 builder = aStudy->NewBuilder();
3069 aGroupSO = _gen_i->ObjectToSObject( theGroup );
3070 if ( !aGroupSO->_is_nil() )
3072 // remove reference to geometry
3073 SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
3074 for ( ; chItr->More(); chItr->Next() )
3076 // Remove group's child SObject
3077 SALOMEDS::SObject_wrap so = chItr->Value();
3078 builder->RemoveObject( so );
3080 // Update Python script
3081 TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
3082 << ".ConvertToStandalone( " << aGroupSO << " )";
3084 // change icon of Group on Filter
3087 // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
3088 // const int isEmpty = ( elemTypes->length() == 0 );
3091 SALOMEDS::GenericAttribute_wrap anAttr =
3092 builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
3093 SALOMEDS::AttributePixMap_wrap pm = anAttr;
3094 pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
3100 // remember new group in own map
3101 aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
3102 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3104 // register CORBA object for persistence
3105 _gen_i->RegisterObject( aGroup );
3107 CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
3108 builder->SetIOR( aGroupSO, ior.in() ); // == aGroup->Register();
3109 //aGroup->Register();
3110 aGroupToRem->UnRegister();
3112 SMESH_CATCH( SMESH::throwCorbaException );
3114 return aGroup._retn();
3117 //================================================================================
3119 * \brief Create a sub-mesh on a given sub-shape
3121 //================================================================================
3123 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
3125 if(MYDEBUG) MESSAGE( "createSubMesh" );
3126 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
3127 ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
3130 SMESH_subMesh_i * subMeshServant;
3133 subMeshId = mySubMesh->GetId();
3134 subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
3136 else // "invalid sub-mesh"
3138 // The invalid sub-mesh is created for the case where a valid sub-shape not found
3139 // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0.
3140 if ( _mapSubMesh.empty() )
3143 subMeshId = _mapSubMesh.begin()->first - 1;
3144 subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject);
3147 SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
3149 _mapSubMesh [subMeshId] = mySubMesh;
3150 _mapSubMesh_i [subMeshId] = subMeshServant;
3151 _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
3153 subMeshServant->Register();
3155 // register CORBA object for persistence
3156 int nextId = _gen_i->RegisterObject( subMesh );
3157 if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
3158 else { (void)nextId; } // avoid "unused variable" warning
3160 // to track changes of GEOM groups
3161 if ( subMeshId > 0 )
3162 addGeomGroupData( theSubShapeObject, subMesh );
3164 return subMesh._retn();
3167 //================================================================================
3169 * \brief Return an existing sub-mesh based on a sub-shape with the given ID
3171 //================================================================================
3173 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
3175 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
3176 if ( it == _mapSubMeshIor.end() )
3177 return SMESH::SMESH_subMesh::_nil();
3179 return SMESH::SMESH_subMesh::_duplicate( (*it).second );
3182 //================================================================================
3184 * \brief Remove a sub-mesh based on the given sub-shape
3186 //================================================================================
3188 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
3189 GEOM::GEOM_Object_ptr theSubShapeObject )
3191 bool isHypChanged = false;
3192 if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
3193 return isHypChanged;
3195 const int subMeshId = theSubMesh->GetId();
3197 if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
3200 if (( _mapSubMesh.count( subMeshId )) &&
3201 ( sm = _impl->GetSubMeshContaining( subMeshId )))
3203 TopoDS_Shape S = sm->GetSubShape();
3206 list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
3207 isHypChanged = !hyps.empty();
3208 if ( isHypChanged && _preMeshInfo )
3209 _preMeshInfo->ForgetOrLoad();
3210 list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
3211 for ( ; hyp != hyps.end(); ++hyp )
3212 _impl->RemoveHypothesis(S, (*hyp)->GetID());
3219 SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
3220 isHypChanged = ( aHypList->length() > 0 );
3221 for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
3222 removeHypothesis( theSubShapeObject, aHypList[i] );
3225 catch( const SALOME::SALOME_Exception& ) {
3226 INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
3228 removeGeomGroupData( theSubShapeObject );
3232 std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
3233 if ( id_smi != _mapSubMesh_i.end() )
3234 id_smi->second->UnRegister();
3236 // remove a CORBA object
3237 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
3238 if ( id_smptr != _mapSubMeshIor.end() )
3239 SMESH::SMESH_subMesh_var( id_smptr->second );
3241 _mapSubMesh.erase(subMeshId);
3242 _mapSubMesh_i.erase(subMeshId);
3243 _mapSubMeshIor.erase(subMeshId);
3245 return isHypChanged;
3248 //================================================================================
3250 * \brief Create a group. Group type depends on given arguments
3252 //================================================================================
3254 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
3255 const char* theName,
3257 const TopoDS_Shape& theShape,
3258 const SMESH_PredicatePtr& thePredicate )
3260 std::string newName;
3261 if ( !theName || !theName[0] )
3263 std::set< std::string > presentNames;
3264 std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
3265 for ( ; i_gr != _mapGroups.end(); ++i_gr )
3267 CORBA::String_var name = i_gr->second->GetName();
3268 presentNames.insert( name.in() );
3271 newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
3272 } while ( !presentNames.insert( newName ).second );
3273 theName = newName.c_str();
3275 SMESH::SMESH_GroupBase_var aGroup;
3276 if ( SMESH_Group* g = _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName,
3277 theID, theShape, thePredicate ))
3279 int anId = g->GetID();
3280 SMESH_GroupBase_i* aGroupImpl;
3281 if ( !theShape.IsNull() )
3282 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3283 else if ( thePredicate )
3284 aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
3286 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3288 aGroup = aGroupImpl->_this();
3289 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3290 aGroupImpl->Register();
3292 // register CORBA object for persistence
3293 int nextId = _gen_i->RegisterObject( aGroup );
3294 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
3295 else { nextId = ( nextId > 0 ); } // avoid "unused variable" warning in release mode
3297 // to track changes of GEOM groups
3298 if ( !theShape.IsNull() ) {
3299 GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
3300 addGeomGroupData( geom, aGroup );
3303 return aGroup._retn();
3306 //=============================================================================
3308 * SMESH_Mesh_i::removeGroup
3310 * Should be called by ~SMESH_Group_i()
3312 //=============================================================================
3314 void SMESH_Mesh_i::removeGroup( const int theId )
3316 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
3317 if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
3318 SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
3319 _mapGroups.erase( theId );
3320 removeGeomGroupData( group );
3321 if ( !_impl->RemoveGroup( theId ))
3323 // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
3324 RemoveGroup( group );
3326 group->UnRegister();
3330 //================================================================================
3332 * \brief Return a log that can be used to move another mesh to the same state as this one
3334 //================================================================================
3336 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
3338 SMESH::log_array_var aLog;
3342 _preMeshInfo->FullLoadFromFile();
3344 list < SMESHDS_Command * >logDS = _impl->GetLog();
3345 aLog = new SMESH::log_array;
3347 int lg = logDS.size();
3349 list < SMESHDS_Command * >::iterator its = logDS.begin();
3350 while(its != logDS.end()){
3351 SMESHDS_Command *com = *its;
3352 int comType = com->GetType();
3353 smIdType lgcom = com->GetNumber();
3354 const list < smIdType >&intList = com->GetIndexes();
3355 int inum = intList.size();
3356 list < smIdType >::const_iterator ii = intList.begin();
3357 const list < double >&coordList = com->GetCoords();
3358 int rnum = coordList.size();
3359 list < double >::const_iterator ir = coordList.begin();
3360 aLog[indexLog].commandType = comType;
3361 aLog[indexLog].number = lgcom;
3362 aLog[indexLog].coords.length(rnum);
3363 aLog[indexLog].indexes.length(inum);
3364 for(int i = 0; i < rnum; i++){
3365 aLog[indexLog].coords[i] = *ir;
3368 for(int i = 0; i < inum; i++){
3369 aLog[indexLog].indexes[i] = *ii;
3378 SMESH_CATCH( SMESH::throwCorbaException );
3380 return aLog._retn();
3383 //================================================================================
3385 * \brief Remove the log of commands
3387 //================================================================================
3389 void SMESH_Mesh_i::ClearLog()
3393 SMESH_CATCH( SMESH::throwCorbaException );
3396 //================================================================================
3398 * \brief Return a mesh ID
3400 //================================================================================
3402 CORBA::Long SMESH_Mesh_i::GetId()
3407 //=============================================================================
3410 //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
3411 // issue 0020918: groups removal is caused by hyp modification
3412 // issue 0021208: to forget not loaded mesh data at hyp modification
3413 struct TCallUp_i : public SMESH_Mesh::TCallUp
3415 SMESH_Mesh_i* _mesh;
3416 TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
3417 void RemoveGroup (const int theGroupID) override { _mesh->removeGroup( theGroupID ); }
3418 void HypothesisModified( int hypID,
3419 bool updIcons) override { _mesh->onHypothesisModified( hypID,
3421 void Load () override { _mesh->Load(); }
3422 bool IsLoaded() override { return _mesh->IsLoaded(); }
3423 TopoDS_Shape GetShapeByEntry(const std::string& entry) override
3425 GEOM::GEOM_Object_var go = SMESH_Gen_i::GetGeomObjectByEntry( entry );
3426 return SMESH_Gen_i::GeomObjectToShape( go );
3431 //================================================================================
3433 * \brief callback from _impl to
3434 * 1) forget not loaded mesh data (issue 0021208)
3435 * 2) mark hypothesis as valid
3437 //================================================================================
3439 void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons)
3442 _preMeshInfo->ForgetOrLoad();
3444 if ( theUpdateIcons )
3446 SMESH::SMESH_Mesh_var mesh = _this();
3447 _gen_i->UpdateIcons( mesh );
3450 if ( _nbInvalidHypos != 0 )
3452 // mark a hypothesis as valid after edition
3454 SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
3455 SALOMEDS::SObject_wrap hypRoot;
3456 if ( !smeshComp->_is_nil() &&
3457 smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
3459 SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
3460 for ( ; anIter->More(); anIter->Next() )
3462 SALOMEDS::SObject_wrap hypSO = anIter->Value();
3463 CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO );
3464 SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
3465 if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
3466 _gen_i->HighLightInvalid( hyp, false );
3468 nbInvalid += _gen_i->IsInvalid( hypSO );
3471 _nbInvalidHypos = nbInvalid;
3475 //================================================================================
3477 * \brief Set mesh implementation
3479 //================================================================================
3481 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
3483 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
3486 _impl->SetCallUp( new TCallUp_i(this));
3489 //=============================================================================
3491 * Return a mesh implementation
3493 //=============================================================================
3495 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
3497 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
3501 //=============================================================================
3503 * Return mesh editor
3505 //=============================================================================
3507 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
3509 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3513 _preMeshInfo->FullLoadFromFile();
3515 // Create MeshEditor
3517 _editor = new SMESH_MeshEditor_i( this, false );
3518 aMeshEdVar = _editor->_this();
3520 // Update Python script
3521 TPythonDump() << _editor << " = "
3522 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
3524 SMESH_CATCH( SMESH::throwCorbaException );
3526 return aMeshEdVar._retn();
3529 //=============================================================================
3531 * Return mesh edition previewer
3533 //=============================================================================
3535 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
3537 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3541 _preMeshInfo->FullLoadFromFile();
3543 if ( !_previewEditor )
3544 _previewEditor = new SMESH_MeshEditor_i( this, true );
3545 aMeshEdVar = _previewEditor->_this();
3547 SMESH_CATCH( SMESH::throwCorbaException );
3549 return aMeshEdVar._retn();
3552 //================================================================================
3554 * \brief Return true if the mesh has been edited since a last total re-compute
3555 * and those modifications may prevent successful partial re-compute
3557 //================================================================================
3559 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard()
3561 Unexpect aCatch(SALOME_SalomeException);
3562 return _impl->HasModificationsToDiscard();
3565 //================================================================================
3567 * \brief Return a random unique color
3569 //================================================================================
3571 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
3573 const int MAX_ATTEMPTS = 100;
3575 double tolerance = 0.5;
3576 SALOMEDS::Color col;
3580 // generate random color
3581 double red = (double)rand() / RAND_MAX;
3582 double green = (double)rand() / RAND_MAX;
3583 double blue = (double)rand() / RAND_MAX;
3584 // check existence in the list of the existing colors
3585 bool matched = false;
3586 std::list<SALOMEDS::Color>::const_iterator it;
3587 for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
3588 SALOMEDS::Color color = *it;
3589 double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B - blue );
3590 matched = tol < tolerance;
3592 if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
3593 ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
3601 //=============================================================================
3603 * Set auto-color mode. If it is on, groups get unique random colors
3605 //=============================================================================
3607 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor)
3609 Unexpect aCatch(SALOME_SalomeException);
3610 _impl->SetAutoColor(theAutoColor);
3612 TPythonDump pyDump; // not to dump group->SetColor() from below code
3613 pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
3615 std::list<SALOMEDS::Color> aReservedColors;
3616 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
3617 for ( ; it != _mapGroups.end(); it++ ) {
3618 if ( CORBA::is_nil( it->second )) continue;
3619 SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
3620 it->second->SetColor( aColor );
3621 aReservedColors.push_back( aColor );
3625 //=============================================================================
3627 * Return true if auto-color mode is on
3629 //=============================================================================
3631 CORBA::Boolean SMESH_Mesh_i::GetAutoColor()
3633 Unexpect aCatch(SALOME_SalomeException);
3634 return _impl->GetAutoColor();
3637 //=============================================================================
3639 * Check if there are groups with equal names
3641 //=============================================================================
3643 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
3645 return _impl->HasDuplicatedGroupNamesMED();
3648 //================================================================================
3650 * \brief Care of a file before exporting mesh into it
3652 //================================================================================
3654 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
3656 SMESH_File aFile( file, false );
3658 if ( aFile.exists() ) {
3659 // existing filesystem node
3660 if ( !aFile.isDirectory() ) {
3661 if ( aFile.openForWriting() ) {
3662 if ( overwrite && ! aFile.remove()) {
3663 msg << "Can't replace " << aFile.getName();
3666 msg << "Can't write into " << aFile.getName();
3669 msg << "Location " << aFile.getName() << " is not a file";
3673 // nonexisting file; check if it can be created
3674 if ( !aFile.openForWriting() ) {
3675 msg << "You cannot create the file "
3677 << ". Check the directory existence and access rights";
3685 THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
3692 std::string SMESH_Mesh_i::generateMeshName()
3694 string aMeshName = "Mesh";
3695 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3696 if ( !aStudy->_is_nil() )
3698 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3699 if ( !aMeshSO->_is_nil() )
3701 CORBA::String_var name = aMeshSO->GetName();
3708 //================================================================================
3710 * \brief Prepare a file for export and pass names of mesh groups from study to mesh DS
3711 * \param file - file name
3712 * \param overwrite - to erase the file or not
3713 * \retval string - mesh name
3715 //================================================================================
3717 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char* file,
3718 CORBA::Boolean overwrite)
3721 PrepareForWriting(file, overwrite);
3722 string aMeshName(this->generateMeshName());
3723 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3724 if ( !aStudy->_is_nil() ) {
3725 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3726 if ( !aMeshSO->_is_nil() ) {
3727 // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
3728 if ( !aStudy->GetProperties()->IsLocked() )
3730 SALOMEDS::GenericAttribute_wrap anAttr;
3731 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3732 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
3733 SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
3734 ASSERT(!aFileName->_is_nil());
3735 aFileName->SetValue(file);
3736 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
3737 SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
3738 ASSERT(!aFileType->_is_nil());
3739 aFileType->SetValue("FICHIERMED");
3743 // Update Python script
3744 // set name of mesh before export
3745 TPythonDump() << _gen_i << ".SetName("
3746 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
3748 // check names of groups
3754 //================================================================================
3756 * \brief Export to MED file
3758 //================================================================================
3760 void SMESH_Mesh_i::ExportMED(const char* file,
3761 CORBA::Boolean auto_groups,
3762 CORBA::Long version,
3763 CORBA::Boolean overwrite,
3764 CORBA::Boolean autoDimension)
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 << "version=" << version << ", "
3778 << "overwrite=" << overwrite << ", "
3779 << "meshPart=None, "
3780 << "autoDimension=" << autoDimension << " )";
3782 SMESH_CATCH( SMESH::throwCorbaException );
3785 CORBA::LongLong SMESH_Mesh_i::ExportMEDCoupling(CORBA::Boolean auto_groups, CORBA::Boolean autoDimension)
3787 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> data;
3789 // TODO : Fix me ! 2 next lines are required
3790 if( !this->_gen_i->isSSLMode() )
3791 SMESH::throwCorbaException("SMESH_Mesh_i::ExportMEDCoupling : only for embedded mode !");
3793 _preMeshInfo->FullLoadFromFile();
3795 string aMeshName = this->generateMeshName();
3796 data = _impl->ExportMEDCoupling( aMeshName.c_str(), auto_groups, 0, autoDimension );
3797 SMESH_CATCH( SMESH::throwCorbaException );
3798 MEDCoupling::DataArrayByte *ret(data.retn());
3799 return reinterpret_cast<CORBA::LongLong>(ret);
3802 //================================================================================
3804 * \brief Export a mesh to a DAT file
3806 //================================================================================
3808 void SMESH_Mesh_i::ExportDAT (const char *file, CORBA::Boolean renumber )
3812 _preMeshInfo->FullLoadFromFile();
3814 // check names of groups
3816 // Update Python script
3817 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3818 << ".ExportDAT( r'" << file<< ", " << renumber << "' )";
3821 PrepareForWriting( file );
3822 _impl->ExportDAT( file, /*part=*/nullptr, renumber );
3824 SMESH_CATCH( SMESH::throwCorbaException );
3827 //================================================================================
3829 * \brief Export a mesh to an UNV file
3831 //================================================================================
3833 void SMESH_Mesh_i::ExportUNV (const char *file, CORBA::Boolean renumber)
3837 _preMeshInfo->FullLoadFromFile();
3839 // check names of groups
3841 // Update Python script
3842 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3843 << ".ExportUNV( r'" << file << "' " << renumber << "' )";
3846 PrepareForWriting( file );
3847 _impl->ExportUNV( file, /*part=*/nullptr, renumber );
3849 SMESH_CATCH( SMESH::throwCorbaException );
3852 //================================================================================
3854 * \brief Export a mesh to an STL file
3856 //================================================================================
3858 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3862 _preMeshInfo->FullLoadFromFile();
3864 // check names of groups
3866 // Update Python script
3867 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3868 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3870 CORBA::String_var name;
3871 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( _this() );
3872 if ( !so->_is_nil() )
3873 name = so->GetName();
3876 PrepareForWriting( file );
3877 _impl->ExportSTL( file, isascii, name.in() );
3879 SMESH_CATCH( SMESH::throwCorbaException );
3882 //================================================================================
3887 MEDFileSpeCls(const char * file,
3888 CORBA::Boolean overwrite,
3889 CORBA::Long version)
3890 :_file(file), _overwrite(overwrite), _version(version)
3892 std::string prepareMeshNameAndGroups(SMESH_Mesh_i& self)
3894 return self.prepareMeshNameAndGroups(_file.c_str(),_overwrite);
3897 void exportTo(SMESH_Mesh *mesh, const std::string& aMeshName, CORBA::Boolean auto_groups,
3898 SMESH_MeshPartDS* partDS, CORBA::Boolean autoDimension, bool have0dField,
3899 CORBA::Double ZTolerance, CORBA::Boolean saveNumbers )
3901 mesh->ExportMED( _file.c_str(), aMeshName.c_str(), auto_groups, _version,
3902 partDS, autoDimension, have0dField, ZTolerance, saveNumbers );
3905 void exportField(SMESH_Mesh_i& self, const std::string& aMeshName, bool have0dField,
3906 SMESHDS_Mesh *meshDS, const GEOM::ListOfFields& fields,
3907 const char*geomAssocFields)
3909 DriverMED_W_Field fieldWriter;
3910 fieldWriter.SetFile( _file.c_str() );
3911 fieldWriter.SetMeshName( aMeshName );
3912 fieldWriter.AddODOnVertices( have0dField );
3913 self.exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3916 void prepareForWriting(SMESH_Mesh_i& self) { self.PrepareForWriting(_file.c_str(), _overwrite); }
3920 CORBA::Boolean _overwrite;
3921 CORBA::Long _version;
3924 //================================================================================
3926 * \brief Export a part of mesh to a med file
3928 //================================================================================
3930 template<class SPECLS>
3931 void SMESH_Mesh_i::ExportPartToMEDCommon(SPECLS& speCls,
3932 SMESH::SMESH_IDSource_ptr meshPart,
3933 CORBA::Boolean auto_groups,
3934 CORBA::Boolean autoDimension,
3935 const GEOM::ListOfFields& fields,
3936 const char* geomAssocFields,
3937 CORBA::Double ZTolerance,
3938 CORBA::Boolean saveNumbers)
3942 _preMeshInfo->FullLoadFromFile();
3945 bool have0dField = false;
3946 if ( fields.length() > 0 )
3948 GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3949 if ( shapeToMesh->_is_nil() )
3950 THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3952 for ( size_t i = 0; i < fields.length(); ++i )
3954 if ( fields[i]->GetDataType() == GEOM::FDT_String )
3955 THROW_SALOME_CORBA_EXCEPTION
3956 ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3957 GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3958 if ( fieldShape->_is_nil() )
3959 THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3960 if ( !fieldShape->IsSame( shapeToMesh ) )
3961 THROW_SALOME_CORBA_EXCEPTION( "Field defined not on shape", SALOME::BAD_PARAM);
3962 if ( fields[i]->GetDimension() == 0 )
3965 if ( geomAssocFields )
3966 for ( int i = 0; geomAssocFields[i]; ++i )
3967 switch ( geomAssocFields[i] ) {
3968 case 'v':case 'e':case 'f':case 's': break;
3969 case 'V':case 'E':case 'F':case 'S': break;
3970 default: THROW_SALOME_CORBA_EXCEPTION
3971 ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3975 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3979 string aMeshName = "Mesh";
3980 SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3981 if ( CORBA::is_nil( meshPart ) ||
3982 SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3984 aMeshName = speCls.prepareMeshNameAndGroups(*this);
3985 speCls.exportTo(_impl, aMeshName, auto_groups, nullptr, autoDimension,
3986 have0dField, ZTolerance, saveNumbers );
3987 meshDS = _impl->GetMeshDS();
3992 _preMeshInfo->FullLoadFromFile();
3994 speCls.prepareForWriting(*this);
3996 SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( meshPart );
3997 if ( !SO->_is_nil() ) {
3998 CORBA::String_var name = SO->GetName();
4002 SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
4003 speCls.exportTo(_impl, aMeshName, auto_groups, partDS, autoDimension,
4004 have0dField, ZTolerance, saveNumbers);
4005 meshDS = tmpDSDeleter._obj = partDS;
4010 if ( _impl->HasShapeToMesh() )
4012 speCls.exportField( *this, aMeshName, have0dField, meshDS, fields, geomAssocFields);
4014 SMESH_CATCH( SMESH::throwCorbaException );
4017 //================================================================================
4019 * \brief Export a part of mesh to a med file
4021 //================================================================================
4023 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
4025 CORBA::Boolean auto_groups,
4026 CORBA::Long version,
4027 CORBA::Boolean overwrite,
4028 CORBA::Boolean autoDimension,
4029 const GEOM::ListOfFields& fields,
4030 const char* geomAssocFields,
4031 CORBA::Double ZTolerance,
4032 CORBA::Boolean saveNumbers)
4034 MESSAGE("MED version: "<< version);
4036 MEDFileSpeCls spe( file, overwrite, version );
4037 this->ExportPartToMEDCommon( spe, meshPart, auto_groups, autoDimension, fields,
4038 geomAssocFields, ZTolerance, saveNumbers );
4041 GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
4042 goList->length( fields.length() );
4043 for ( size_t i = 0; i < fields.length(); ++i )
4045 GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
4048 TPythonDump() << _this() << ".ExportPartToMED( "
4049 << meshPart << ", r'"
4051 << auto_groups << ", "
4053 << overwrite << ", "
4054 << autoDimension << ", "
4056 << ( geomAssocFields ? geomAssocFields : "" ) << "',"
4057 << TVar( ZTolerance ) << ", "
4060 SMESH_CATCH( SMESH::throwCorbaException );
4063 //================================================================================
4065 class MEDFileMemSpeCls
4068 std::string prepareMeshNameAndGroups(SMESH_Mesh_i& self) { return self.generateMeshName(); }
4070 void exportTo(SMESH_Mesh *mesh, const std::string& aMeshName, CORBA::Boolean auto_groups,
4071 SMESH_MeshPartDS* partDS, CORBA::Boolean autoDimension, bool have0dField,
4072 CORBA::Double ZTolerance, CORBA::Boolean saveNumbers )
4074 _res = mesh->ExportMEDCoupling(aMeshName.c_str(), auto_groups, partDS,
4075 autoDimension, have0dField, ZTolerance, saveNumbers );
4077 void prepareForWriting(SMESH_Mesh_i& /*self*/) { /* nothing here */ }
4079 void exportField(SMESH_Mesh_i& self, const std::string& aMeshName, bool have0dField,
4080 SMESHDS_Mesh *meshDS, const GEOM::ListOfFields& fields,
4081 const char*geomAssocFields)
4083 DriverMED_W_Field_Mem fieldWriter(_res);
4084 fieldWriter.SetMeshName( aMeshName );
4085 fieldWriter.AddODOnVertices( have0dField );
4086 self.exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
4087 _res = fieldWriter.getData();
4090 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> getData() { return _res; }
4093 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> _res;
4096 //================================================================================
4098 * \brief Export a part of mesh to a MEDCoupling DS
4100 //================================================================================
4102 CORBA::LongLong SMESH_Mesh_i::ExportPartToMEDCoupling(SMESH::SMESH_IDSource_ptr meshPart,
4103 CORBA::Boolean auto_groups,
4104 CORBA::Boolean autoDimension,
4105 const GEOM::ListOfFields& fields,
4106 const char* geomAssocFields,
4107 CORBA::Double ZTolerance,
4108 CORBA::Boolean saveNumbers)
4110 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> data;
4113 if( !this->_gen_i->isSSLMode() )
4114 SMESH::throwCorbaException("SMESH_Mesh_i::ExportPartToMEDCoupling : only for embedded mode !");
4116 MEDFileMemSpeCls spe;
4117 this->ExportPartToMEDCommon( spe, meshPart, auto_groups, autoDimension, fields, geomAssocFields,
4118 ZTolerance, saveNumbers );
4119 data = spe.getData();
4121 SMESH_CATCH( SMESH::throwCorbaException );
4123 MEDCoupling::DataArrayByte *ret(data.retn());
4124 return reinterpret_cast<CORBA::LongLong>(ret);
4127 //================================================================================
4129 * Write GEOM fields to MED file
4131 //================================================================================
4133 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field& fieldWriter,
4134 SMESHDS_Mesh* meshDS,
4135 const GEOM::ListOfFields& fields,
4136 const char* geomAssocFields)
4138 #define METH "SMESH_Mesh_i::exportMEDFields() "
4140 if (( fields.length() < 1 ) &&
4141 ( !geomAssocFields || !geomAssocFields[0] ))
4144 std::vector< std::vector< double > > dblVals;
4145 std::vector< std::vector< int > > intVals;
4146 std::vector< int > subIdsByDim[ 4 ];
4147 const double noneDblValue = 0.;
4148 const double noneIntValue = 0;
4150 for ( size_t iF = 0; iF < fields.length(); ++iF )
4154 int dim = fields[ iF ]->GetDimension();
4155 SMDSAbs_ElementType elemType;
4156 TopAbs_ShapeEnum shapeType;
4158 case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
4159 case 1: elemType = SMDSAbs_Edge; shapeType = TopAbs_EDGE; break;
4160 case 2: elemType = SMDSAbs_Face; shapeType = TopAbs_FACE; break;
4161 case 3: elemType = SMDSAbs_Volume; shapeType = TopAbs_SOLID; break;
4163 continue; // skip fields on whole shape
4165 GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
4166 if ( dataType == GEOM::FDT_String )
4168 GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
4169 if ( stepIDs->length() < 1 )
4171 GEOM::string_array_var comps = fields[ iF ]->GetComponents();
4172 if ( comps->length() < 1 )
4174 CORBA::String_var name = fields[ iF ]->GetName();
4176 if ( !fieldWriter.Set( meshDS,
4180 /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
4183 for ( size_t iC = 0; iC < comps->length(); ++iC )
4184 fieldWriter.SetCompName( iC, comps[ iC ].in() );
4186 dblVals.resize( comps->length() );
4187 intVals.resize( comps->length() );
4189 // find sub-shape IDs
4191 std::vector< int >& subIds = subIdsByDim[ dim ];
4192 if ( subIds.empty() )
4193 for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
4194 if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
4195 subIds.push_back( id );
4199 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4203 for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
4205 GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
4206 if ( step->_is_nil() )
4209 CORBA::Long stamp = step->GetStamp();
4210 CORBA::Long id = step->GetID();
4211 fieldWriter.SetDtIt( int( stamp ), int( id ));
4213 // fill dblVals or intVals
4214 for ( size_t iC = 0; iC < comps->length(); ++iC )
4215 if ( dataType == GEOM::FDT_Double )
4217 dblVals[ iC ].clear();
4218 dblVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4222 intVals[ iC ].clear();
4223 intVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4227 case GEOM::FDT_Double:
4229 GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
4230 if ( dblStep->_is_nil() ) continue;
4231 GEOM::ListOfDouble_var vv = dblStep->GetValues();
4232 if ( vv->length() != subIds.size() * comps->length() )
4233 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4234 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4235 for ( size_t iC = 0; iC < comps->length(); ++iC )
4236 dblVals[ iC ][ subIds[ iS ]] = vv[ iV++ ];
4241 GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
4242 if ( intStep->_is_nil() ) continue;
4243 GEOM::ListOfLong_var vv = intStep->GetValues();
4244 if ( vv->length() != subIds.size() * comps->length() )
4245 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4246 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4247 for ( size_t iC = 0; iC < comps->length(); ++iC )
4248 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4251 case GEOM::FDT_Bool:
4253 GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
4254 if ( boolStep->_is_nil() ) continue;
4255 GEOM::short_array_var vv = boolStep->GetValues();
4256 if ( vv->length() != subIds.size() * comps->length() )
4257 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4258 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4259 for ( size_t iC = 0; iC < comps->length(); ++iC )
4260 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4266 // pass values to fieldWriter
4267 elemIt = fieldWriter.GetOrderedElems();
4268 if ( dataType == GEOM::FDT_Double )
4269 while ( elemIt->more() )
4271 const SMDS_MeshElement* e = elemIt->next();
4272 const int shapeID = e->getshapeId();
4273 if ( shapeID < 1 || shapeID >= (int) dblVals[0].size() )
4274 for ( size_t iC = 0; iC < comps->length(); ++iC )
4275 fieldWriter.AddValue( noneDblValue );
4277 for ( size_t iC = 0; iC < comps->length(); ++iC )
4278 fieldWriter.AddValue( dblVals[ iC ][ shapeID ]);
4281 while ( elemIt->more() )
4283 const SMDS_MeshElement* e = elemIt->next();
4284 const int shapeID = e->getshapeId();
4285 if ( shapeID < 1 || shapeID >= (int) intVals[0].size() )
4286 for ( size_t iC = 0; iC < comps->length(); ++iC )
4287 fieldWriter.AddValue( (double) noneIntValue );
4289 for ( size_t iC = 0; iC < comps->length(); ++iC )
4290 fieldWriter.AddValue( (double) intVals[ iC ][ shapeID ]);
4294 fieldWriter.Perform();
4295 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4296 if ( res && res->IsKO() )
4298 if ( res->myComment.empty() )
4299 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4301 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4307 if ( !geomAssocFields || !geomAssocFields[0] )
4310 // write geomAssocFields
4312 std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
4313 shapeDim[ TopAbs_COMPOUND ] = 3;
4314 shapeDim[ TopAbs_COMPSOLID ] = 3;
4315 shapeDim[ TopAbs_SOLID ] = 3;
4316 shapeDim[ TopAbs_SHELL ] = 2;
4317 shapeDim[ TopAbs_FACE ] = 2;
4318 shapeDim[ TopAbs_WIRE ] = 1;
4319 shapeDim[ TopAbs_EDGE ] = 1;
4320 shapeDim[ TopAbs_VERTEX ] = 0;
4321 shapeDim[ TopAbs_SHAPE ] = 3;
4323 for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
4325 std::vector< std::string > compNames;
4326 switch ( geomAssocFields[ iF ]) {
4328 fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
4329 compNames.push_back( "dim" );
4332 fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
4335 fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
4338 fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
4342 compNames.push_back( "id" );
4343 for ( size_t iC = 0; iC < compNames.size(); ++iC )
4344 fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
4346 fieldWriter.SetDtIt( -1, -1 );
4348 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4352 if ( compNames.size() == 2 ) // _vertices_
4353 while ( elemIt->more() )
4355 const SMDS_MeshElement* e = elemIt->next();
4356 const int shapeID = e->getshapeId();
4359 fieldWriter.AddValue( (double) -1 );
4360 fieldWriter.AddValue( (double) -1 );
4364 const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
4365 fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
4366 fieldWriter.AddValue( (double) shapeID );
4370 while ( elemIt->more() )
4372 const SMDS_MeshElement* e = elemIt->next();
4373 const int shapeID = e->getshapeId();
4375 fieldWriter.AddValue( (double) -1 );
4377 fieldWriter.AddValue( (double) shapeID );
4381 fieldWriter.Perform();
4382 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4383 if ( res && res->IsKO() )
4385 if ( res->myComment.empty() )
4386 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4388 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4391 } // loop on geomAssocFields
4396 //================================================================================
4398 * \brief Export a part of mesh to a DAT file
4400 //================================================================================
4402 void SMESH_Mesh_i::ExportPartToDAT(SMESH::SMESH_IDSource_ptr meshPart,
4404 CORBA::Boolean renumber )
4408 SMESH_MeshPartDS partDS( meshPart );
4409 _impl->ExportDAT( file, &partDS, renumber );
4411 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4412 << ".ExportPartToDAT( " << meshPart << ", r'" << file << ", " << renumber << "' )";
4414 SMESH_CATCH( SMESH::throwCorbaException );
4416 //================================================================================
4418 * \brief Export a part of mesh to an UNV file
4420 //================================================================================
4422 void SMESH_Mesh_i::ExportPartToUNV(SMESH::SMESH_IDSource_ptr meshPart,
4424 CORBA::Boolean renumber)
4428 _preMeshInfo->FullLoadFromFile();
4430 PrepareForWriting(file);
4432 SMESH_MeshPartDS partDS( meshPart );
4433 _impl->ExportUNV(file, &partDS, renumber );
4435 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4436 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << ", " << renumber << "' )";
4438 SMESH_CATCH( SMESH::throwCorbaException );
4440 //================================================================================
4442 * \brief Export a part of mesh to an STL file
4444 //================================================================================
4446 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
4448 ::CORBA::Boolean isascii)
4452 _preMeshInfo->FullLoadFromFile();
4454 PrepareForWriting(file);
4456 CORBA::String_var name;
4457 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4458 if ( !so->_is_nil() )
4459 name = so->GetName();
4461 SMESH_MeshPartDS partDS( meshPart );
4462 _impl->ExportSTL( file, isascii, name.in(), &partDS );
4464 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
4465 << meshPart<< ", r'" << file << "', " << isascii << ")";
4467 SMESH_CATCH( SMESH::throwCorbaException );
4470 //================================================================================
4472 * \brief Export a part of mesh to an STL file
4474 //================================================================================
4476 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
4478 CORBA::Boolean overwrite,
4479 CORBA::Boolean groupElemsByType)
4484 _preMeshInfo->FullLoadFromFile();
4486 PrepareForWriting(file,overwrite);
4488 std::string meshName("");
4489 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4490 if ( !so->_is_nil() )
4492 CORBA::String_var name = so->GetName();
4493 meshName = name.in();
4497 SMESH_MeshPartDS partDS( meshPart );
4498 _impl->ExportCGNS(file, &partDS, meshName.c_str(), groupElemsByType );
4500 SMESH_CATCH( SMESH::throwCorbaException );
4502 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
4503 << meshPart<< ", r'" << file << "', " << overwrite << ")";
4505 SMESH_CATCH( SMESH::throwCorbaException );
4508 THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
4512 //================================================================================
4514 * \brief Export a part of mesh to a GMF file
4516 //================================================================================
4518 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
4520 bool withRequiredGroups)
4524 _preMeshInfo->FullLoadFromFile();
4526 PrepareForWriting(file,/*overwrite=*/true);
4528 SMESH_MeshPartDS partDS( meshPart );
4529 _impl->ExportGMF(file, &partDS, withRequiredGroups);
4531 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
4532 << meshPart<< ", r'"
4534 << withRequiredGroups << ")";
4536 SMESH_CATCH( SMESH::throwCorbaException );
4539 //=============================================================================
4541 * Return computation progress [0.,1]
4543 //=============================================================================
4545 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
4549 return _impl->GetComputeProgress();
4551 SMESH_CATCH( SMESH::doNothing );
4555 //================================================================================
4557 * \brief Return nb of nodes
4559 //================================================================================
4561 SMESH::smIdType SMESH_Mesh_i::NbNodes()
4563 Unexpect aCatch(SALOME_SalomeException);
4565 return _preMeshInfo->NbNodes();
4567 return _impl->NbNodes();
4570 //================================================================================
4572 * \brief Return nb of elements
4574 //================================================================================
4576 SMESH::smIdType SMESH_Mesh_i::NbElements()
4578 Unexpect aCatch(SALOME_SalomeException);
4580 return _preMeshInfo->NbElements();
4582 return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
4585 //================================================================================
4587 * \brief Return nb of 0D elements
4589 //================================================================================
4591 SMESH::smIdType SMESH_Mesh_i::Nb0DElements()
4593 Unexpect aCatch(SALOME_SalomeException);
4595 return _preMeshInfo->Nb0DElements();
4597 return _impl->Nb0DElements();
4600 //================================================================================
4602 * \brief Return nb of BALL elements
4604 //================================================================================
4606 SMESH::smIdType SMESH_Mesh_i::NbBalls()
4608 Unexpect aCatch(SALOME_SalomeException);
4610 return _preMeshInfo->NbBalls();
4612 return _impl->NbBalls();
4615 //================================================================================
4617 * \brief Return nb of 1D elements
4619 //================================================================================
4621 SMESH::smIdType SMESH_Mesh_i::NbEdges()
4623 Unexpect aCatch(SALOME_SalomeException);
4625 return _preMeshInfo->NbEdges();
4627 return _impl->NbEdges();
4630 //================================================================================
4632 * \brief Return nb of edges
4634 //================================================================================
4636 SMESH::smIdType SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
4638 Unexpect aCatch(SALOME_SalomeException);
4640 return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
4642 return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
4645 //================================================================================
4647 * \brief Return nb of faces
4649 //================================================================================
4651 SMESH::smIdType SMESH_Mesh_i::NbFaces()
4653 Unexpect aCatch(SALOME_SalomeException);
4655 return _preMeshInfo->NbFaces();
4657 return _impl->NbFaces();
4660 //================================================================================
4662 * \brief Return nb of tringles
4664 //================================================================================
4666 SMESH::smIdType SMESH_Mesh_i::NbTriangles()
4668 Unexpect aCatch(SALOME_SalomeException);
4670 return _preMeshInfo->NbTriangles();
4672 return _impl->NbTriangles();
4675 //================================================================================
4677 * \brief Return nb of bi-quadratic triangles
4679 //================================================================================
4681 SMESH::smIdType SMESH_Mesh_i::NbBiQuadTriangles()
4683 Unexpect aCatch(SALOME_SalomeException);
4685 return _preMeshInfo->NbBiQuadTriangles();
4687 return _impl->NbBiQuadTriangles();
4690 SMESH::smIdType SMESH_Mesh_i::NbQuadrangles()
4692 Unexpect aCatch(SALOME_SalomeException);
4694 return _preMeshInfo->NbQuadrangles();
4696 return _impl->NbQuadrangles();
4699 SMESH::smIdType SMESH_Mesh_i::NbBiQuadQuadrangles()
4701 Unexpect aCatch(SALOME_SalomeException);
4703 return _preMeshInfo->NbBiQuadQuadrangles();
4705 return _impl->NbBiQuadQuadrangles();
4708 SMESH::smIdType SMESH_Mesh_i::NbPolygons()
4710 Unexpect aCatch(SALOME_SalomeException);
4712 return _preMeshInfo->NbPolygons();
4714 return _impl->NbPolygons();
4717 SMESH::smIdType SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order)
4719 Unexpect aCatch(SALOME_SalomeException);
4721 return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
4723 return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
4726 SMESH::smIdType SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
4728 Unexpect aCatch(SALOME_SalomeException);
4730 return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
4732 return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
4735 SMESH::smIdType SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
4737 Unexpect aCatch(SALOME_SalomeException);
4739 return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
4741 return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
4744 SMESH::smIdType SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
4746 Unexpect aCatch(SALOME_SalomeException);
4748 return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
4750 return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
4753 //=============================================================================
4755 SMESH::smIdType SMESH_Mesh_i::NbVolumes()
4757 Unexpect aCatch(SALOME_SalomeException);
4759 return _preMeshInfo->NbVolumes();
4761 return _impl->NbVolumes();
4764 SMESH::smIdType SMESH_Mesh_i::NbTetras()
4766 Unexpect aCatch(SALOME_SalomeException);
4768 return _preMeshInfo->NbTetras();
4770 return _impl->NbTetras();
4773 SMESH::smIdType SMESH_Mesh_i::NbHexas()
4775 Unexpect aCatch(SALOME_SalomeException);
4777 return _preMeshInfo->NbHexas();
4779 return _impl->NbHexas();
4782 SMESH::smIdType SMESH_Mesh_i::NbTriQuadraticHexas()
4784 Unexpect aCatch(SALOME_SalomeException);
4786 return _preMeshInfo->NbTriQuadHexas();
4788 return _impl->NbTriQuadraticHexas();
4791 SMESH::smIdType SMESH_Mesh_i::NbPyramids()
4793 Unexpect aCatch(SALOME_SalomeException);
4795 return _preMeshInfo->NbPyramids();
4797 return _impl->NbPyramids();
4800 SMESH::smIdType SMESH_Mesh_i::NbPrisms()
4802 Unexpect aCatch(SALOME_SalomeException);
4804 return _preMeshInfo->NbPrisms();
4806 return _impl->NbPrisms();
4809 SMESH::smIdType SMESH_Mesh_i::NbHexagonalPrisms()
4811 Unexpect aCatch(SALOME_SalomeException);
4813 return _preMeshInfo->NbHexPrisms();
4815 return _impl->NbHexagonalPrisms();
4818 SMESH::smIdType SMESH_Mesh_i::NbPolyhedrons()
4820 Unexpect aCatch(SALOME_SalomeException);
4822 return _preMeshInfo->NbPolyhedrons();
4824 return _impl->NbPolyhedrons();
4827 SMESH::smIdType SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
4829 Unexpect aCatch(SALOME_SalomeException);
4831 return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
4833 return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
4836 SMESH::smIdType SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
4838 Unexpect aCatch(SALOME_SalomeException);
4840 return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
4842 return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
4845 SMESH::smIdType SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
4847 Unexpect aCatch(SALOME_SalomeException);
4849 return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
4851 return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
4854 SMESH::smIdType SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
4856 Unexpect aCatch(SALOME_SalomeException);
4858 return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
4860 return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
4863 SMESH::smIdType SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
4865 Unexpect aCatch(SALOME_SalomeException);
4867 return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
4869 return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
4872 //=============================================================================
4874 * Return nb of published sub-meshes
4876 //=============================================================================
4878 SMESH::smIdType SMESH_Mesh_i::NbSubMesh()
4880 Unexpect aCatch(SALOME_SalomeException);
4881 return _mapSubMesh_i.size();
4884 //=============================================================================
4886 * Dumps mesh into a string
4888 //=============================================================================
4890 char* SMESH_Mesh_i::Dump()
4894 return CORBA::string_dup( os.str().c_str() );
4897 //=============================================================================
4899 * Method of SMESH_IDSource interface
4901 //=============================================================================
4903 SMESH::smIdType_array* SMESH_Mesh_i::GetIDs()
4905 return GetElementsId();
4908 //=============================================================================
4910 * Return ids of all elements
4912 //=============================================================================
4914 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsId()
4916 Unexpect aCatch(SALOME_SalomeException);
4918 _preMeshInfo->FullLoadFromFile();
4920 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
4921 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4923 if ( aSMESHDS_Mesh == NULL )
4924 return aResult._retn();
4926 smIdType nbElements = NbElements();
4927 aResult->length( nbElements );
4928 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
4929 for ( smIdType i = 0, n = nbElements; i < n && anIt->more(); i++ )
4930 aResult[i] = anIt->next()->GetID();
4932 return aResult._retn();
4936 //=============================================================================
4938 * Return ids of all elements of given type
4940 //=============================================================================
4942 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
4944 Unexpect aCatch(SALOME_SalomeException);
4946 _preMeshInfo->FullLoadFromFile();
4948 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
4949 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4951 if ( aSMESHDS_Mesh == NULL )
4952 return aResult._retn();
4954 smIdType nbElements = NbElements();
4956 // No sense in returning ids of elements along with ids of nodes:
4957 // when theElemType == SMESH::ALL, return node ids only if
4958 // there are no elements
4959 if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
4960 return GetNodesId();
4962 aResult->length( nbElements );
4966 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
4967 while ( i < nbElements && anIt->more() )
4968 aResult[i++] = anIt->next()->GetID();
4970 aResult->length( i );
4972 return aResult._retn();
4975 //=============================================================================
4977 * Return ids of all nodes
4979 //=============================================================================
4981 SMESH::smIdType_array* SMESH_Mesh_i::GetNodesId()
4983 Unexpect aCatch(SALOME_SalomeException);
4985 _preMeshInfo->FullLoadFromFile();
4987 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
4988 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4990 if ( aMeshDS == NULL )
4991 return aResult._retn();
4993 smIdType nbNodes = NbNodes();
4994 aResult->length( nbNodes );
4995 SMDS_NodeIteratorPtr anIt = aMeshDS->nodesIterator();
4996 for ( smIdType i = 0, n = nbNodes; i < n && anIt->more(); i++ )
4997 aResult[i] = anIt->next()->GetID();
4999 return aResult._retn();
5002 //=============================================================================
5004 * Return type of the given element
5006 //=============================================================================
5008 SMESH::ElementType SMESH_Mesh_i::GetElementType( const SMESH::smIdType id, const bool iselem )
5010 SMESH::ElementType type = SMESH::ALL;
5014 _preMeshInfo->FullLoadFromFile();
5016 type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
5018 SMESH_CATCH( SMESH::throwCorbaException );
5023 //=============================================================================
5025 * Return geometric type of the given element
5027 //=============================================================================
5029 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const SMESH::smIdType id )
5032 _preMeshInfo->FullLoadFromFile();
5034 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
5036 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
5038 return ( SMESH::EntityType ) e->GetEntityType();
5041 //=============================================================================
5043 * Return type of the given element
5045 //=============================================================================
5047 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const SMESH::smIdType id )
5050 _preMeshInfo->FullLoadFromFile();
5052 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
5054 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
5056 return ( SMESH::GeometryType ) e->GetGeomType();
5059 //=============================================================================
5061 * Return ID of elements for given submesh
5063 //=============================================================================
5065 SMESH::smIdType_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
5067 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5071 _preMeshInfo->FullLoadFromFile();
5073 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5074 if(!SM) return aResult._retn();
5076 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5077 if(!SDSM) return aResult._retn();
5079 aResult->length(SDSM->NbElements());
5081 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5083 while ( eIt->more() ) {
5084 aResult[i++] = eIt->next()->GetID();
5087 SMESH_CATCH( SMESH::throwCorbaException );
5089 return aResult._retn();
5092 //=============================================================================
5094 * Return ID of nodes for given sub-mesh
5095 * If param all==true - return all nodes, else -
5096 * Return only nodes on shapes.
5098 //=============================================================================
5100 SMESH::smIdType_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
5103 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5107 _preMeshInfo->FullLoadFromFile();
5109 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5110 if(!SM) return aResult._retn();
5112 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5113 if(!SDSM) return aResult._retn();
5115 set<smIdType> theElems;
5116 if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
5117 SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
5118 while ( nIt->more() ) {
5119 const SMDS_MeshNode* elem = nIt->next();
5120 theElems.insert( elem->GetID() );
5123 else { // all nodes of submesh elements
5124 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5125 while ( eIt->more() ) {
5126 const SMDS_MeshElement* anElem = eIt->next();
5127 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
5128 while ( nIt->more() ) {
5129 const SMDS_MeshElement* elem = nIt->next();
5130 theElems.insert( elem->GetID() );
5135 aResult->length(theElems.size());
5136 set<smIdType>::iterator itElem;
5138 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
5139 aResult[i++] = *itElem;
5141 SMESH_CATCH( SMESH::throwCorbaException );
5143 return aResult._retn();
5146 //=============================================================================
5148 * Return type of elements for given sub-mesh
5150 //=============================================================================
5152 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
5154 SMESH::ElementType type = SMESH::ALL;
5158 _preMeshInfo->FullLoadFromFile();
5160 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5161 if(!SM) return SMESH::ALL;
5163 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5164 if(!SDSM) return SMESH::ALL;
5166 if(SDSM->NbElements()==0)
5167 return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
5169 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5170 const SMDS_MeshElement* anElem = eIt->next();
5172 type = ( SMESH::ElementType ) anElem->GetType();
5174 SMESH_CATCH( SMESH::throwCorbaException );
5180 //=============================================================================
5182 * Return pointer to _impl as an integer value. Is called from constructor of SMESH_Client
5184 //=============================================================================
5186 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
5189 _preMeshInfo->FullLoadFromFile();
5191 CORBA::LongLong pointeur = CORBA::LongLong(_impl);
5192 if ( MYDEBUG ) MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
5197 //=============================================================================
5199 * Get XYZ coordinates of node as list of double
5200 * If there is not node for given ID - return empty list
5202 //=============================================================================
5204 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const SMESH::smIdType id)
5207 _preMeshInfo->FullLoadFromFile();
5209 SMESH::double_array_var aResult = new SMESH::double_array();
5210 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5211 if ( aMeshDS == NULL )
5212 return aResult._retn();
5215 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5217 return aResult._retn();
5221 aResult[0] = aNode->X();
5222 aResult[1] = aNode->Y();
5223 aResult[2] = aNode->Z();
5224 return aResult._retn();
5228 //=============================================================================
5230 * For given node return list of IDs of inverse elements
5231 * If there is not node for given ID - return empty list
5233 //=============================================================================
5235 SMESH::smIdType_array* SMESH_Mesh_i::GetNodeInverseElements(const SMESH::smIdType id,
5236 SMESH::ElementType elemType)
5239 _preMeshInfo->FullLoadFromFile();
5241 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5242 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5243 if ( aMeshDS == NULL )
5244 return aResult._retn();
5247 const SMDS_MeshNode* aNode = aMeshDS->FindNode( id );
5249 return aResult._retn();
5251 // find inverse elements
5252 SMDSAbs_ElementType type = SMDSAbs_ElementType( elemType );
5253 SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator( type );
5254 aResult->length( aNode->NbInverseElements( type ));
5255 for( smIdType i = 0; eIt->more(); ++i )
5257 const SMDS_MeshElement* elem = eIt->next();
5258 aResult[ i ] = elem->GetID();
5260 return aResult._retn();
5263 //=============================================================================
5265 * \brief Return position of a node on shape
5267 //=============================================================================
5269 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(SMESH::smIdType NodeID)
5272 _preMeshInfo->FullLoadFromFile();
5274 SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
5275 aNodePosition->shapeID = 0;
5276 aNodePosition->shapeType = GEOM::SHAPE;
5278 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5279 if ( !mesh ) return aNodePosition;
5281 if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
5283 if ( SMDS_PositionPtr pos = aNode->GetPosition() )
5285 aNodePosition->shapeID = aNode->getshapeId();
5286 switch ( pos->GetTypeOfPosition() ) {
5288 aNodePosition->shapeType = GEOM::EDGE;
5289 aNodePosition->params.length(1);
5290 aNodePosition->params[0] = SMDS_EdgePositionPtr( pos )->GetUParameter();
5292 case SMDS_TOP_FACE: {
5293 SMDS_FacePositionPtr fPos = pos;
5294 aNodePosition->shapeType = GEOM::FACE;
5295 aNodePosition->params.length(2);
5296 aNodePosition->params[0] = fPos->GetUParameter();
5297 aNodePosition->params[1] = fPos->GetVParameter();
5300 case SMDS_TOP_VERTEX:
5301 aNodePosition->shapeType = GEOM::VERTEX;
5303 case SMDS_TOP_3DSPACE:
5304 if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
5305 aNodePosition->shapeType = GEOM::SOLID;
5306 else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
5307 aNodePosition->shapeType = GEOM::SHELL;
5313 return aNodePosition;
5316 //=============================================================================
5318 * \brief Return position of an element on shape
5320 //=============================================================================
5322 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(SMESH::smIdType ElemID)
5325 _preMeshInfo->FullLoadFromFile();
5327 SMESH::ElementPosition anElementPosition;
5328 anElementPosition.shapeID = 0;
5329 anElementPosition.shapeType = GEOM::SHAPE;
5331 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5332 if ( !mesh ) return anElementPosition;
5334 if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
5336 anElementPosition.shapeID = anElem->getshapeId();
5337 const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
5338 if ( !aSp.IsNull() ) {
5339 switch ( aSp.ShapeType() ) {
5341 anElementPosition.shapeType = GEOM::EDGE;
5344 anElementPosition.shapeType = GEOM::FACE;
5347 anElementPosition.shapeType = GEOM::VERTEX;
5350 anElementPosition.shapeType = GEOM::SOLID;
5353 anElementPosition.shapeType = GEOM::SHELL;
5359 return anElementPosition;
5362 //=============================================================================
5364 * If given element is node return IDs of shape from position
5365 * If there is not node for given ID - return -1
5367 //=============================================================================
5369 CORBA::Long SMESH_Mesh_i::GetShapeID(const SMESH::smIdType id)
5372 _preMeshInfo->FullLoadFromFile();
5374 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5375 if ( aMeshDS == NULL )
5379 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5381 return aNode->getshapeId();
5388 //=============================================================================
5390 * For given element return ID of result shape after
5391 * ::FindShape() from SMESH_MeshEditor
5392 * If there is not element for given ID - return -1
5394 //=============================================================================
5396 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const SMESH::smIdType id)
5399 _preMeshInfo->FullLoadFromFile();
5401 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5402 if ( aMeshDS == NULL )
5405 // try to find element
5406 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5410 ::SMESH_MeshEditor aMeshEditor(_impl);
5411 int index = aMeshEditor.FindShape( elem );
5419 //=============================================================================
5421 * Return number of nodes for given element
5422 * If there is not element for given ID - return -1
5424 //=============================================================================
5426 CORBA::Short SMESH_Mesh_i::GetElemNbNodes(const SMESH::smIdType id)
5429 _preMeshInfo->FullLoadFromFile();
5431 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5432 if ( aMeshDS == NULL ) return -1;
5433 // try to find element
5434 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5435 if(!elem) return -1;
5436 return elem->NbNodes();
5440 //=============================================================================
5442 * Return ID of node by given index for given element
5443 * If there is not element for given ID - return -1
5444 * If there is not node for given index - return -2
5446 //=============================================================================
5448 SMESH::smIdType SMESH_Mesh_i::GetElemNode(const SMESH::smIdType id, const CORBA::Short index)
5451 _preMeshInfo->FullLoadFromFile();
5453 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5454 if ( aMeshDS == NULL ) return -1;
5455 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5456 if(!elem) return -1;
5457 if( index>=elem->NbNodes() || index<0 ) return -1;
5458 return elem->GetNode(index)->GetID();
5461 //=============================================================================
5463 * Return IDs of nodes of given element
5465 //=============================================================================
5467 SMESH::smIdType_array* SMESH_Mesh_i::GetElemNodes(const SMESH::smIdType id)
5470 _preMeshInfo->FullLoadFromFile();
5472 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5473 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5475 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(id) )
5477 aResult->length( elem->NbNodes() );
5478 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5479 if ( const SMDS_MeshNode* n = elem->GetNode( i ))
5480 aResult[ i ] = n->GetID();
5483 return aResult._retn();
5486 //=============================================================================
5488 * Return true if given node is medium node
5489 * in given quadratic element
5491 //=============================================================================
5493 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const SMESH::smIdType ide, const SMESH::smIdType idn)
5496 _preMeshInfo->FullLoadFromFile();
5498 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5499 if ( aMeshDS == NULL ) return false;
5501 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5502 if(!aNode) return false;
5503 // try to find element
5504 const SMDS_MeshElement* elem = aMeshDS->FindElement(ide);
5505 if(!elem) return false;
5507 return elem->IsMediumNode(aNode);
5511 //=============================================================================
5513 * Return true if given node is medium node
5514 * in one of quadratic elements
5516 //=============================================================================
5518 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const SMESH::smIdType idn,
5519 SMESH::ElementType theElemType)
5522 _preMeshInfo->FullLoadFromFile();
5524 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5525 if ( aMeshDS == NULL ) return false;
5528 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5529 if(!aNode) return false;
5531 SMESH_MesherHelper aHelper( *(_impl) );
5533 SMDSAbs_ElementType aType;
5534 if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
5535 else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
5536 else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
5537 else aType = SMDSAbs_All;
5539 return aHelper.IsMedium(aNode,aType);
5543 //=============================================================================
5545 * Return number of edges for given element
5547 //=============================================================================
5549 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const SMESH::smIdType id)
5552 _preMeshInfo->FullLoadFromFile();
5554 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5555 if ( aMeshDS == NULL ) return -1;
5556 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5557 if(!elem) return -1;
5558 return elem->NbEdges();
5562 //=============================================================================
5564 * Return number of faces for given element
5566 //=============================================================================
5568 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const SMESH::smIdType id)
5571 _preMeshInfo->FullLoadFromFile();
5573 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5574 if ( aMeshDS == NULL ) return -1;
5575 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5576 if(!elem) return -1;
5577 return elem->NbFaces();
5580 //================================================================================
5582 * \brief Return nodes of given face (counted from zero) for given element.
5584 //================================================================================
5586 SMESH::smIdType_array* SMESH_Mesh_i::GetElemFaceNodes(SMESH::smIdType elemId,
5587 CORBA::Short faceIndex)
5590 _preMeshInfo->FullLoadFromFile();
5592 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5593 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5595 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) )
5597 SMDS_VolumeTool vtool( elem, /*skipCentralNodes = */false );
5598 if ( faceIndex < vtool.NbFaces() )
5600 aResult->length( vtool.NbFaceNodes( faceIndex ));
5601 const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
5602 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5603 aResult[ i ] = nn[ i ]->GetID();
5607 return aResult._retn();
5610 //================================================================================
5612 * \brief Return three components of normal of given mesh face.
5614 //================================================================================
5616 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long elemId,
5617 CORBA::Boolean normalized)
5620 _preMeshInfo->FullLoadFromFile();
5622 SMESH::double_array_var aResult = new SMESH::double_array();
5624 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5627 if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
5629 aResult->length( 3 );
5630 aResult[ 0 ] = normal.X();
5631 aResult[ 1 ] = normal.Y();
5632 aResult[ 2 ] = normal.Z();
5635 return aResult._retn();
5638 //================================================================================
5640 * \brief Return an element based on all given nodes.
5642 //================================================================================
5644 SMESH::smIdType SMESH_Mesh_i::FindElementByNodes(const SMESH::smIdType_array& nodes)
5647 _preMeshInfo->FullLoadFromFile();
5649 CORBA::Long elemID(0);
5650 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5652 vector< const SMDS_MeshNode * > nn( nodes.length() );
5653 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5654 if ( !( nn[i] = mesh->FindNode( nodes[i] )))
5657 const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
5658 if ( !elem && ( _impl->NbEdges ( ORDER_QUADRATIC ) ||
5659 _impl->NbFaces ( ORDER_QUADRATIC ) ||
5660 _impl->NbVolumes( ORDER_QUADRATIC )))
5661 elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
5663 if ( elem ) elemID = CORBA::Long( elem->GetID() );
5668 //================================================================================
5670 * \brief Return elements including all given nodes.
5672 //================================================================================
5674 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsByNodes(const SMESH::smIdType_array& nodes,
5675 SMESH::ElementType elemType)
5678 _preMeshInfo->FullLoadFromFile();
5680 SMESH::smIdType_array_var result = new SMESH::smIdType_array();
5682 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5684 vector< const SMDS_MeshNode * > nn( nodes.length() );
5685 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5686 nn[i] = mesh->FindNode( nodes[i] );
5688 std::vector<const SMDS_MeshElement *> elems;
5689 mesh->GetElementsByNodes( nn, elems, (SMDSAbs_ElementType) elemType );
5690 result->length( elems.size() );
5691 for ( size_t i = 0; i < elems.size(); ++i )
5692 result[i] = elems[i]->GetID();
5694 return result._retn();
5697 //=============================================================================
5699 * Return true if given element is polygon
5701 //=============================================================================
5703 CORBA::Boolean SMESH_Mesh_i::IsPoly(const SMESH::smIdType id)
5706 _preMeshInfo->FullLoadFromFile();
5708 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5709 if ( aMeshDS == NULL ) return false;
5710 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5711 if(!elem) return false;
5712 return elem->IsPoly();
5716 //=============================================================================
5718 * Return true if given element is quadratic
5720 //=============================================================================
5722 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const SMESH::smIdType id)
5725 _preMeshInfo->FullLoadFromFile();
5727 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5728 if ( aMeshDS == NULL ) return false;
5729 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5730 if(!elem) return false;
5731 return elem->IsQuadratic();
5734 //=============================================================================
5736 * Return diameter of ball discrete element or zero in case of an invalid \a id
5738 //=============================================================================
5740 CORBA::Double SMESH_Mesh_i::GetBallDiameter(SMESH::smIdType id)
5743 _preMeshInfo->FullLoadFromFile();
5745 if ( const SMDS_BallElement* ball =
5746 SMDS_Mesh::DownCast<SMDS_BallElement>( _impl->GetMeshDS()->FindElement( id )))
5747 return ball->GetDiameter();
5752 //=============================================================================
5754 * Return bary center for given element
5756 //=============================================================================
5758 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const SMESH::smIdType id)
5761 _preMeshInfo->FullLoadFromFile();
5763 SMESH::double_array_var aResult = new SMESH::double_array();
5764 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5765 if ( aMeshDS == NULL )
5766 return aResult._retn();
5768 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5770 return aResult._retn();
5772 if(elem->GetType()==SMDSAbs_Volume) {
5773 SMDS_VolumeTool aTool;
5774 if(aTool.Set(elem)) {
5776 if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
5781 SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
5783 double x=0., y=0., z=0.;
5784 for(; anIt->more(); ) {
5786 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
5800 return aResult._retn();
5803 //================================================================================
5805 * \brief Create a group of elements preventing computation of a sub-shape
5807 //================================================================================
5809 SMESH::ListOfGroups*
5810 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int theSubShapeID,
5811 const char* theGroupName )
5813 Unexpect aCatch(SALOME_SalomeException);
5815 if ( !theGroupName || strlen( theGroupName) == 0 )
5816 THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
5818 SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
5819 ::SMESH_MeshEditor::ElemFeatures elemType;
5821 // submesh by subshape id
5822 if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
5823 if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
5826 SMESH_ComputeErrorPtr error = sm->GetComputeError();
5827 if ( error && error->HasBadElems() )
5829 // sort bad elements by type
5830 vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
5831 const list<const SMDS_MeshElement*>& badElems =
5832 static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
5833 list<const SMDS_MeshElement*>::const_iterator elemIt = badElems.begin();
5834 list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
5835 for ( ; elemIt != elemEnd; ++elemIt )
5837 const SMDS_MeshElement* elem = *elemIt;
5838 if ( !elem ) continue;
5840 if ( elem->GetID() < 1 )
5842 // elem is a temporary element, make a real element
5843 vector< const SMDS_MeshNode* > nodes;
5844 SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
5845 while ( nIt->more() && elem )
5847 nodes.push_back( nIt->next() );
5848 if ( nodes.back()->GetID() < 1 )
5849 elem = 0; // a temporary element on temporary nodes
5853 ::SMESH_MeshEditor editor( _impl );
5854 elem = editor.AddElement( nodes, elemType.Init( elem ));
5858 elemsByType[ elem->GetType() ].push_back( elem );
5861 // how many groups to create?
5863 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5864 nbTypes += int( !elemsByType[ i ].empty() );
5865 groups->length( nbTypes );
5868 for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
5870 vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
5871 if ( elems.empty() ) continue;
5873 groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
5874 if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
5876 SMESH::SMESH_Mesh_var mesh = _this();
5877 SALOMEDS::SObject_wrap aSO =
5878 _gen_i->PublishGroup( mesh, groups[ iG ],
5879 GEOM::GEOM_Object::_nil(), theGroupName);
5881 SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
5882 if ( !grp_i ) continue;
5884 if ( SMESHDS_Group* grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
5885 for ( size_t iE = 0; iE < elems.size(); ++iE )
5886 grpDS->SMDSGroup().Add( elems[ iE ]);
5891 return groups._retn();
5894 //=============================================================================
5896 * Create and publish group servants if any groups were imported or created anyhow
5898 //=============================================================================
5900 void SMESH_Mesh_i::CreateGroupServants()
5902 SMESH::SMESH_Mesh_var aMesh = _this();
5905 ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
5906 while ( groupIt->more() )
5908 ::SMESH_Group* group = groupIt->next();
5909 int anId = group->GetID();
5911 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
5912 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5914 addedIDs.insert( anId );
5916 SMESH_GroupBase_i* aGroupImpl;
5918 if ( SMESHDS_GroupOnGeom* groupOnGeom =
5919 dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
5921 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
5922 shape = groupOnGeom->GetShape();
5925 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
5928 SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
5929 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
5930 aGroupImpl->Register();
5932 // register CORBA object for persistence
5933 int nextId = _gen_i->RegisterObject( groupVar );
5934 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
5935 else { (void)nextId; } // avoid "unused variable" warning in release mode
5937 // publishing the groups in the study
5938 GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
5939 _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName());
5942 if ( !addedIDs.empty() )
5945 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
5946 for ( int index = 0; i_grp != _mapGroups.end(); ++index, ++i_grp )
5948 set<int>::iterator it = addedIDs.find( i_grp->first );
5949 if ( it != addedIDs.end() )
5951 TPythonDump() << i_grp->second << " = " << aMesh << ".GetGroups()[ "<< index << " ]";
5952 addedIDs.erase( it );
5953 if ( addedIDs.empty() )
5960 //=============================================================================
5962 * \brief Return true if all sub-meshes are computed OK - to update an icon
5964 //=============================================================================
5966 bool SMESH_Mesh_i::IsComputedOK()
5968 return _impl->IsComputedOK();
5971 //=============================================================================
5973 * \brief Return groups cantained in _mapGroups by their IDs
5975 //=============================================================================
5977 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
5979 int nbGroups = groupIDs.size();
5980 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
5981 aList->length( nbGroups );
5983 list<int>::const_iterator ids = groupIDs.begin();
5984 for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
5986 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
5987 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5988 aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
5990 aList->length( nbGroups );
5991 return aList._retn();
5994 //=============================================================================
5996 * \brief Return information about imported file
5998 //=============================================================================
6000 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
6002 SMESH::MedFileInfo_var res( _medFileInfo );
6003 if ( !res.operator->() ) {
6004 res = new SMESH::MedFileInfo;
6006 res->fileSize = res->major = res->minor = res->release = -1;
6011 //=======================================================================
6012 //function : FileInfoToString
6013 //purpose : Persistence of file info
6014 //=======================================================================
6016 std::string SMESH_Mesh_i::FileInfoToString()
6019 if ( &_medFileInfo.in() && _medFileInfo->fileName[0] )
6021 s = SMESH_Comment( _medFileInfo->fileSize )
6022 << " " << _medFileInfo->major
6023 << " " << _medFileInfo->minor
6024 << " " << _medFileInfo->release
6025 << " " << _medFileInfo->fileName;
6030 //=======================================================================
6031 //function : FileInfoFromString
6032 //purpose : Persistence of file info
6033 //=======================================================================
6035 void SMESH_Mesh_i::FileInfoFromString(const std::string& info)
6037 std::string size, major, minor, release, fileName;
6038 std::istringstream is(info);
6039 is >> size >> major >> minor >> release;
6040 fileName = info.data() + ( size.size() + 1 +
6043 release.size()+ 1 );
6045 _medFileInfo = new SMESH::MedFileInfo();
6046 _medFileInfo->fileName = fileName.c_str();
6047 _medFileInfo->fileSize = atoi( size.c_str() );
6048 _medFileInfo->major = atoi( major.c_str() );
6049 _medFileInfo->minor = atoi( minor.c_str() );
6050 _medFileInfo->release = atoi( release.c_str() );
6053 //=============================================================================
6055 * \brief Pass names of mesh groups from study to mesh DS
6057 //=============================================================================
6059 void SMESH_Mesh_i::checkGroupNames()
6061 int nbGrp = NbGroups();
6065 SMESH::ListOfGroups* grpList = 0;
6066 // avoid dump of "GetGroups"
6068 // store python dump into a local variable inside local scope
6069 SMESH::TPythonDump pDump; // do not delete this line of code
6070 grpList = GetGroups();
6073 for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
6074 SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
6077 SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aGrp );
6078 if ( aGrpSO->_is_nil() )
6080 // correct name of the mesh group if necessary
6081 const char* guiName = aGrpSO->GetName();
6082 if ( strcmp(guiName, aGrp->GetName()) )
6083 aGrp->SetName( guiName );
6087 //=============================================================================
6089 * \brief Set list of notebook variables used for Mesh operations separated by ":" symbol
6091 //=============================================================================
6092 void SMESH_Mesh_i::SetParameters(const char* theParameters)
6094 SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
6098 //=============================================================================
6100 * \brief Return list of notebook variables used for Mesh operations separated by ":" symbol
6102 //=============================================================================
6104 char* SMESH_Mesh_i::GetParameters()
6106 return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
6109 //=============================================================================
6111 * \brief Return list of notebook variables used for last Mesh operation
6113 //=============================================================================
6114 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
6116 SMESH::string_array_var aResult = new SMESH::string_array();
6117 SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
6119 CORBA::String_var aParameters = GetParameters();
6120 SALOMEDS::ListOfListOfStrings_var aSections = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->ParseVariables(aParameters);
6121 if ( aSections->length() > 0 ) {
6122 SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
6123 aResult->length( aVars.length() );
6124 for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
6125 aResult[i] = CORBA::string_dup( aVars[i] );
6128 return aResult._retn();
6131 //================================================================================
6133 * \brief Return types of elements it contains
6135 //================================================================================
6137 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
6140 return _preMeshInfo->GetTypes();
6142 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
6146 if (_impl->NbEdges()) types[nbTypes++] = SMESH::EDGE;
6147 if (_impl->NbFaces()) types[nbTypes++] = SMESH::FACE;
6148 if (_impl->NbVolumes()) types[nbTypes++] = SMESH::VOLUME;
6149 if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
6150 if (_impl->NbBalls()) types[nbTypes++] = SMESH::BALL;
6151 if (_impl->NbNodes() &&
6152 nbTypes == 0 ) types[nbTypes++] = SMESH::NODE;
6153 types->length( nbTypes );
6155 return types._retn();
6158 //================================================================================
6160 * \brief Return self
6162 //================================================================================
6164 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
6166 return SMESH::SMESH_Mesh::_duplicate( _this() );
6169 //================================================================================
6171 * \brief Return false if GetMeshInfo() return incorrect information that may
6172 * happen if mesh data is not yet fully loaded from the file of study.
6176 //================================================================================
6178 bool SMESH_Mesh_i::IsMeshInfoCorrect()
6180 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
6183 //=============================================================================
6185 * \brief Return number of mesh elements per each \a EntityType
6187 //=============================================================================
6189 SMESH::smIdType_array* SMESH_Mesh_i::GetMeshInfo()
6192 return _preMeshInfo->GetMeshInfo();
6194 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
6195 aRes->length(SMESH::Entity_Last);
6196 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6198 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6200 return aRes._retn();
6201 const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
6202 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6203 aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
6204 return aRes._retn();
6207 //=============================================================================
6209 * \brief Return number of mesh elements per each \a ElementType
6211 //=============================================================================
6213 SMESH::smIdType_array* SMESH_Mesh_i::GetNbElementsByType()
6215 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
6216 aRes->length(SMESH::NB_ELEMENT_TYPES);
6217 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6220 const SMDS_MeshInfo* meshInfo = 0;
6222 meshInfo = _preMeshInfo;
6223 else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
6224 meshInfo = & meshDS->GetMeshInfo();
6227 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6228 aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
6230 return aRes._retn();
6233 //=============================================================================
6235 * Collect statistic of mesh elements given by iterator
6237 //=============================================================================
6239 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
6240 SMESH::smIdType_array& theInfo)
6242 if (!theItr) return;
6243 while (theItr->more())
6244 theInfo[ theItr->next()->GetEntityType() ]++;
6246 //=============================================================================
6248 * Return mesh unstructed grid information.
6250 //=============================================================================
6252 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
6254 SALOMEDS::TMPFile_var SeqFile;
6255 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
6256 SMDS_UnstructuredGrid* aGrid = aMeshDS->GetGrid();
6258 vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
6259 aWriter->WriteToOutputStringOn();
6260 aWriter->SetInputData(aGrid);
6261 aWriter->SetFileTypeToBinary();
6263 char* str = aWriter->GetOutputString();
6264 int size = aWriter->GetOutputStringLength();
6266 //Allocate octet buffer of required size
6267 CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
6268 //Copy ostrstream content to the octet buffer
6269 memcpy(OctetBuf, str, size);
6270 //Create and return TMPFile
6271 SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
6275 return SeqFile._retn();
6278 //=============================================================================
6279 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
6280 * SMESH::ElementType type) */
6282 using namespace SMESH::Controls;
6283 //-----------------------------------------------------------------------------
6284 struct PredicateIterator : public SMDS_ElemIterator
6286 SMDS_ElemIteratorPtr _elemIter;
6287 PredicatePtr _predicate;
6288 const SMDS_MeshElement* _elem;
6289 SMDSAbs_ElementType _type;
6291 PredicateIterator( SMDS_ElemIteratorPtr iterator,
6292 PredicatePtr predicate,
6293 SMDSAbs_ElementType type):
6294 _elemIter(iterator), _predicate(predicate), _type(type)
6302 virtual const SMDS_MeshElement* next()
6304 const SMDS_MeshElement* res = _elem;
6306 while ( _elemIter->more() && !_elem )
6308 if ((_elem = _elemIter->next()) &&
6309 (( _type != SMDSAbs_All && _type != _elem->GetType() ) ||
6310 ( !_predicate->IsSatisfy( _elem->GetID() ))))
6317 //-----------------------------------------------------------------------------
6318 struct IDSourceIterator : public SMDS_ElemIterator
6320 const SMESH::smIdType* _idPtr;
6321 const SMESH::smIdType* _idEndPtr;
6322 SMESH::smIdType_array_var _idArray;
6323 const SMDS_Mesh* _mesh;
6324 const SMDSAbs_ElementType _type;
6325 const SMDS_MeshElement* _elem;
6327 IDSourceIterator( const SMDS_Mesh* mesh,
6328 const SMESH::smIdType* ids,
6329 const smIdType nbIds,
6330 SMDSAbs_ElementType type):
6331 _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
6333 if ( _idPtr && nbIds && _mesh )
6336 IDSourceIterator( const SMDS_Mesh* mesh,
6337 SMESH::smIdType_array* idArray,
6338 SMDSAbs_ElementType type):
6339 _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
6341 if ( idArray && _mesh )
6343 _idPtr = &_idArray[0];
6344 _idEndPtr = _idPtr + _idArray->length();
6352 virtual const SMDS_MeshElement* next()
6354 const SMDS_MeshElement* res = _elem;
6356 while ( _idPtr < _idEndPtr && !_elem )
6358 if ( _type == SMDSAbs_Node )
6360 _elem = _mesh->FindNode( *_idPtr++ );
6362 else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
6363 (_elem->GetType() != _type && _type != SMDSAbs_All ))
6371 //-----------------------------------------------------------------------------
6373 struct NodeOfElemIterator : public SMDS_ElemIterator
6375 TColStd_MapOfInteger _checkedNodeIDs;
6376 SMDS_ElemIteratorPtr _elemIter;
6377 SMDS_ElemIteratorPtr _nodeIter;
6378 const SMDS_MeshElement* _node;
6380 NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
6382 if ( _elemIter && _elemIter->more() )
6384 _nodeIter = _elemIter->next()->nodesIterator();
6392 virtual const SMDS_MeshElement* next()
6394 const SMDS_MeshElement* res = _node;
6396 while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
6398 if ( _nodeIter->more() )
6400 _node = _nodeIter->next();
6401 if ( !_checkedNodeIDs.Add( _node->GetID() ))
6406 _nodeIter = _elemIter->next()->nodesIterator();
6414 //=============================================================================
6416 * Return iterator on elements of given type in given object
6418 //=============================================================================
6420 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
6421 SMESH::ElementType theType)
6423 SMDS_ElemIteratorPtr elemIt;
6424 bool typeOK = ( theType == SMESH::ALL );
6425 SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
6427 SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
6428 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
6429 if ( !mesh_i ) return elemIt;
6430 SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
6432 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
6434 elemIt = meshDS->elementsIterator( elemType );
6437 else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
6439 SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
6442 elemIt = sm->GetElements();
6443 if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6445 typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
6446 elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
6450 else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
6452 SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
6453 if ( groupDS && ( elemType == groupDS->GetType() ||
6454 elemType == SMDSAbs_Node ||
6455 elemType == SMDSAbs_All ))
6457 elemIt = groupDS->GetElements();
6458 typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
6461 else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
6463 if ( filter_i->GetElementType() == theType ||
6464 filter_i->GetElementType() == SMESH::ALL ||
6465 elemType == SMDSAbs_Node ||
6466 elemType == SMDSAbs_All)
6468 SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
6469 if ( pred_i && pred_i->GetPredicate() )
6471 SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
6472 SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
6473 SMDSAbs_ElementType iterType = elemType == SMDSAbs_Node ? filterType : elemType;
6474 elemIt = SMDS_ElemIteratorPtr
6475 ( new PredicateIterator( allElemIt, pred_i->GetPredicate(), iterType ));
6476 typeOK = ( elemType == SMDSAbs_Node ? filterType == SMDSAbs_Node : elemIt->more() );
6482 SMESH::array_of_ElementType_var types = theObject->GetTypes();
6483 const bool isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
6484 if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6486 SMDSAbs_ElementType iterType = isNodes ? SMDSAbs_Node : elemType;
6487 if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
6489 SMESH::smIdType nbIds;
6490 if ( SMESH::smIdType* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
6491 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, iterType ));
6495 SMESH::smIdType_array_var ids = theObject->GetIDs();
6496 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), iterType ));
6498 typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
6501 if ( elemIt && elemIt->more() && !typeOK )
6503 if ( elemType == SMDSAbs_Node )
6505 elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
6509 elemIt = SMDS_ElemIteratorPtr();
6515 //=============================================================================
6516 namespace // Finding concurrent hypotheses
6517 //=============================================================================
6521 * \brief mapping of mesh dimension into shape type
6523 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
6525 TopAbs_ShapeEnum aType = TopAbs_SOLID;
6527 case 0: aType = TopAbs_VERTEX; break;
6528 case 1: aType = TopAbs_EDGE; break;
6529 case 2: aType = TopAbs_FACE; break;
6531 default:aType = TopAbs_SOLID; break;
6536 //-----------------------------------------------------------------------------
6538 * \brief Internal structure used to find concurrent submeshes
6540 * It represents a pair < submesh, concurrent dimension >, where
6541 * 'concurrent dimension' is dimension of shape where the submesh can concurrent
6542 * with another submesh. In other words, it is dimension of a hypothesis assigned
6549 int _dim; //!< a dimension the algo can build (concurrent dimension)
6550 int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
6551 TopTools_MapOfShape _shapeMap; //!< [sub-]shapes of dimension == _dim
6552 const SMESH_subMesh* _subMesh;
6553 list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
6555 //-----------------------------------------------------------------------------
6556 // Return the algorithm
6557 const SMESH_Algo* GetAlgo() const
6558 { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
6560 //-----------------------------------------------------------------------------
6562 SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
6564 const TopoDS_Shape& theShape)
6566 _subMesh = theSubMesh;
6567 SetShape( theDim, theShape );
6570 //-----------------------------------------------------------------------------
6572 void SetShape(const int theDim,
6573 const TopoDS_Shape& theShape)
6576 _ownDim = SMESH_Gen::GetShapeDim(theShape);
6577 if (_dim >= _ownDim)
6578 _shapeMap.Add( theShape );
6580 TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
6581 for( ; anExp.More(); anExp.Next() )
6582 _shapeMap.Add( anExp.Current() );
6586 //-----------------------------------------------------------------------------
6587 //! Check sharing of sub-shapes
6588 static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
6589 const TopTools_MapOfShape& theToFind,
6590 const TopAbs_ShapeEnum theType)
6592 bool isShared = false;
6593 TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
6594 for (; !isShared && anItr.More(); anItr.Next() )
6596 const TopoDS_Shape& aSubSh = anItr.Key();
6597 // check for case when concurrent dimensions are same
6598 isShared = theToFind.Contains( aSubSh );
6599 // check for sub-shape with concurrent dimension
6600 TopExp_Explorer anExp( aSubSh, theType );
6601 for ( ; !isShared && anExp.More(); anExp.Next() )
6602 isShared = theToFind.Contains( anExp.Current() );
6607 //-----------------------------------------------------------------------------
6608 //! check algorithms
6609 static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
6610 const SMESHDS_Hypothesis* theA2)
6612 if ( !theA1 || !theA2 ||
6613 theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
6614 theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
6615 return false; // one of the hypothesis is not algorithm
6616 // check algorithm names (should be equal)
6617 return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
6621 //-----------------------------------------------------------------------------
6622 //! Check if sub-shape hypotheses are concurrent
6623 bool IsConcurrent(const SMESH_DimHyp* theOther) const
6625 if ( _subMesh == theOther->_subMesh )
6626 return false; // same sub-shape - should not be
6628 // if ( <own dim of either of submeshes> == <concurrent dim> &&
6629 // any of the two submeshes is not on COMPOUND shape )
6630 // -> no concurrency
6631 bool meIsCompound = (_subMesh->GetSubMeshDS() &&
6632 _subMesh->GetSubMeshDS()->IsComplexSubmesh());
6633 bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
6634 theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
6635 if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
6638 bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
6639 if ( !checkSubShape )
6642 // check algorithms to be same
6643 const SMESH_Algo* a1 = this->GetAlgo();
6644 const SMESH_Algo* a2 = theOther->GetAlgo();
6645 bool isSame = checkAlgo( a1, a2 );
6649 // commented off for IPAL54678
6650 // if ( !a1 || !a2 )
6651 // return false; // pb?
6652 // return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency !
6655 // check hypothesises for concurrence (skip first as algorithm)
6657 // pointers should be same, because it is referened from mesh hypothesis partition
6658 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
6659 list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
6660 for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
6661 if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
6663 // the submeshes are concurrent if their algorithms has different parameters
6664 return nbSame != theOther->_hypotheses.size() - 1;
6667 // Return true if algorithm of this SMESH_DimHyp is used if no
6668 // sub-mesh order is imposed by the user
6669 bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
6671 // NeedDiscreteBoundary() algo has a higher priority
6672 if ( this ->GetAlgo()->NeedDiscreteBoundary() !=
6673 theOther->GetAlgo()->NeedDiscreteBoundary() )
6674 return !this->GetAlgo()->NeedDiscreteBoundary();
6676 return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
6679 }; // end of SMESH_DimHyp
6680 //-----------------------------------------------------------------------------
6682 typedef list<const SMESH_DimHyp*> TDimHypList;
6684 //-----------------------------------------------------------------------------
6686 void addDimHypInstance(const int theDim,
6687 const TopoDS_Shape& theShape,
6688 const SMESH_Algo* theAlgo,
6689 const SMESH_subMesh* theSubMesh,
6690 const list <const SMESHDS_Hypothesis*>& theHypList,
6691 TDimHypList* theDimHypListArr )
6693 if ( !theAlgo->NeedDiscreteBoundary() &&
6694 theAlgo->NeedLowerHyps( theDim )) // IPAL54678
6696 TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
6697 if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh )
6699 SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
6700 dimHyp->_hypotheses.push_front(theAlgo);
6701 listOfdimHyp.push_back( dimHyp );
6704 SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
6705 dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
6706 theHypList.begin(), theHypList.end() );
6709 //-----------------------------------------------------------------------------
6710 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
6711 TDimHypList& theListOfConcurr)
6713 if ( theListOfConcurr.empty() )
6715 theListOfConcurr.push_back( theDimHyp );
6719 TDimHypList::iterator hypIt = theListOfConcurr.begin();
6720 while ( hypIt != theListOfConcurr.end() &&
6721 !theDimHyp->IsHigherPriorityThan( *hypIt ))
6723 theListOfConcurr.insert( hypIt, theDimHyp );
6727 //-----------------------------------------------------------------------------
6728 void findConcurrents(const SMESH_DimHyp* theDimHyp,
6729 const TDimHypList& theListOfDimHyp,
6730 TDimHypList& theListOfConcurrHyp,
6731 set<int>& theSetOfConcurrId )
6733 TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
6734 for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
6736 const SMESH_DimHyp* curDimHyp = *rIt;
6737 if ( curDimHyp == theDimHyp )
6738 break; // meet own dimHyp pointer in same dimension
6740 if ( theDimHyp->IsConcurrent( curDimHyp ) &&
6741 theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
6743 addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
6748 //-----------------------------------------------------------------------------
6749 bool unionLists(TListOfInt& theListOfId,
6750 TListOfListOfInt& theListOfListOfId,
6753 bool changed = false;
6754 if ( theListOfId.empty() )
6756 TListOfListOfInt::iterator it = theListOfListOfId.begin();
6757 for ( int i = 0; it != theListOfListOfId.end(); it++, i++ )
6760 continue; //skip already treated lists
6761 // check if other list has any same submesh object
6762 TListOfInt& otherListOfId = *it;
6763 if ( find_first_of( theListOfId.begin(), theListOfId.end(),
6764 otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
6767 // union two lists (from source into target)
6768 TListOfInt::iterator it2 = otherListOfId.begin();
6769 for ( ; it2 != otherListOfId.end(); it2++ ) {
6770 if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
6772 theListOfId.push_back(*it2);
6776 // clear source list
6777 otherListOfId.clear();
6781 //-----------------------------------------------------------------------------
6783 //! free memory allocated for dimension-hypothesis objects
6784 void removeDimHyps( TDimHypList* theArrOfList )
6786 for (int i = 0; i < 4; i++ ) {
6787 TDimHypList& listOfdimHyp = theArrOfList[i];
6788 TDimHypList::const_iterator it = listOfdimHyp.begin();
6789 for ( ; it != listOfdimHyp.end(); it++ )
6794 //-----------------------------------------------------------------------------
6796 * \brief find common submeshes with given submesh
6797 * \param theSubMeshList list of already collected submesh to check
6798 * \param theSubMesh given submesh to intersect with other
6799 * \param theCommonSubMeshes collected common submeshes
6801 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
6802 const SMESH_subMesh* theSubMesh,
6803 set<const SMESH_subMesh*>& theCommon )
6807 list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
6808 for ( ; it != theSubMeshList.end(); it++ )
6809 theSubMesh->FindIntersection( *it, theCommon );
6810 theSubMeshList.push_back( theSubMesh );
6811 //theCommon.insert( theSubMesh );
6814 //-----------------------------------------------------------------------------
6815 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
6817 TListOfListOfInt::const_iterator listsIt = smLists.begin();
6818 for ( ; listsIt != smLists.end(); ++listsIt )
6820 const TListOfInt& smIDs = *listsIt;
6821 if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
6829 //=============================================================================
6831 * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
6833 //=============================================================================
6835 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
6837 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6838 if ( isSubMeshInList( submeshID, anOrder ))
6841 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6842 return isSubMeshInList( submeshID, allConurrent );
6845 //=============================================================================
6847 * \brief Return sub-mesh objects list in meshing order
6849 //=============================================================================
6851 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
6853 SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
6855 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6857 return aResult._retn();
6859 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6860 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6861 anOrder.splice( anOrder.end(), allConurrent );
6866 TListOfListOfInt::iterator listIt = anOrder.begin();
6867 for ( int listIndx = 1; listIt != anOrder.end(); listIt++, listIndx++ )
6868 if ( unionLists( *listIt, anOrder, listIndx ))
6873 // convert submesh ids into interface instances
6874 // and dump command into python
6875 convertMeshOrder( anOrder, aResult, false );
6877 return aResult._retn();
6880 //=============================================================================
6882 * \brief Finds concurrent sub-meshes
6884 //=============================================================================
6886 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
6888 TListOfListOfInt anOrder;
6889 ::SMESH_Mesh& mesh = GetImpl();
6891 // collect submeshes and detect concurrent algorithms and hypothesises
6892 TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
6894 map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
6895 for ( ; i_sm != _mapSubMesh.end(); i_sm++ )
6897 ::SMESH_subMesh* sm = (*i_sm).second;
6899 const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
6901 // list of assigned hypothesises
6902 const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
6903 // Find out dimensions where the submesh can be concurrent.
6904 // We define the dimensions by algo of each of hypotheses in hypList
6905 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
6906 for( ; hypIt != hypList.end(); hypIt++ )
6908 SMESH_Algo* anAlgo = 0;
6909 const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
6910 if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
6911 // hyp it-self is algo
6912 anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
6914 // try to find algorithm with help of sub-shapes
6915 TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
6916 for ( ; !anAlgo && anExp.More(); anExp.Next() )
6917 anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
6920 continue; // no algorithm assigned to a current submesh
6922 int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
6923 // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary()
6924 // and !anAlgo->NeedLowerHyps( dim ))
6926 // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
6927 for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
6928 addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
6930 } // end iterations on submesh
6932 // iterate on created dimension-hypotheses and check for concurrents
6933 for ( int i = 0; i < 4; i++ )
6935 const TDimHypList& listOfDimHyp = dimHypListArr[i];
6936 // check for concurrents in own and other dimensions (step-by-step)
6937 TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
6938 for ( ; dhIt != listOfDimHyp.end(); dhIt++ )
6940 const SMESH_DimHyp* dimHyp = *dhIt;
6941 TDimHypList listOfConcurr;
6942 set<int> setOfConcurrIds;
6943 // looking for concurrents and collect into own list
6944 for ( int j = i; j < 4; j++ )
6945 findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
6946 // check if any concurrents found
6947 if ( listOfConcurr.size() > 0 )
6949 // add own submesh to list of concurrent
6950 addInOrderOfPriority( dimHyp, listOfConcurr );
6951 list<int> listOfConcurrIds;
6952 TDimHypList::iterator hypIt = listOfConcurr.begin();
6953 for ( ; hypIt != listOfConcurr.end(); ++hypIt )
6954 listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
6955 anOrder.push_back( listOfConcurrIds );
6960 removeDimHyps(dimHypListArr);
6962 // now, minimize the number of concurrent groups
6963 // Here we assume that lists of submeshes can have same submesh
6964 // in case of multi-dimension algorithms, as result
6965 // list with common submesh has to be united into one list
6967 TListOfListOfInt::iterator listIt = anOrder.begin();
6968 for(; listIt != anOrder.end(); listIt++, listIndx++ )
6969 unionLists( *listIt, anOrder, listIndx + 1 );
6974 //=============================================================================
6976 * \brief Set submesh object order
6977 * \param theSubMeshArray submesh array order
6979 //=============================================================================
6981 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
6984 _preMeshInfo->ForgetOrLoad();
6987 ::SMESH_Mesh& mesh = GetImpl();
6989 TPythonDump aPythonDump; // prevent dump of called methods
6990 aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
6992 TListOfListOfInt subMeshOrder;
6993 for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
6995 const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
6996 TListOfInt subMeshIds;
6998 aPythonDump << ", ";
6999 aPythonDump << "[ ";
7000 // Collect subMeshes which should be clear
7001 // do it list-by-list, because modification of submesh order
7002 // take effect between concurrent submeshes only
7003 set<const SMESH_subMesh*> subMeshToClear;
7004 list<const SMESH_subMesh*> subMeshList;
7005 for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
7007 const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
7009 aPythonDump << ", ";
7010 aPythonDump << subMesh;
7011 subMeshIds.push_back( subMesh->GetId() );
7012 // detect common parts of submeshes
7013 if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
7014 findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
7016 aPythonDump << " ]";
7017 subMeshOrder.push_back( subMeshIds );
7019 // clear collected sub-meshes
7020 set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
7021 for ( ; clrIt != subMeshToClear.end(); clrIt++ )
7022 if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
7024 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
7025 if ( SMESH_Algo* algo = sm->GetAlgo() ) // #16748
7026 sm->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, algo ); // to clear a cached algo
7029 aPythonDump << " ])";
7031 mesh.SetMeshOrder( subMeshOrder );
7034 SMESH::SMESH_Mesh_var me = _this();
7035 _gen_i->UpdateIcons( me );
7040 //=============================================================================
7042 * \brief Convert submesh ids into submesh interfaces
7044 //=============================================================================
7046 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt& theIdsOrder,
7047 SMESH::submesh_array_array& theResOrder,
7048 const bool theIsDump)
7050 int nbSet = theIdsOrder.size();
7051 TPythonDump aPythonDump; // prevent dump of called methods
7053 aPythonDump << "[ ";
7054 theResOrder.length(nbSet);
7055 TListOfListOfInt::const_iterator it = theIdsOrder.begin();
7057 for( ; it != theIdsOrder.end(); it++ )
7059 // translate submesh identificators into submesh objects
7060 // takeing into account real number of concurrent lists
7061 const TListOfInt& aSubOrder = (*it);
7062 if (!aSubOrder.size())
7065 aPythonDump << "[ ";
7066 // convert shape indices into interfaces
7067 SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
7068 aResSubSet->length(aSubOrder.size());
7069 TListOfInt::const_iterator subIt = aSubOrder.begin();
7071 for( j = 0; subIt != aSubOrder.end(); subIt++ )
7073 if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
7075 SMESH::SMESH_subMesh_var subMesh =
7076 SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
7079 aPythonDump << ", ";
7080 aPythonDump << subMesh;
7082 aResSubSet[ j++ ] = subMesh;
7085 aPythonDump << " ]";
7087 theResOrder[ listIndx++ ] = aResSubSet;
7089 // correct number of lists
7090 theResOrder.length( listIndx );
7093 // finilise python dump
7094 aPythonDump << " ]";
7095 aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
7099 namespace // utils used by SMESH_MeshPartDS
7102 * \brief Class used to access to protected data of SMDS_MeshInfo
7104 struct TMeshInfo : public SMDS_MeshInfo
7106 void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
7109 * \brief Element holing its ID only
7111 struct TElemID : public SMDS_LinearEdge
7113 TElemID(int ID) : SMDS_LinearEdge(0,0) { setID( ID ); }
7117 //================================================================================
7119 // Implementation of SMESH_MeshPartDS
7121 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
7122 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
7124 SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
7125 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
7128 _meshDS = mesh_i->GetImpl().GetMeshDS();
7130 SetPersistentId( _meshDS->GetPersistentId() );
7132 if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
7134 // <meshPart> is the whole mesh
7135 myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
7137 set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
7138 myGroupSet = _meshDS->GetGroups();
7143 SMESH::smIdType_array_var anIDs = meshPart->GetIDs();
7144 SMESH::array_of_ElementType_var types = meshPart->GetTypes();
7145 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
7147 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7148 if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
7149 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7154 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7155 if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
7156 if ( _elements[ e->GetType() ].insert( e ).second )
7159 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7160 while ( nIt->more() )
7162 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7163 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7170 ShapeToMesh( _meshDS->ShapeToMesh() );
7172 _meshDS = 0; // to enforce iteration on _elements and _nodes
7175 // -------------------------------------------------------------------------------------
7176 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
7177 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
7180 list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
7181 for ( ; partIt != meshPart.end(); ++partIt )
7182 if ( const SMDS_MeshElement * e = *partIt )
7183 if ( _elements[ e->GetType() ].insert( e ).second )
7186 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7187 while ( nIt->more() )
7189 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7190 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7196 // -------------------------------------------------------------------------------------
7197 const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const
7199 if ( _meshDS ) return _meshDS->FindElement( IDelem );
7201 TElemID elem( IDelem );
7202 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7203 if ( !_elements[ iType ].empty() )
7205 TIDSortedElemSet::const_iterator it = _elements[ iType ].find( &elem );
7206 if ( it != _elements[ iType ].end() )
7211 // -------------------------------------------------------------------------------------
7212 bool SMESH_MeshPartDS::HasNumerationHoles()
7214 if ( _meshDS ) return _meshDS->HasNumerationHoles();
7216 return ( MinNodeID() != 1 ||
7217 MaxNodeID() != NbNodes() ||
7218 MinElementID() != 1 ||
7219 MaxElementID() != NbElements() );
7221 // -------------------------------------------------------------------------------------
7222 smIdType SMESH_MeshPartDS::MaxNodeID() const
7224 if ( _meshDS ) return _meshDS->MaxNodeID();
7225 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].rbegin())->GetID();
7227 // -------------------------------------------------------------------------------------
7228 smIdType SMESH_MeshPartDS::MinNodeID() const
7230 if ( _meshDS ) return _meshDS->MinNodeID();
7231 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].begin())->GetID();
7233 // -------------------------------------------------------------------------------------
7234 smIdType SMESH_MeshPartDS::MaxElementID() const
7236 if ( _meshDS ) return _meshDS->MaxElementID();
7238 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7239 if ( !_elements[ iType ].empty() )
7240 maxID = std::max( maxID, (*_elements[ iType ].rbegin())->GetID() );
7243 // -------------------------------------------------------------------------------------
7244 smIdType SMESH_MeshPartDS::MinElementID() const
7246 if ( _meshDS ) return _meshDS->MinElementID();
7248 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7249 if ( !_elements[ iType ].empty() )
7250 minID = std::min( minID, (*_elements[ iType ].begin())->GetID() );
7253 // -------------------------------------------------------------------------------------
7254 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
7256 if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
7258 typedef SMDS_SetIterator
7259 <const SMDS_MeshElement*,
7260 TIDSortedElemSet::const_iterator,
7261 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7262 SMDS_MeshElement::GeomFilter
7265 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( geomType );
7267 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7268 _elements[type].end(),
7269 SMDS_MeshElement::GeomFilter( geomType )));
7271 // -------------------------------------------------------------------------------------
7272 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
7274 if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
7276 typedef SMDS_SetIterator
7277 <const SMDS_MeshElement*,
7278 TIDSortedElemSet::const_iterator,
7279 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7280 SMDS_MeshElement::EntityFilter
7283 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( entity );
7285 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7286 _elements[type].end(),
7287 SMDS_MeshElement::EntityFilter( entity )));
7289 // -------------------------------------------------------------------------------------
7290 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
7292 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
7293 if ( type == SMDSAbs_All && !_meshDS )
7295 typedef vector< SMDS_ElemIteratorPtr > TIterVec;
7297 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
7298 if ( !_elements[i].empty() && i != SMDSAbs_Node )
7300 ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
7302 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
7303 return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
7305 return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
7306 ( new TIter( _elements[type].begin(), _elements[type].end() ));
7308 // -------------------------------------------------------------------------------------
7309 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType) \
7310 iterType SMESH_MeshPartDS::methName() const \
7312 typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
7313 return _meshDS ? _meshDS->methName() : iterType \
7314 ( new TIter( _elements[elemType].begin(), _elements[elemType].end() )); \
7316 // -------------------------------------------------------------------------------------
7317 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
7318 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
7319 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
7320 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
7321 #undef _GET_ITER_DEFINE
7323 // END Implementation of SMESH_MeshPartDS
7325 //================================================================================