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 if ( nb != NbNodes() + NbElements() ) // something removed due to hypotheses change
2419 _gen_i->UpdateIcons( me );
2423 // Update after shape modification or breakLink w/o geometry change
2425 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2426 if ( !geomClient ) return;
2427 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( mainGO );
2428 if ( geomGen->_is_nil() ) return;
2429 CORBA::String_var geomComponentType = geomGen->ComponentDataType();
2430 bool isShaper = ( strcmp( geomComponentType.in(), "SHAPERSTUDY" ) == 0 );
2432 SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
2434 TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
2435 if ( meshDS->ShapeToIndex( newShape ) == 1 ) // not yet updated
2437 CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
2438 geomClient->RemoveShapeFromBuffer( ior.in() );
2439 newShape = _gen_i->GeomObjectToShape( mainGO );
2442 // Update data taking into account that if topology doesn't change
2443 // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
2446 _preMeshInfo->ForgetAllData();
2448 if ( geomChanged || !isShaper )
2450 if ( newShape.IsNull() )
2453 _mainShapeTick = mainGO->GetTick();
2455 // store data of groups on geometry including new TopoDS_Shape's
2456 std::vector< TGroupOnGeomData > groupsData;
2457 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2458 groupsData.reserve( groups.size() );
2459 TopTools_DataMapOfShapeShape old2newShapeMap;
2460 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2461 for ( ; g != groups.end(); ++g )
2463 if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
2465 groupsData.push_back( TGroupOnGeomData( group ));
2468 SMESH::SMESH_GroupOnGeom_var gog;
2469 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.find( group->GetID() );
2470 if ( i_grp != _mapGroups.end() )
2471 gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second );
2473 GEOM::GEOM_Object_var geom;
2474 if ( !gog->_is_nil() )
2476 if ( !theIsBreakLink )
2477 geom = gog->GetShape();
2479 if ( theIsBreakLink || geom->_is_nil() )
2481 SALOMEDS::SObject_wrap grpSO = _gen_i->ObjectToSObject( gog );
2482 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2483 if ( !grpSO->_is_nil() &&
2484 grpSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2485 geomRefSO->ReferencedObject( geomSO.inout() ))
2487 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2488 geom = GEOM::GEOM_Object::_narrow( geomObj );
2492 if ( old2newShapeMap.IsBound( group->GetShape() ))
2494 groupsData.back()._shape = old2newShapeMap( group->GetShape() );
2496 else if ( !geom->_is_nil() )
2498 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2499 if ( meshDS->IsGroupOfSubShapes( groupsData.back()._shape ))
2501 CORBA::String_var ior = geomGen->GetStringFromIOR( geom );
2502 geomClient->RemoveShapeFromBuffer( ior.in() );
2503 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2505 old2newShapeMap.Bind( group->GetShape(), groupsData.back()._shape );
2510 // store assigned hypotheses
2511 std::vector< pair< int, THypList > > ids2Hyps;
2512 const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
2513 for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
2515 const TopoDS_Shape& s = s2hyps.Key();
2516 const THypList& hyps = s2hyps.ChangeValue();
2517 ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
2520 std::multimap< std::set<int>, int > ii2iMap; // group sub-ids to group id in SMESHDS
2522 // count shapes excluding compounds corresponding to geom groups
2523 int oldNbSubShapes = meshDS->MaxShapeIndex();
2524 for ( ; oldNbSubShapes > 0; --oldNbSubShapes )
2526 const TopoDS_Shape& s = meshDS->IndexToShape( oldNbSubShapes );
2527 if ( s.IsNull() || s.ShapeType() != TopAbs_COMPOUND )
2530 std::set<int> subIds;
2531 for ( TopoDS_Iterator it( s ); it.More(); it.Next() )
2532 subIds.insert( meshDS->ShapeToIndex( it.Value() ));
2533 ii2iMap.insert( std::make_pair( subIds, oldNbSubShapes ));
2536 // check if shape topology changes - save shape type per shape ID
2537 std::vector< TopAbs_ShapeEnum > shapeTypes( Max( oldNbSubShapes + 1, 1 ));
2538 for ( int shapeID = oldNbSubShapes; shapeID > 0; --shapeID )
2539 shapeTypes[ shapeID ] = meshDS->IndexToShape( shapeID ).ShapeType();
2541 // change shape to mesh
2542 _impl->ShapeToMesh( TopoDS_Shape() );
2543 _impl->ShapeToMesh( newShape );
2545 // check if shape topology changes - check new shape types
2546 bool sameTopology = ( oldNbSubShapes == meshDS->MaxShapeIndex() );
2547 for ( int shapeID = oldNbSubShapes; shapeID > 0 && sameTopology; --shapeID )
2549 const TopoDS_Shape& s = meshDS->IndexToShape( shapeID );
2550 sameTopology = ( !s.IsNull() && s.ShapeType() == shapeTypes[ shapeID ]);
2553 // re-add shapes (compounds) of geom groups
2554 typedef std::map< std::vector< int >, TGeomGroupData* > TIndices2GroupData;
2555 TIndices2GroupData ii2grData;
2556 std::vector< int > ii;
2557 std::map< int, int > old2newIDs; // group IDs
2558 std::list<TGeomGroupData>::iterator dataIt = _geomGroupData.begin();
2559 for ( ; dataIt != _geomGroupData.end(); ++dataIt )
2561 TGeomGroupData* data = &(*dataIt);
2562 ii.reserve( data->_indices.size() );
2563 ii.assign( data->_indices.begin(), data->_indices.end() );
2564 TIndices2GroupData::iterator ii2gd = ii2grData.insert( std::make_pair( ii, data )).first;
2565 if ( ii2gd->second != data )
2567 data->_groupEntry = ii2gd->second->_groupEntry;
2568 data->_indices = ii2gd->second->_indices;
2571 const int oldNbSub = data->_indices.size();
2572 const int soleOldID = oldNbSub == 1 ? *data->_indices.begin() : 0;
2574 std::multimap< std::set<int>, int >::iterator ii2i = ii2iMap.find( data->_indices );
2575 if ( ii2i != ii2iMap.end() )
2577 oldID = ii2i->second;
2578 ii2iMap.erase( ii2i );
2580 if ( !oldID && oldNbSub == 1 )
2582 if ( old2newIDs.count( oldID ))
2585 int how = ( theIsBreakLink || !sameTopology ) ? IS_BREAK_LINK : MAIN_TRANSFORMED;
2586 newShape = newGroupShape( *data, how );
2588 if ( !newShape.IsNull() )
2590 if ( oldNbSub > 1 && meshDS->ShapeToIndex( newShape ) > 0 ) // group reduced to one sub-shape
2592 TopoDS_Compound compound;
2593 BRep_Builder().MakeCompound( compound );
2594 BRep_Builder().Add( compound, newShape );
2595 newShape = compound;
2597 int newID = _impl->GetSubMesh( newShape )->GetId();
2598 if ( oldID /*&& oldID != newID*/ )
2599 old2newIDs.insert( std::make_pair( oldID, newID ));
2600 if ( oldNbSub == 1 )
2601 old2newIDs.insert( std::make_pair( soleOldID, newID ));
2605 // re-assign hypotheses
2606 for ( size_t i = 0; i < ids2Hyps.size(); ++i )
2608 int sID = ids2Hyps[i].first;
2611 std::map< int, int >::iterator o2n = old2newIDs.find( sID );
2612 if ( o2n != old2newIDs.end() )
2614 else if ( !sameTopology )
2617 const TopoDS_Shape& s = meshDS->IndexToShape( sID );
2620 const THypList& hyps = ids2Hyps[i].second;
2621 THypList::const_iterator h = hyps.begin();
2622 for ( ; h != hyps.end(); ++h )
2623 _impl->AddHypothesis( s, (*h)->GetID() );
2627 // restore groups on geometry
2628 for ( size_t i = 0; i < groupsData.size(); ++i )
2630 const TGroupOnGeomData& data = groupsData[i];
2631 if ( data._shape.IsNull() )
2634 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
2635 if ( i2g == _mapGroups.end() ) continue;
2637 SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
2638 if ( !gr_i ) continue;
2640 SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape );
2642 _mapGroups.erase( i2g );
2644 g->GetGroupDS()->SetColor( data._color );
2647 if ( !sameTopology )
2649 std::map< int, int >::iterator o2n = old2newIDs.begin();
2650 for ( ; o2n != old2newIDs.end(); ++o2n )
2652 int newID = o2n->second, oldID = o2n->first;
2653 if ( newID == oldID || !_mapSubMesh.count( oldID ))
2657 _mapSubMesh [ newID ] = _impl->GetSubMeshContaining( newID );
2658 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2659 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2661 _mapSubMesh. erase(oldID);
2662 _mapSubMesh_i. erase(oldID);
2663 _mapSubMeshIor.erase(oldID);
2665 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2669 // update _mapSubMesh
2670 std::map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
2671 for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
2672 i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
2675 if ( !sameTopology )
2677 // remove invalid study sub-objects
2678 CheckGeomGroupModif();
2681 _gen_i->UpdateIcons( me );
2683 if ( !theIsBreakLink && isShaper )
2685 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2686 if ( !meshSO->_is_nil() )
2687 _gen_i->SetPixMap(meshSO, "ICON_SMESH_TREE_GEOM_MODIF");
2691 //=============================================================================
2693 * \brief Update objects depending on changed geom groups
2695 * NPAL16168: geometrical group edition from a submesh don't modify mesh computation
2696 * issue 0020210: Update of a smesh group after modification of the associated geom group
2698 //=============================================================================
2700 void SMESH_Mesh_i::CheckGeomGroupModif()
2702 // remove sub-meshes referring a removed sub-shapes (if main shape still exists)
2703 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2704 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2705 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() ));
2706 if ( !mainGO->_is_nil() && !meshSO->_is_nil() )
2708 SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO;
2709 for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag )
2710 if ( meshSO->FindSubObject( tag, rootSO.inout() ))
2712 int nbValid = 0, nbRemoved = 0;
2713 SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO );
2714 for ( ; chItr->More(); chItr->Next() )
2716 SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO
2717 if ( !smSO->_is_nil() &&
2718 smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2719 geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference
2721 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2722 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj );
2723 if ( !geom->_non_existent() )
2726 continue; // keep the sub-mesh
2729 CORBA::Object_var smObj = _gen_i->SObjectToObject( smSO );
2730 SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj );
2731 if ( !sm->_is_nil() && !sm->_non_existent() )
2733 GEOM::GEOM_Object_var smGeom = sm->GetSubShape();
2734 if ( smGeom->_is_nil() )
2736 RemoveSubMesh( sm );
2743 _preMeshInfo->ForgetAllData(); // unknown hypothesis modified
2744 builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH
2748 if ( /*nbRemoved > 0 &&*/ nbValid == 0 )
2749 builder->RemoveObjectWithChildren( rootSO );
2753 // check for removed sub-shapes and convert geom dependent groups into standalone ones
2754 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2755 while ( i_gr != _mapGroups.end())
2757 SMESH::SMESH_GroupBase_ptr group = i_gr->second;
2759 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( group ), refSO, geomSO;
2760 SMESH::SMESH_GroupOnGeom_var onGeom = SMESH::SMESH_GroupOnGeom::_narrow ( group );
2761 SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group );
2762 bool isValidGeom = false;
2763 if ( !onGeom->_is_nil() )
2765 isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() ); // check TopoDS
2766 if ( !isValidGeom ) // check reference
2768 isValidGeom = ( ! groupSO->_is_nil() &&
2769 groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ) &&
2770 refSO->ReferencedObject( geomSO.inout() ) &&
2771 ! geomSO->_is_nil() &&
2772 !CORBA::is_nil( CORBA::Object_var( geomSO->GetObject() )));
2775 else if ( !onFilt->_is_nil() )
2777 isValidGeom = isValidGeomFilter( onFilt->GetFilter() );
2781 isValidGeom = ( !groupSO->_is_nil() &&
2782 !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ));
2786 if ( !IsLoaded() || group->IsEmpty() )
2788 RemoveGroup( group );
2790 else if ( !onGeom->_is_nil() || !onFilt->_is_nil() )
2792 SMESH::SMESH_Group_var ( ConvertToStandalone( group ));
2794 else // is it possible?
2796 builder->RemoveObjectWithChildren( refSO );
2802 if ( !_impl->HasShapeToMesh() ) return;
2804 SMESH::smIdType nbEntities = NbNodes() + NbElements();
2806 // Check if group contents changed
2808 typedef map< string, TopoDS_Shape > TEntry2Geom;
2809 TEntry2Geom newGroupContents;
2811 list<TGeomGroupData>::iterator
2812 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2813 for ( ; data != dataEnd; ++data )
2815 pair< TEntry2Geom::iterator, bool > it_new =
2816 newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
2817 bool processedGroup = !it_new.second;
2818 TopoDS_Shape& newShape = it_new.first->second;
2819 if ( !processedGroup )
2820 newShape = newGroupShape( *data, ONLY_IF_CHANGED );
2821 if ( newShape.IsNull() )
2822 continue; // no changes
2825 _preMeshInfo->ForgetOrLoad();
2827 if ( processedGroup ) { // update group indices
2828 list<TGeomGroupData>::iterator data2 = data;
2829 for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
2830 data->_indices = data2->_indices;
2833 // Update SMESH objects according to new GEOM group contents
2835 SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2836 if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2838 int oldID = submesh->GetId();
2839 if ( !_mapSubMeshIor.count( oldID ))
2841 TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2843 // update hypotheses
2844 list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2845 list <const SMESHDS_Hypothesis * >::iterator hypIt;
2846 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2848 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2849 _impl->AddHypothesis ( newShape, (*hypIt)->GetID());
2851 // care of submeshes
2852 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2853 int newID = newSubmesh->GetId();
2854 if ( newID != oldID ) {
2855 _mapSubMesh [ newID ] = newSubmesh;
2856 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2857 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2858 _mapSubMesh. erase(oldID);
2859 _mapSubMesh_i. erase(oldID);
2860 _mapSubMeshIor.erase(oldID);
2861 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2866 SMESH::SMESH_GroupOnGeom_var smeshGroup =
2867 SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2868 if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2870 SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2872 ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2873 SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2874 ds->SetShape( newShape );
2879 SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2880 if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2882 // Remove groups and submeshes basing on removed sub-shapes
2884 TopTools_MapOfShape newShapeMap;
2885 TopoDS_Iterator shapeIt( newShape );
2886 for ( ; shapeIt.More(); shapeIt.Next() )
2887 newShapeMap.Add( shapeIt.Value() );
2889 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2890 for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2892 if ( newShapeMap.Contains( shapeIt.Value() ))
2894 TopTools_IndexedMapOfShape oldShapeMap;
2895 TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2896 for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2898 const TopoDS_Shape& oldShape = oldShapeMap(i);
2899 int oldInd = meshDS->ShapeToIndex( oldShape );
2901 map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2902 if ( i_smIor != _mapSubMeshIor.end() ) {
2903 RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2906 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2907 for ( ; i_grp != _mapGroups.end(); ++i_grp )
2909 // check if a group bases on oldInd shape
2910 SMESHDS_GroupOnGeom* grpOnGeom = 0;
2911 if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2912 grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2913 if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2915 RemoveGroup( i_grp->second ); // several groups can base on same shape
2916 i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2921 // Reassign hypotheses and update groups after setting the new shape to mesh
2923 // collect anassigned hypotheses
2924 typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2925 list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2926 TShapeHypList assignedHyps;
2927 for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2929 const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2930 list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2931 if ( !hyps.empty() ) {
2932 assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2933 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2934 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2937 // collect shapes supporting groups
2938 typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2939 TShapeTypeList groupData;
2940 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2941 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2942 for ( ; grIt != groups.end(); ++grIt )
2944 if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2946 ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2948 // set new shape to mesh -> DS of sub-meshes and geom groups is deleted
2950 _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
2951 _impl->ShapeToMesh( newShape );
2953 // reassign hypotheses
2954 TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2955 for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2957 TIndexedShape& geom = indS_hyps->first;
2958 list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2959 int oldID = geom._index;
2960 int newID = meshDS->ShapeToIndex( geom._shape );
2961 if ( oldID == 1 ) { // main shape
2963 geom._shape = newShape;
2967 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2968 _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2969 // care of sub-meshes
2970 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2971 if ( newID != oldID ) {
2972 _mapSubMesh [ newID ] = newSubmesh;
2973 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2974 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2975 _mapSubMesh. erase(oldID);
2976 _mapSubMesh_i. erase(oldID);
2977 _mapSubMeshIor.erase(oldID);
2978 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2982 TShapeTypeList::iterator geomType = groupData.begin();
2983 for ( ; geomType != groupData.end(); ++geomType )
2985 const TIndexedShape& geom = geomType->first;
2986 int oldID = geom._index;
2987 if ( _mapGroups.find( oldID ) == _mapGroups.end() )
2990 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( _mapGroups[oldID] );
2991 CORBA::String_var name = groupSO->GetName();
2993 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID]))
2994 if ( SMESH_Group* group = _impl->AddGroup( geomType->second, name.in(),
2995 /*id=*/-1, geom._shape ))
2996 group_i->changeLocalId( group->GetID() );
2999 break; // everything has been updated
3002 } // loop on group data
3006 SMESH::smIdType newNbEntities = NbNodes() + NbElements();
3007 list< SALOMEDS::SObject_wrap > soToUpdateIcons;
3008 if ( newNbEntities != nbEntities )
3010 // Add all SObjects with icons to soToUpdateIcons
3011 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( _this() )); // mesh
3013 for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
3014 i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
3015 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_sm->second ));
3017 for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
3018 i_gr != _mapGroups.end(); ++i_gr ) // groups
3019 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_gr->second ));
3022 list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
3023 for ( ; so != soToUpdateIcons.end(); ++so )
3024 _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
3027 //=============================================================================
3029 * \brief Create standalone group from a group on geometry or filter
3031 //=============================================================================
3033 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
3035 SMESH::SMESH_Group_var aGroup;
3040 _preMeshInfo->FullLoadFromFile();
3042 if ( theGroup->_is_nil() )
3043 return aGroup._retn();
3045 SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
3047 return aGroup._retn();
3049 const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
3051 const int anId = aGroupToRem->GetLocalID();
3052 if ( !_impl->ConvertToStandalone( anId ) )
3053 return aGroup._retn();
3054 removeGeomGroupData( theGroup );
3056 SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3058 // remove old instance of group from own map
3059 { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
3060 _mapGroups.erase( anId );
3062 SALOMEDS::StudyBuilder_var builder;
3063 SALOMEDS::SObject_wrap aGroupSO;
3064 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3065 if ( !aStudy->_is_nil() ) {
3066 builder = aStudy->NewBuilder();
3067 aGroupSO = _gen_i->ObjectToSObject( theGroup );
3068 if ( !aGroupSO->_is_nil() )
3070 // remove reference to geometry
3071 SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
3072 for ( ; chItr->More(); chItr->Next() )
3074 // Remove group's child SObject
3075 SALOMEDS::SObject_wrap so = chItr->Value();
3076 builder->RemoveObject( so );
3078 // Update Python script
3079 TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
3080 << ".ConvertToStandalone( " << aGroupSO << " )";
3082 // change icon of Group on Filter
3085 // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
3086 // const int isEmpty = ( elemTypes->length() == 0 );
3089 SALOMEDS::GenericAttribute_wrap anAttr =
3090 builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
3091 SALOMEDS::AttributePixMap_wrap pm = anAttr;
3092 pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
3098 // remember new group in own map
3099 aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
3100 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3102 // register CORBA object for persistence
3103 _gen_i->RegisterObject( aGroup );
3105 CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
3106 builder->SetIOR( aGroupSO, ior.in() ); // == aGroup->Register();
3107 //aGroup->Register();
3108 aGroupToRem->UnRegister();
3110 SMESH_CATCH( SMESH::throwCorbaException );
3112 return aGroup._retn();
3115 //================================================================================
3117 * \brief Create a sub-mesh on a given sub-shape
3119 //================================================================================
3121 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
3123 if(MYDEBUG) MESSAGE( "createSubMesh" );
3124 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
3125 ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
3128 SMESH_subMesh_i * subMeshServant;
3131 subMeshId = mySubMesh->GetId();
3132 subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
3134 else // "invalid sub-mesh"
3136 // The invalid sub-mesh is created for the case where a valid sub-shape not found
3137 // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0.
3138 if ( _mapSubMesh.empty() )
3141 subMeshId = _mapSubMesh.begin()->first - 1;
3142 subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject);
3145 SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
3147 _mapSubMesh [subMeshId] = mySubMesh;
3148 _mapSubMesh_i [subMeshId] = subMeshServant;
3149 _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
3151 subMeshServant->Register();
3153 // register CORBA object for persistence
3154 int nextId = _gen_i->RegisterObject( subMesh );
3155 if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
3156 else { (void)nextId; } // avoid "unused variable" warning
3158 // to track changes of GEOM groups
3159 if ( subMeshId > 0 )
3160 addGeomGroupData( theSubShapeObject, subMesh );
3162 return subMesh._retn();
3165 //================================================================================
3167 * \brief Return an existing sub-mesh based on a sub-shape with the given ID
3169 //================================================================================
3171 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
3173 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
3174 if ( it == _mapSubMeshIor.end() )
3175 return SMESH::SMESH_subMesh::_nil();
3177 return SMESH::SMESH_subMesh::_duplicate( (*it).second );
3180 //================================================================================
3182 * \brief Remove a sub-mesh based on the given sub-shape
3184 //================================================================================
3186 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
3187 GEOM::GEOM_Object_ptr theSubShapeObject )
3189 bool isHypChanged = false;
3190 if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
3191 return isHypChanged;
3193 const int subMeshId = theSubMesh->GetId();
3195 if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
3198 if (( _mapSubMesh.count( subMeshId )) &&
3199 ( sm = _impl->GetSubMeshContaining( subMeshId )))
3201 TopoDS_Shape S = sm->GetSubShape();
3204 list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
3205 isHypChanged = !hyps.empty();
3206 if ( isHypChanged && _preMeshInfo )
3207 _preMeshInfo->ForgetOrLoad();
3208 list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
3209 for ( ; hyp != hyps.end(); ++hyp )
3210 _impl->RemoveHypothesis(S, (*hyp)->GetID());
3217 SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
3218 isHypChanged = ( aHypList->length() > 0 );
3219 for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
3220 removeHypothesis( theSubShapeObject, aHypList[i] );
3223 catch( const SALOME::SALOME_Exception& ) {
3224 INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
3226 removeGeomGroupData( theSubShapeObject );
3230 std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
3231 if ( id_smi != _mapSubMesh_i.end() )
3232 id_smi->second->UnRegister();
3234 // remove a CORBA object
3235 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
3236 if ( id_smptr != _mapSubMeshIor.end() )
3237 SMESH::SMESH_subMesh_var( id_smptr->second );
3239 _mapSubMesh.erase(subMeshId);
3240 _mapSubMesh_i.erase(subMeshId);
3241 _mapSubMeshIor.erase(subMeshId);
3243 return isHypChanged;
3246 //================================================================================
3248 * \brief Create a group. Group type depends on given arguments
3250 //================================================================================
3252 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
3253 const char* theName,
3255 const TopoDS_Shape& theShape,
3256 const SMESH_PredicatePtr& thePredicate )
3258 std::string newName;
3259 if ( !theName || !theName[0] )
3261 std::set< std::string > presentNames;
3262 std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
3263 for ( ; i_gr != _mapGroups.end(); ++i_gr )
3265 CORBA::String_var name = i_gr->second->GetName();
3266 presentNames.insert( name.in() );
3269 newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
3270 } while ( !presentNames.insert( newName ).second );
3271 theName = newName.c_str();
3273 SMESH::SMESH_GroupBase_var aGroup;
3274 if ( SMESH_Group* g = _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName,
3275 theID, theShape, thePredicate ))
3277 int anId = g->GetID();
3278 SMESH_GroupBase_i* aGroupImpl;
3279 if ( !theShape.IsNull() )
3280 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3281 else if ( thePredicate )
3282 aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
3284 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3286 aGroup = aGroupImpl->_this();
3287 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3288 aGroupImpl->Register();
3290 // register CORBA object for persistence
3291 int nextId = _gen_i->RegisterObject( aGroup );
3292 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
3293 else { nextId = ( nextId > 0 ); } // avoid "unused variable" warning in release mode
3295 // to track changes of GEOM groups
3296 if ( !theShape.IsNull() ) {
3297 GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
3298 addGeomGroupData( geom, aGroup );
3301 return aGroup._retn();
3304 //=============================================================================
3306 * SMESH_Mesh_i::removeGroup
3308 * Should be called by ~SMESH_Group_i()
3310 //=============================================================================
3312 void SMESH_Mesh_i::removeGroup( const int theId )
3314 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
3315 if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
3316 SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
3317 _mapGroups.erase( theId );
3318 removeGeomGroupData( group );
3319 if ( !_impl->RemoveGroup( theId ))
3321 // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
3322 RemoveGroup( group );
3324 group->UnRegister();
3328 //================================================================================
3330 * \brief Return a log that can be used to move another mesh to the same state as this one
3332 //================================================================================
3334 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
3336 SMESH::log_array_var aLog;
3340 _preMeshInfo->FullLoadFromFile();
3342 list < SMESHDS_Command * >logDS = _impl->GetLog();
3343 aLog = new SMESH::log_array;
3345 int lg = logDS.size();
3347 list < SMESHDS_Command * >::iterator its = logDS.begin();
3348 while(its != logDS.end()){
3349 SMESHDS_Command *com = *its;
3350 int comType = com->GetType();
3351 smIdType lgcom = com->GetNumber();
3352 const list < smIdType >&intList = com->GetIndexes();
3353 int inum = intList.size();
3354 list < smIdType >::const_iterator ii = intList.begin();
3355 const list < double >&coordList = com->GetCoords();
3356 int rnum = coordList.size();
3357 list < double >::const_iterator ir = coordList.begin();
3358 aLog[indexLog].commandType = comType;
3359 aLog[indexLog].number = lgcom;
3360 aLog[indexLog].coords.length(rnum);
3361 aLog[indexLog].indexes.length(inum);
3362 for(int i = 0; i < rnum; i++){
3363 aLog[indexLog].coords[i] = *ir;
3366 for(int i = 0; i < inum; i++){
3367 aLog[indexLog].indexes[i] = *ii;
3376 SMESH_CATCH( SMESH::throwCorbaException );
3378 return aLog._retn();
3381 //================================================================================
3383 * \brief Remove the log of commands
3385 //================================================================================
3387 void SMESH_Mesh_i::ClearLog()
3391 SMESH_CATCH( SMESH::throwCorbaException );
3394 //================================================================================
3396 * \brief Return a mesh ID
3398 //================================================================================
3400 CORBA::Long SMESH_Mesh_i::GetId()
3405 //=============================================================================
3408 //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
3409 // issue 0020918: groups removal is caused by hyp modification
3410 // issue 0021208: to forget not loaded mesh data at hyp modification
3411 struct TCallUp_i : public SMESH_Mesh::TCallUp
3413 SMESH_Mesh_i* _mesh;
3414 TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
3415 void RemoveGroup (const int theGroupID) override { _mesh->removeGroup( theGroupID ); }
3416 void HypothesisModified( int hypID,
3417 bool updIcons) override { _mesh->onHypothesisModified( hypID,
3419 void Load () override { _mesh->Load(); }
3420 bool IsLoaded() override { return _mesh->IsLoaded(); }
3421 TopoDS_Shape GetShapeByEntry(const std::string& entry) override
3423 GEOM::GEOM_Object_var go = SMESH_Gen_i::GetGeomObjectByEntry( entry );
3424 return SMESH_Gen_i::GeomObjectToShape( go );
3429 //================================================================================
3431 * \brief callback from _impl to
3432 * 1) forget not loaded mesh data (issue 0021208)
3433 * 2) mark hypothesis as valid
3435 //================================================================================
3437 void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons)
3440 _preMeshInfo->ForgetOrLoad();
3442 if ( theUpdateIcons )
3444 SMESH::SMESH_Mesh_var mesh = _this();
3445 _gen_i->UpdateIcons( mesh );
3448 if ( _nbInvalidHypos != 0 )
3450 // mark a hypothesis as valid after edition
3452 SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
3453 SALOMEDS::SObject_wrap hypRoot;
3454 if ( !smeshComp->_is_nil() &&
3455 smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
3457 SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
3458 for ( ; anIter->More(); anIter->Next() )
3460 SALOMEDS::SObject_wrap hypSO = anIter->Value();
3461 CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO );
3462 SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
3463 if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
3464 _gen_i->HighLightInvalid( hyp, false );
3466 nbInvalid += _gen_i->IsInvalid( hypSO );
3469 _nbInvalidHypos = nbInvalid;
3473 //================================================================================
3475 * \brief Set mesh implementation
3477 //================================================================================
3479 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
3481 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
3484 _impl->SetCallUp( new TCallUp_i(this));
3487 //=============================================================================
3489 * Return a mesh implementation
3491 //=============================================================================
3493 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
3495 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
3499 //=============================================================================
3501 * Return mesh editor
3503 //=============================================================================
3505 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
3507 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3511 _preMeshInfo->FullLoadFromFile();
3513 // Create MeshEditor
3515 _editor = new SMESH_MeshEditor_i( this, false );
3516 aMeshEdVar = _editor->_this();
3518 // Update Python script
3519 TPythonDump() << _editor << " = "
3520 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
3522 SMESH_CATCH( SMESH::throwCorbaException );
3524 return aMeshEdVar._retn();
3527 //=============================================================================
3529 * Return mesh edition previewer
3531 //=============================================================================
3533 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
3535 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3539 _preMeshInfo->FullLoadFromFile();
3541 if ( !_previewEditor )
3542 _previewEditor = new SMESH_MeshEditor_i( this, true );
3543 aMeshEdVar = _previewEditor->_this();
3545 SMESH_CATCH( SMESH::throwCorbaException );
3547 return aMeshEdVar._retn();
3550 //================================================================================
3552 * \brief Return true if the mesh has been edited since a last total re-compute
3553 * and those modifications may prevent successful partial re-compute
3555 //================================================================================
3557 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard()
3559 Unexpect aCatch(SALOME_SalomeException);
3560 return _impl->HasModificationsToDiscard();
3563 //================================================================================
3565 * \brief Return a random unique color
3567 //================================================================================
3569 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
3571 const int MAX_ATTEMPTS = 100;
3573 double tolerance = 0.5;
3574 SALOMEDS::Color col;
3578 // generate random color
3579 double red = (double)rand() / RAND_MAX;
3580 double green = (double)rand() / RAND_MAX;
3581 double blue = (double)rand() / RAND_MAX;
3582 // check existence in the list of the existing colors
3583 bool matched = false;
3584 std::list<SALOMEDS::Color>::const_iterator it;
3585 for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
3586 SALOMEDS::Color color = *it;
3587 double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B - blue );
3588 matched = tol < tolerance;
3590 if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
3591 ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
3599 //=============================================================================
3601 * Set auto-color mode. If it is on, groups get unique random colors
3603 //=============================================================================
3605 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor)
3607 Unexpect aCatch(SALOME_SalomeException);
3608 _impl->SetAutoColor(theAutoColor);
3610 TPythonDump pyDump; // not to dump group->SetColor() from below code
3611 pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
3613 std::list<SALOMEDS::Color> aReservedColors;
3614 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
3615 for ( ; it != _mapGroups.end(); it++ ) {
3616 if ( CORBA::is_nil( it->second )) continue;
3617 SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
3618 it->second->SetColor( aColor );
3619 aReservedColors.push_back( aColor );
3623 //=============================================================================
3625 * Return true if auto-color mode is on
3627 //=============================================================================
3629 CORBA::Boolean SMESH_Mesh_i::GetAutoColor()
3631 Unexpect aCatch(SALOME_SalomeException);
3632 return _impl->GetAutoColor();
3635 //=============================================================================
3637 * Check if there are groups with equal names
3639 //=============================================================================
3641 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
3643 return _impl->HasDuplicatedGroupNamesMED();
3646 //================================================================================
3648 * \brief Care of a file before exporting mesh into it
3650 //================================================================================
3652 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
3654 SMESH_File aFile( file, false );
3656 if ( aFile.exists() ) {
3657 // existing filesystem node
3658 if ( !aFile.isDirectory() ) {
3659 if ( aFile.openForWriting() ) {
3660 if ( overwrite && ! aFile.remove()) {
3661 msg << "Can't replace " << aFile.getName();
3664 msg << "Can't write into " << aFile.getName();
3667 msg << "Location " << aFile.getName() << " is not a file";
3671 // nonexisting file; check if it can be created
3672 if ( !aFile.openForWriting() ) {
3673 msg << "You cannot create the file "
3675 << ". Check the directory existence and access rights";
3683 THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
3690 std::string SMESH_Mesh_i::generateMeshName()
3692 string aMeshName = "Mesh";
3693 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3694 if ( !aStudy->_is_nil() )
3696 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3697 if ( !aMeshSO->_is_nil() )
3699 CORBA::String_var name = aMeshSO->GetName();
3706 //================================================================================
3708 * \brief Prepare a file for export and pass names of mesh groups from study to mesh DS
3709 * \param file - file name
3710 * \param overwrite - to erase the file or not
3711 * \retval string - mesh name
3713 //================================================================================
3715 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char* file,
3716 CORBA::Boolean overwrite)
3719 PrepareForWriting(file, overwrite);
3720 string aMeshName(this->generateMeshName());
3721 SALOMEDS::Study_var aStudy = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
3722 if ( !aStudy->_is_nil() ) {
3723 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3724 if ( !aMeshSO->_is_nil() ) {
3725 // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
3726 if ( !aStudy->GetProperties()->IsLocked() )
3728 SALOMEDS::GenericAttribute_wrap anAttr;
3729 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3730 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
3731 SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
3732 ASSERT(!aFileName->_is_nil());
3733 aFileName->SetValue(file);
3734 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
3735 SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
3736 ASSERT(!aFileType->_is_nil());
3737 aFileType->SetValue("FICHIERMED");
3741 // Update Python script
3742 // set name of mesh before export
3743 TPythonDump() << _gen_i << ".SetName("
3744 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
3746 // check names of groups
3752 //================================================================================
3754 * \brief Export to MED file
3756 //================================================================================
3758 void SMESH_Mesh_i::ExportMED(const char* file,
3759 CORBA::Boolean auto_groups,
3760 CORBA::Long version,
3761 CORBA::Boolean overwrite,
3762 CORBA::Boolean autoDimension)
3764 //MESSAGE("MED minor version: "<< minor);
3767 _preMeshInfo->FullLoadFromFile();
3769 string aMeshName = prepareMeshNameAndGroups(file, overwrite);
3770 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, 0, autoDimension );
3772 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportMED( r'"
3774 << "auto_groups=" <<auto_groups << ", "
3775 << "version=" << version << ", "
3776 << "overwrite=" << overwrite << ", "
3777 << "meshPart=None, "
3778 << "autoDimension=" << autoDimension << " )";
3780 SMESH_CATCH( SMESH::throwCorbaException );
3783 CORBA::LongLong SMESH_Mesh_i::ExportMEDCoupling(CORBA::Boolean auto_groups, CORBA::Boolean autoDimension)
3785 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> data;
3787 // TODO : Fix me ! 2 next lines are required
3788 if( !this->_gen_i->isSSLMode() )
3789 SMESH::throwCorbaException("SMESH_Mesh_i::ExportMEDCoupling : only for embedded mode !");
3791 _preMeshInfo->FullLoadFromFile();
3793 string aMeshName = this->generateMeshName();
3794 data = _impl->ExportMEDCoupling( aMeshName.c_str(), auto_groups, 0, autoDimension );
3795 SMESH_CATCH( SMESH::throwCorbaException );
3796 MEDCoupling::DataArrayByte *ret(data.retn());
3797 return reinterpret_cast<CORBA::LongLong>(ret);
3800 //================================================================================
3802 * \brief Export a mesh to a SAUV file
3804 //================================================================================
3806 void SMESH_Mesh_i::ExportSAUV( const char* file, CORBA::Boolean auto_groups )
3810 _preMeshInfo->FullLoadFromFile();
3812 string aMeshName = prepareMeshNameAndGroups(file, true);
3813 TPythonDump() << SMESH::SMESH_Mesh_var( _this())
3814 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
3815 _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
3817 SMESH_CATCH( SMESH::throwCorbaException );
3821 //================================================================================
3823 * \brief Export a mesh to a DAT file
3825 //================================================================================
3827 void SMESH_Mesh_i::ExportDAT (const char *file, CORBA::Boolean renumber )
3831 _preMeshInfo->FullLoadFromFile();
3833 // check names of groups
3835 // Update Python script
3836 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3837 << ".ExportDAT( r'" << file<< ", " << renumber << "' )";
3840 PrepareForWriting( file );
3841 _impl->ExportDAT( file, /*part=*/nullptr, renumber );
3843 SMESH_CATCH( SMESH::throwCorbaException );
3846 //================================================================================
3848 * \brief Export a mesh to an UNV file
3850 //================================================================================
3852 void SMESH_Mesh_i::ExportUNV (const char *file, CORBA::Boolean renumber)
3856 _preMeshInfo->FullLoadFromFile();
3858 // check names of groups
3860 // Update Python script
3861 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3862 << ".ExportUNV( r'" << file << "' " << renumber << "' )";
3865 PrepareForWriting( file );
3866 _impl->ExportUNV( file, /*part=*/nullptr, renumber );
3868 SMESH_CATCH( SMESH::throwCorbaException );
3871 //================================================================================
3873 * \brief Export a mesh to an STL file
3875 //================================================================================
3877 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3881 _preMeshInfo->FullLoadFromFile();
3883 // check names of groups
3885 // Update Python script
3886 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3887 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3889 CORBA::String_var name;
3890 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( _this() );
3891 if ( !so->_is_nil() )
3892 name = so->GetName();
3895 PrepareForWriting( file );
3896 _impl->ExportSTL( file, isascii, name.in() );
3898 SMESH_CATCH( SMESH::throwCorbaException );
3901 //================================================================================
3906 MEDFileSpeCls(const char * file,
3907 CORBA::Boolean overwrite,
3908 CORBA::Long version)
3909 :_file(file), _overwrite(overwrite), _version(version)
3911 std::string prepareMeshNameAndGroups(SMESH_Mesh_i& self)
3913 return self.prepareMeshNameAndGroups(_file.c_str(),_overwrite);
3916 void exportTo(SMESH_Mesh *mesh, const std::string& aMeshName, CORBA::Boolean auto_groups,
3917 SMESH_MeshPartDS* partDS, CORBA::Boolean autoDimension, bool have0dField,
3918 CORBA::Double ZTolerance, CORBA::Boolean saveNumbers )
3920 mesh->ExportMED( _file.c_str(), aMeshName.c_str(), auto_groups, _version,
3921 partDS, autoDimension, have0dField, ZTolerance, saveNumbers );
3924 void exportField(SMESH_Mesh_i& self, const std::string& aMeshName, bool have0dField,
3925 SMESHDS_Mesh *meshDS, const GEOM::ListOfFields& fields,
3926 const char*geomAssocFields)
3928 DriverMED_W_Field fieldWriter;
3929 fieldWriter.SetFile( _file.c_str() );
3930 fieldWriter.SetMeshName( aMeshName );
3931 fieldWriter.AddODOnVertices( have0dField );
3932 self.exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3935 void prepareForWriting(SMESH_Mesh_i& self) { self.PrepareForWriting(_file.c_str(), _overwrite); }
3939 CORBA::Boolean _overwrite;
3940 CORBA::Long _version;
3943 //================================================================================
3945 * \brief Export a part of mesh to a med file
3947 //================================================================================
3949 template<class SPECLS>
3950 void SMESH_Mesh_i::ExportPartToMEDCommon(SPECLS& speCls,
3951 SMESH::SMESH_IDSource_ptr meshPart,
3952 CORBA::Boolean auto_groups,
3953 CORBA::Boolean autoDimension,
3954 const GEOM::ListOfFields& fields,
3955 const char* geomAssocFields,
3956 CORBA::Double ZTolerance,
3957 CORBA::Boolean saveNumbers)
3961 _preMeshInfo->FullLoadFromFile();
3964 bool have0dField = false;
3965 if ( fields.length() > 0 )
3967 GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3968 if ( shapeToMesh->_is_nil() )
3969 THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3971 for ( size_t i = 0; i < fields.length(); ++i )
3973 if ( fields[i]->GetDataType() == GEOM::FDT_String )
3974 THROW_SALOME_CORBA_EXCEPTION
3975 ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3976 GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3977 if ( fieldShape->_is_nil() )
3978 THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3979 if ( !fieldShape->IsSame( shapeToMesh ) )
3980 THROW_SALOME_CORBA_EXCEPTION( "Field defined not on shape", SALOME::BAD_PARAM);
3981 if ( fields[i]->GetDimension() == 0 )
3984 if ( geomAssocFields )
3985 for ( int i = 0; geomAssocFields[i]; ++i )
3986 switch ( geomAssocFields[i] ) {
3987 case 'v':case 'e':case 'f':case 's': break;
3988 case 'V':case 'E':case 'F':case 'S': break;
3989 default: THROW_SALOME_CORBA_EXCEPTION
3990 ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3994 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3998 string aMeshName = "Mesh";
3999 SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
4000 if ( CORBA::is_nil( meshPart ) ||
4001 SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
4003 aMeshName = speCls.prepareMeshNameAndGroups(*this);
4004 speCls.exportTo(_impl, aMeshName, auto_groups, nullptr, autoDimension,
4005 have0dField, ZTolerance, saveNumbers );
4006 meshDS = _impl->GetMeshDS();
4011 _preMeshInfo->FullLoadFromFile();
4013 speCls.prepareForWriting(*this);
4015 SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( meshPart );
4016 if ( !SO->_is_nil() ) {
4017 CORBA::String_var name = SO->GetName();
4021 SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
4022 speCls.exportTo(_impl, aMeshName, auto_groups, partDS, autoDimension,
4023 have0dField, ZTolerance, saveNumbers);
4024 meshDS = tmpDSDeleter._obj = partDS;
4029 if ( _impl->HasShapeToMesh() )
4031 speCls.exportField( *this, aMeshName, have0dField, meshDS, fields, geomAssocFields);
4033 SMESH_CATCH( SMESH::throwCorbaException );
4036 //================================================================================
4038 * \brief Export a part of mesh to a med file
4040 //================================================================================
4042 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
4044 CORBA::Boolean auto_groups,
4045 CORBA::Long version,
4046 CORBA::Boolean overwrite,
4047 CORBA::Boolean autoDimension,
4048 const GEOM::ListOfFields& fields,
4049 const char* geomAssocFields,
4050 CORBA::Double ZTolerance,
4051 CORBA::Boolean saveNumbers)
4053 MESSAGE("MED version: "<< version);
4055 MEDFileSpeCls spe( file, overwrite, version );
4056 this->ExportPartToMEDCommon( spe, meshPart, auto_groups, autoDimension, fields,
4057 geomAssocFields, ZTolerance, saveNumbers );
4060 GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
4061 goList->length( fields.length() );
4062 for ( size_t i = 0; i < fields.length(); ++i )
4064 GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
4067 TPythonDump() << _this() << ".ExportPartToMED( "
4068 << meshPart << ", r'"
4070 << auto_groups << ", "
4072 << overwrite << ", "
4073 << autoDimension << ", "
4075 << ( geomAssocFields ? geomAssocFields : "" ) << "',"
4076 << TVar( ZTolerance ) << ", "
4079 SMESH_CATCH( SMESH::throwCorbaException );
4082 //================================================================================
4084 class MEDFileMemSpeCls
4087 std::string prepareMeshNameAndGroups(SMESH_Mesh_i& self) { return self.generateMeshName(); }
4089 void exportTo(SMESH_Mesh *mesh, const std::string& aMeshName, CORBA::Boolean auto_groups,
4090 SMESH_MeshPartDS* partDS, CORBA::Boolean autoDimension, bool have0dField,
4091 CORBA::Double ZTolerance, CORBA::Boolean saveNumbers )
4093 _res = mesh->ExportMEDCoupling(aMeshName.c_str(), auto_groups, partDS,
4094 autoDimension, have0dField, ZTolerance, saveNumbers );
4096 void prepareForWriting(SMESH_Mesh_i& /*self*/) { /* nothing here */ }
4098 void exportField(SMESH_Mesh_i& self, const std::string& aMeshName, bool have0dField,
4099 SMESHDS_Mesh *meshDS, const GEOM::ListOfFields& fields,
4100 const char*geomAssocFields)
4102 DriverMED_W_Field_Mem fieldWriter(_res);
4103 fieldWriter.SetMeshName( aMeshName );
4104 fieldWriter.AddODOnVertices( have0dField );
4105 self.exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
4106 _res = fieldWriter.getData();
4109 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> getData() { return _res; }
4112 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> _res;
4115 //================================================================================
4117 * \brief Export a part of mesh to a MEDCoupling DS
4119 //================================================================================
4121 CORBA::LongLong SMESH_Mesh_i::ExportPartToMEDCoupling(SMESH::SMESH_IDSource_ptr meshPart,
4122 CORBA::Boolean auto_groups,
4123 CORBA::Boolean autoDimension,
4124 const GEOM::ListOfFields& fields,
4125 const char* geomAssocFields,
4126 CORBA::Double ZTolerance,
4127 CORBA::Boolean saveNumbers)
4129 MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> data;
4132 if( !this->_gen_i->isSSLMode() )
4133 SMESH::throwCorbaException("SMESH_Mesh_i::ExportPartToMEDCoupling : only for embedded mode !");
4135 MEDFileMemSpeCls spe;
4136 this->ExportPartToMEDCommon( spe, meshPart, auto_groups, autoDimension, fields, geomAssocFields,
4137 ZTolerance, saveNumbers );
4138 data = spe.getData();
4140 SMESH_CATCH( SMESH::throwCorbaException );
4142 MEDCoupling::DataArrayByte *ret(data.retn());
4143 return reinterpret_cast<CORBA::LongLong>(ret);
4146 //================================================================================
4148 * Write GEOM fields to MED file
4150 //================================================================================
4152 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field& fieldWriter,
4153 SMESHDS_Mesh* meshDS,
4154 const GEOM::ListOfFields& fields,
4155 const char* geomAssocFields)
4157 #define METH "SMESH_Mesh_i::exportMEDFields() "
4159 if (( fields.length() < 1 ) &&
4160 ( !geomAssocFields || !geomAssocFields[0] ))
4163 std::vector< std::vector< double > > dblVals;
4164 std::vector< std::vector< int > > intVals;
4165 std::vector< int > subIdsByDim[ 4 ];
4166 const double noneDblValue = 0.;
4167 const double noneIntValue = 0;
4169 for ( size_t iF = 0; iF < fields.length(); ++iF )
4173 int dim = fields[ iF ]->GetDimension();
4174 SMDSAbs_ElementType elemType;
4175 TopAbs_ShapeEnum shapeType;
4177 case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
4178 case 1: elemType = SMDSAbs_Edge; shapeType = TopAbs_EDGE; break;
4179 case 2: elemType = SMDSAbs_Face; shapeType = TopAbs_FACE; break;
4180 case 3: elemType = SMDSAbs_Volume; shapeType = TopAbs_SOLID; break;
4182 continue; // skip fields on whole shape
4184 GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
4185 if ( dataType == GEOM::FDT_String )
4187 GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
4188 if ( stepIDs->length() < 1 )
4190 GEOM::string_array_var comps = fields[ iF ]->GetComponents();
4191 if ( comps->length() < 1 )
4193 CORBA::String_var name = fields[ iF ]->GetName();
4195 if ( !fieldWriter.Set( meshDS,
4199 /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
4202 for ( size_t iC = 0; iC < comps->length(); ++iC )
4203 fieldWriter.SetCompName( iC, comps[ iC ].in() );
4205 dblVals.resize( comps->length() );
4206 intVals.resize( comps->length() );
4208 // find sub-shape IDs
4210 std::vector< int >& subIds = subIdsByDim[ dim ];
4211 if ( subIds.empty() )
4212 for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
4213 if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
4214 subIds.push_back( id );
4218 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4222 for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
4224 GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
4225 if ( step->_is_nil() )
4228 CORBA::Long stamp = step->GetStamp();
4229 CORBA::Long id = step->GetID();
4230 fieldWriter.SetDtIt( int( stamp ), int( id ));
4232 // fill dblVals or intVals
4233 for ( size_t iC = 0; iC < comps->length(); ++iC )
4234 if ( dataType == GEOM::FDT_Double )
4236 dblVals[ iC ].clear();
4237 dblVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4241 intVals[ iC ].clear();
4242 intVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4246 case GEOM::FDT_Double:
4248 GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
4249 if ( dblStep->_is_nil() ) continue;
4250 GEOM::ListOfDouble_var vv = dblStep->GetValues();
4251 if ( vv->length() != subIds.size() * comps->length() )
4252 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4253 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4254 for ( size_t iC = 0; iC < comps->length(); ++iC )
4255 dblVals[ iC ][ subIds[ iS ]] = vv[ iV++ ];
4260 GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
4261 if ( intStep->_is_nil() ) continue;
4262 GEOM::ListOfLong_var vv = intStep->GetValues();
4263 if ( vv->length() != subIds.size() * comps->length() )
4264 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4265 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4266 for ( size_t iC = 0; iC < comps->length(); ++iC )
4267 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4270 case GEOM::FDT_Bool:
4272 GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
4273 if ( boolStep->_is_nil() ) continue;
4274 GEOM::short_array_var vv = boolStep->GetValues();
4275 if ( vv->length() != subIds.size() * comps->length() )
4276 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4277 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4278 for ( size_t iC = 0; iC < comps->length(); ++iC )
4279 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4285 // pass values to fieldWriter
4286 elemIt = fieldWriter.GetOrderedElems();
4287 if ( dataType == GEOM::FDT_Double )
4288 while ( elemIt->more() )
4290 const SMDS_MeshElement* e = elemIt->next();
4291 const int shapeID = e->getshapeId();
4292 if ( shapeID < 1 || shapeID >= (int) dblVals[0].size() )
4293 for ( size_t iC = 0; iC < comps->length(); ++iC )
4294 fieldWriter.AddValue( noneDblValue );
4296 for ( size_t iC = 0; iC < comps->length(); ++iC )
4297 fieldWriter.AddValue( dblVals[ iC ][ shapeID ]);
4300 while ( elemIt->more() )
4302 const SMDS_MeshElement* e = elemIt->next();
4303 const int shapeID = e->getshapeId();
4304 if ( shapeID < 1 || shapeID >= (int) intVals[0].size() )
4305 for ( size_t iC = 0; iC < comps->length(); ++iC )
4306 fieldWriter.AddValue( (double) noneIntValue );
4308 for ( size_t iC = 0; iC < comps->length(); ++iC )
4309 fieldWriter.AddValue( (double) intVals[ iC ][ shapeID ]);
4313 fieldWriter.Perform();
4314 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4315 if ( res && res->IsKO() )
4317 if ( res->myComment.empty() )
4318 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4320 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4326 if ( !geomAssocFields || !geomAssocFields[0] )
4329 // write geomAssocFields
4331 std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
4332 shapeDim[ TopAbs_COMPOUND ] = 3;
4333 shapeDim[ TopAbs_COMPSOLID ] = 3;
4334 shapeDim[ TopAbs_SOLID ] = 3;
4335 shapeDim[ TopAbs_SHELL ] = 2;
4336 shapeDim[ TopAbs_FACE ] = 2;
4337 shapeDim[ TopAbs_WIRE ] = 1;
4338 shapeDim[ TopAbs_EDGE ] = 1;
4339 shapeDim[ TopAbs_VERTEX ] = 0;
4340 shapeDim[ TopAbs_SHAPE ] = 3;
4342 for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
4344 std::vector< std::string > compNames;
4345 switch ( geomAssocFields[ iF ]) {
4347 fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
4348 compNames.push_back( "dim" );
4351 fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
4354 fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
4357 fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
4361 compNames.push_back( "id" );
4362 for ( size_t iC = 0; iC < compNames.size(); ++iC )
4363 fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
4365 fieldWriter.SetDtIt( -1, -1 );
4367 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4371 if ( compNames.size() == 2 ) // _vertices_
4372 while ( elemIt->more() )
4374 const SMDS_MeshElement* e = elemIt->next();
4375 const int shapeID = e->getshapeId();
4378 fieldWriter.AddValue( (double) -1 );
4379 fieldWriter.AddValue( (double) -1 );
4383 const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
4384 fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
4385 fieldWriter.AddValue( (double) shapeID );
4389 while ( elemIt->more() )
4391 const SMDS_MeshElement* e = elemIt->next();
4392 const int shapeID = e->getshapeId();
4394 fieldWriter.AddValue( (double) -1 );
4396 fieldWriter.AddValue( (double) shapeID );
4400 fieldWriter.Perform();
4401 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4402 if ( res && res->IsKO() )
4404 if ( res->myComment.empty() )
4405 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4407 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4410 } // loop on geomAssocFields
4415 //================================================================================
4417 * \brief Export a part of mesh to a DAT file
4419 //================================================================================
4421 void SMESH_Mesh_i::ExportPartToDAT(SMESH::SMESH_IDSource_ptr meshPart,
4423 CORBA::Boolean renumber )
4427 SMESH_MeshPartDS partDS( meshPart );
4428 _impl->ExportDAT( file, &partDS, renumber );
4430 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4431 << ".ExportPartToDAT( " << meshPart << ", r'" << file << ", " << renumber << "' )";
4433 SMESH_CATCH( SMESH::throwCorbaException );
4435 //================================================================================
4437 * \brief Export a part of mesh to an UNV file
4439 //================================================================================
4441 void SMESH_Mesh_i::ExportPartToUNV(SMESH::SMESH_IDSource_ptr meshPart,
4443 CORBA::Boolean renumber)
4447 _preMeshInfo->FullLoadFromFile();
4449 PrepareForWriting(file);
4451 SMESH_MeshPartDS partDS( meshPart );
4452 _impl->ExportUNV(file, &partDS, renumber );
4454 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4455 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << ", " << renumber << "' )";
4457 SMESH_CATCH( SMESH::throwCorbaException );
4459 //================================================================================
4461 * \brief Export a part of mesh to an STL file
4463 //================================================================================
4465 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
4467 ::CORBA::Boolean isascii)
4471 _preMeshInfo->FullLoadFromFile();
4473 PrepareForWriting(file);
4475 CORBA::String_var name;
4476 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4477 if ( !so->_is_nil() )
4478 name = so->GetName();
4480 SMESH_MeshPartDS partDS( meshPart );
4481 _impl->ExportSTL( file, isascii, name.in(), &partDS );
4483 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
4484 << meshPart<< ", r'" << file << "', " << isascii << ")";
4486 SMESH_CATCH( SMESH::throwCorbaException );
4489 //================================================================================
4491 * \brief Export a part of mesh to an STL file
4493 //================================================================================
4495 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
4497 CORBA::Boolean overwrite,
4498 CORBA::Boolean groupElemsByType)
4503 _preMeshInfo->FullLoadFromFile();
4505 PrepareForWriting(file,overwrite);
4507 std::string meshName("");
4508 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4509 if ( !so->_is_nil() )
4511 CORBA::String_var name = so->GetName();
4512 meshName = name.in();
4516 SMESH_MeshPartDS partDS( meshPart );
4517 _impl->ExportCGNS(file, &partDS, meshName.c_str(), groupElemsByType );
4519 SMESH_CATCH( SMESH::throwCorbaException );
4521 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
4522 << meshPart<< ", r'" << file << "', " << overwrite << ")";
4524 SMESH_CATCH( SMESH::throwCorbaException );
4527 THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
4531 //================================================================================
4533 * \brief Export a part of mesh to a GMF file
4535 //================================================================================
4537 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
4539 bool withRequiredGroups)
4543 _preMeshInfo->FullLoadFromFile();
4545 PrepareForWriting(file,/*overwrite=*/true);
4547 SMESH_MeshPartDS partDS( meshPart );
4548 _impl->ExportGMF(file, &partDS, withRequiredGroups);
4550 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
4551 << meshPart<< ", r'"
4553 << withRequiredGroups << ")";
4555 SMESH_CATCH( SMESH::throwCorbaException );
4558 //=============================================================================
4560 * Return computation progress [0.,1]
4562 //=============================================================================
4564 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
4568 return _impl->GetComputeProgress();
4570 SMESH_CATCH( SMESH::doNothing );
4574 //================================================================================
4576 * \brief Return nb of nodes
4578 //================================================================================
4580 SMESH::smIdType SMESH_Mesh_i::NbNodes()
4582 Unexpect aCatch(SALOME_SalomeException);
4584 return _preMeshInfo->NbNodes();
4586 return _impl->NbNodes();
4589 //================================================================================
4591 * \brief Return nb of elements
4593 //================================================================================
4595 SMESH::smIdType SMESH_Mesh_i::NbElements()
4597 Unexpect aCatch(SALOME_SalomeException);
4599 return _preMeshInfo->NbElements();
4601 return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
4604 //================================================================================
4606 * \brief Return nb of 0D elements
4608 //================================================================================
4610 SMESH::smIdType SMESH_Mesh_i::Nb0DElements()
4612 Unexpect aCatch(SALOME_SalomeException);
4614 return _preMeshInfo->Nb0DElements();
4616 return _impl->Nb0DElements();
4619 //================================================================================
4621 * \brief Return nb of BALL elements
4623 //================================================================================
4625 SMESH::smIdType SMESH_Mesh_i::NbBalls()
4627 Unexpect aCatch(SALOME_SalomeException);
4629 return _preMeshInfo->NbBalls();
4631 return _impl->NbBalls();
4634 //================================================================================
4636 * \brief Return nb of 1D elements
4638 //================================================================================
4640 SMESH::smIdType SMESH_Mesh_i::NbEdges()
4642 Unexpect aCatch(SALOME_SalomeException);
4644 return _preMeshInfo->NbEdges();
4646 return _impl->NbEdges();
4649 //================================================================================
4651 * \brief Return nb of edges
4653 //================================================================================
4655 SMESH::smIdType SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
4657 Unexpect aCatch(SALOME_SalomeException);
4659 return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
4661 return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
4664 //================================================================================
4666 * \brief Return nb of faces
4668 //================================================================================
4670 SMESH::smIdType SMESH_Mesh_i::NbFaces()
4672 Unexpect aCatch(SALOME_SalomeException);
4674 return _preMeshInfo->NbFaces();
4676 return _impl->NbFaces();
4679 //================================================================================
4681 * \brief Return nb of tringles
4683 //================================================================================
4685 SMESH::smIdType SMESH_Mesh_i::NbTriangles()
4687 Unexpect aCatch(SALOME_SalomeException);
4689 return _preMeshInfo->NbTriangles();
4691 return _impl->NbTriangles();
4694 //================================================================================
4696 * \brief Return nb of bi-quadratic triangles
4698 //================================================================================
4700 SMESH::smIdType SMESH_Mesh_i::NbBiQuadTriangles()
4702 Unexpect aCatch(SALOME_SalomeException);
4704 return _preMeshInfo->NbBiQuadTriangles();
4706 return _impl->NbBiQuadTriangles();
4709 SMESH::smIdType SMESH_Mesh_i::NbQuadrangles()
4711 Unexpect aCatch(SALOME_SalomeException);
4713 return _preMeshInfo->NbQuadrangles();
4715 return _impl->NbQuadrangles();
4718 SMESH::smIdType SMESH_Mesh_i::NbBiQuadQuadrangles()
4720 Unexpect aCatch(SALOME_SalomeException);
4722 return _preMeshInfo->NbBiQuadQuadrangles();
4724 return _impl->NbBiQuadQuadrangles();
4727 SMESH::smIdType SMESH_Mesh_i::NbPolygons()
4729 Unexpect aCatch(SALOME_SalomeException);
4731 return _preMeshInfo->NbPolygons();
4733 return _impl->NbPolygons();
4736 SMESH::smIdType SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order)
4738 Unexpect aCatch(SALOME_SalomeException);
4740 return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
4742 return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
4745 SMESH::smIdType SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
4747 Unexpect aCatch(SALOME_SalomeException);
4749 return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
4751 return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
4754 SMESH::smIdType SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
4756 Unexpect aCatch(SALOME_SalomeException);
4758 return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
4760 return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
4763 SMESH::smIdType SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
4765 Unexpect aCatch(SALOME_SalomeException);
4767 return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
4769 return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
4772 //=============================================================================
4774 SMESH::smIdType SMESH_Mesh_i::NbVolumes()
4776 Unexpect aCatch(SALOME_SalomeException);
4778 return _preMeshInfo->NbVolumes();
4780 return _impl->NbVolumes();
4783 SMESH::smIdType SMESH_Mesh_i::NbTetras()
4785 Unexpect aCatch(SALOME_SalomeException);
4787 return _preMeshInfo->NbTetras();
4789 return _impl->NbTetras();
4792 SMESH::smIdType SMESH_Mesh_i::NbHexas()
4794 Unexpect aCatch(SALOME_SalomeException);
4796 return _preMeshInfo->NbHexas();
4798 return _impl->NbHexas();
4801 SMESH::smIdType SMESH_Mesh_i::NbTriQuadraticHexas()
4803 Unexpect aCatch(SALOME_SalomeException);
4805 return _preMeshInfo->NbTriQuadHexas();
4807 return _impl->NbTriQuadraticHexas();
4810 SMESH::smIdType SMESH_Mesh_i::NbPyramids()
4812 Unexpect aCatch(SALOME_SalomeException);
4814 return _preMeshInfo->NbPyramids();
4816 return _impl->NbPyramids();
4819 SMESH::smIdType SMESH_Mesh_i::NbPrisms()
4821 Unexpect aCatch(SALOME_SalomeException);
4823 return _preMeshInfo->NbPrisms();
4825 return _impl->NbPrisms();
4828 SMESH::smIdType SMESH_Mesh_i::NbHexagonalPrisms()
4830 Unexpect aCatch(SALOME_SalomeException);
4832 return _preMeshInfo->NbHexPrisms();
4834 return _impl->NbHexagonalPrisms();
4837 SMESH::smIdType SMESH_Mesh_i::NbPolyhedrons()
4839 Unexpect aCatch(SALOME_SalomeException);
4841 return _preMeshInfo->NbPolyhedrons();
4843 return _impl->NbPolyhedrons();
4846 SMESH::smIdType SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
4848 Unexpect aCatch(SALOME_SalomeException);
4850 return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
4852 return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
4855 SMESH::smIdType SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
4857 Unexpect aCatch(SALOME_SalomeException);
4859 return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
4861 return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
4864 SMESH::smIdType SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
4866 Unexpect aCatch(SALOME_SalomeException);
4868 return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
4870 return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
4873 SMESH::smIdType SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
4875 Unexpect aCatch(SALOME_SalomeException);
4877 return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
4879 return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
4882 SMESH::smIdType SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
4884 Unexpect aCatch(SALOME_SalomeException);
4886 return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
4888 return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
4891 //=============================================================================
4893 * Return nb of published sub-meshes
4895 //=============================================================================
4897 SMESH::smIdType SMESH_Mesh_i::NbSubMesh()
4899 Unexpect aCatch(SALOME_SalomeException);
4900 return _mapSubMesh_i.size();
4903 //=============================================================================
4905 * Dumps mesh into a string
4907 //=============================================================================
4909 char* SMESH_Mesh_i::Dump()
4913 return CORBA::string_dup( os.str().c_str() );
4916 //=============================================================================
4918 * Method of SMESH_IDSource interface
4920 //=============================================================================
4922 SMESH::smIdType_array* SMESH_Mesh_i::GetIDs()
4924 return GetElementsId();
4927 //=============================================================================
4929 * Return ids of all elements
4931 //=============================================================================
4933 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsId()
4935 Unexpect aCatch(SALOME_SalomeException);
4937 _preMeshInfo->FullLoadFromFile();
4939 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
4940 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4942 if ( aSMESHDS_Mesh == NULL )
4943 return aResult._retn();
4945 smIdType nbElements = NbElements();
4946 aResult->length( nbElements );
4947 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
4948 for ( smIdType i = 0, n = nbElements; i < n && anIt->more(); i++ )
4949 aResult[i] = anIt->next()->GetID();
4951 return aResult._retn();
4955 //=============================================================================
4957 * Return ids of all elements of given type
4959 //=============================================================================
4961 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
4963 Unexpect aCatch(SALOME_SalomeException);
4965 _preMeshInfo->FullLoadFromFile();
4967 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
4968 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4970 if ( aSMESHDS_Mesh == NULL )
4971 return aResult._retn();
4973 smIdType nbElements = NbElements();
4975 // No sense in returning ids of elements along with ids of nodes:
4976 // when theElemType == SMESH::ALL, return node ids only if
4977 // there are no elements
4978 if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
4979 return GetNodesId();
4981 aResult->length( nbElements );
4985 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
4986 while ( i < nbElements && anIt->more() )
4987 aResult[i++] = anIt->next()->GetID();
4989 aResult->length( i );
4991 return aResult._retn();
4994 //=============================================================================
4996 * Return ids of all nodes
4998 //=============================================================================
5000 SMESH::smIdType_array* SMESH_Mesh_i::GetNodesId()
5002 Unexpect aCatch(SALOME_SalomeException);
5004 _preMeshInfo->FullLoadFromFile();
5006 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5007 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5009 if ( aMeshDS == NULL )
5010 return aResult._retn();
5012 smIdType nbNodes = NbNodes();
5013 aResult->length( nbNodes );
5014 SMDS_NodeIteratorPtr anIt = aMeshDS->nodesIterator();
5015 for ( smIdType i = 0, n = nbNodes; i < n && anIt->more(); i++ )
5016 aResult[i] = anIt->next()->GetID();
5018 return aResult._retn();
5021 //=============================================================================
5023 * Return type of the given element
5025 //=============================================================================
5027 SMESH::ElementType SMESH_Mesh_i::GetElementType( const SMESH::smIdType id, const bool iselem )
5029 SMESH::ElementType type = SMESH::ALL;
5033 _preMeshInfo->FullLoadFromFile();
5035 type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
5037 SMESH_CATCH( SMESH::throwCorbaException );
5042 //=============================================================================
5044 * Return geometric type of the given element
5046 //=============================================================================
5048 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const SMESH::smIdType id )
5051 _preMeshInfo->FullLoadFromFile();
5053 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
5055 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
5057 return ( SMESH::EntityType ) e->GetEntityType();
5060 //=============================================================================
5062 * Return type of the given element
5064 //=============================================================================
5066 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const SMESH::smIdType id )
5069 _preMeshInfo->FullLoadFromFile();
5071 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
5073 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
5075 return ( SMESH::GeometryType ) e->GetGeomType();
5078 //=============================================================================
5080 * Return ID of elements for given submesh
5082 //=============================================================================
5084 SMESH::smIdType_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
5086 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5090 _preMeshInfo->FullLoadFromFile();
5092 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5093 if(!SM) return aResult._retn();
5095 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5096 if(!SDSM) return aResult._retn();
5098 aResult->length(SDSM->NbElements());
5100 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5102 while ( eIt->more() ) {
5103 aResult[i++] = eIt->next()->GetID();
5106 SMESH_CATCH( SMESH::throwCorbaException );
5108 return aResult._retn();
5111 //=============================================================================
5113 * Return ID of nodes for given sub-mesh
5114 * If param all==true - return all nodes, else -
5115 * Return only nodes on shapes.
5117 //=============================================================================
5119 SMESH::smIdType_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
5122 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5126 _preMeshInfo->FullLoadFromFile();
5128 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5129 if(!SM) return aResult._retn();
5131 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5132 if(!SDSM) return aResult._retn();
5134 set<smIdType> theElems;
5135 if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
5136 SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
5137 while ( nIt->more() ) {
5138 const SMDS_MeshNode* elem = nIt->next();
5139 theElems.insert( elem->GetID() );
5142 else { // all nodes of submesh elements
5143 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5144 while ( eIt->more() ) {
5145 const SMDS_MeshElement* anElem = eIt->next();
5146 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
5147 while ( nIt->more() ) {
5148 const SMDS_MeshElement* elem = nIt->next();
5149 theElems.insert( elem->GetID() );
5154 aResult->length(theElems.size());
5155 set<smIdType>::iterator itElem;
5157 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
5158 aResult[i++] = *itElem;
5160 SMESH_CATCH( SMESH::throwCorbaException );
5162 return aResult._retn();
5165 //=============================================================================
5167 * Return type of elements for given sub-mesh
5169 //=============================================================================
5171 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
5173 SMESH::ElementType type = SMESH::ALL;
5177 _preMeshInfo->FullLoadFromFile();
5179 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
5180 if(!SM) return SMESH::ALL;
5182 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5183 if(!SDSM) return SMESH::ALL;
5185 if(SDSM->NbElements()==0)
5186 return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
5188 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5189 const SMDS_MeshElement* anElem = eIt->next();
5191 type = ( SMESH::ElementType ) anElem->GetType();
5193 SMESH_CATCH( SMESH::throwCorbaException );
5199 //=============================================================================
5201 * Return pointer to _impl as an integer value. Is called from constructor of SMESH_Client
5203 //=============================================================================
5205 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
5208 _preMeshInfo->FullLoadFromFile();
5210 CORBA::LongLong pointeur = CORBA::LongLong(_impl);
5211 if ( MYDEBUG ) MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
5216 //=============================================================================
5218 * Get XYZ coordinates of node as list of double
5219 * If there is not node for given ID - return empty list
5221 //=============================================================================
5223 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const SMESH::smIdType id)
5226 _preMeshInfo->FullLoadFromFile();
5228 SMESH::double_array_var aResult = new SMESH::double_array();
5229 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5230 if ( aMeshDS == NULL )
5231 return aResult._retn();
5234 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5236 return aResult._retn();
5240 aResult[0] = aNode->X();
5241 aResult[1] = aNode->Y();
5242 aResult[2] = aNode->Z();
5243 return aResult._retn();
5247 //=============================================================================
5249 * For given node return list of IDs of inverse elements
5250 * If there is not node for given ID - return empty list
5252 //=============================================================================
5254 SMESH::smIdType_array* SMESH_Mesh_i::GetNodeInverseElements(const SMESH::smIdType id,
5255 SMESH::ElementType elemType)
5258 _preMeshInfo->FullLoadFromFile();
5260 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5261 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5262 if ( aMeshDS == NULL )
5263 return aResult._retn();
5266 const SMDS_MeshNode* aNode = aMeshDS->FindNode( id );
5268 return aResult._retn();
5270 // find inverse elements
5271 SMDSAbs_ElementType type = SMDSAbs_ElementType( elemType );
5272 SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator( type );
5273 aResult->length( aNode->NbInverseElements( type ));
5274 for( smIdType i = 0; eIt->more(); ++i )
5276 const SMDS_MeshElement* elem = eIt->next();
5277 aResult[ i ] = elem->GetID();
5279 return aResult._retn();
5282 //=============================================================================
5284 * \brief Return position of a node on shape
5286 //=============================================================================
5288 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(SMESH::smIdType NodeID)
5291 _preMeshInfo->FullLoadFromFile();
5293 SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
5294 aNodePosition->shapeID = 0;
5295 aNodePosition->shapeType = GEOM::SHAPE;
5297 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5298 if ( !mesh ) return aNodePosition;
5300 if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
5302 if ( SMDS_PositionPtr pos = aNode->GetPosition() )
5304 aNodePosition->shapeID = aNode->getshapeId();
5305 switch ( pos->GetTypeOfPosition() ) {
5307 aNodePosition->shapeType = GEOM::EDGE;
5308 aNodePosition->params.length(1);
5309 aNodePosition->params[0] = SMDS_EdgePositionPtr( pos )->GetUParameter();
5311 case SMDS_TOP_FACE: {
5312 SMDS_FacePositionPtr fPos = pos;
5313 aNodePosition->shapeType = GEOM::FACE;
5314 aNodePosition->params.length(2);
5315 aNodePosition->params[0] = fPos->GetUParameter();
5316 aNodePosition->params[1] = fPos->GetVParameter();
5319 case SMDS_TOP_VERTEX:
5320 aNodePosition->shapeType = GEOM::VERTEX;
5322 case SMDS_TOP_3DSPACE:
5323 if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
5324 aNodePosition->shapeType = GEOM::SOLID;
5325 else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
5326 aNodePosition->shapeType = GEOM::SHELL;
5332 return aNodePosition;
5335 //=============================================================================
5337 * \brief Return position of an element on shape
5339 //=============================================================================
5341 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(SMESH::smIdType ElemID)
5344 _preMeshInfo->FullLoadFromFile();
5346 SMESH::ElementPosition anElementPosition;
5347 anElementPosition.shapeID = 0;
5348 anElementPosition.shapeType = GEOM::SHAPE;
5350 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5351 if ( !mesh ) return anElementPosition;
5353 if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
5355 anElementPosition.shapeID = anElem->getshapeId();
5356 const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
5357 if ( !aSp.IsNull() ) {
5358 switch ( aSp.ShapeType() ) {
5360 anElementPosition.shapeType = GEOM::EDGE;
5363 anElementPosition.shapeType = GEOM::FACE;
5366 anElementPosition.shapeType = GEOM::VERTEX;
5369 anElementPosition.shapeType = GEOM::SOLID;
5372 anElementPosition.shapeType = GEOM::SHELL;
5378 return anElementPosition;
5381 //=============================================================================
5383 * If given element is node return IDs of shape from position
5384 * If there is not node for given ID - return -1
5386 //=============================================================================
5388 CORBA::Long SMESH_Mesh_i::GetShapeID(const SMESH::smIdType id)
5391 _preMeshInfo->FullLoadFromFile();
5393 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5394 if ( aMeshDS == NULL )
5398 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5400 return aNode->getshapeId();
5407 //=============================================================================
5409 * For given element return ID of result shape after
5410 * ::FindShape() from SMESH_MeshEditor
5411 * If there is not element for given ID - return -1
5413 //=============================================================================
5415 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const SMESH::smIdType id)
5418 _preMeshInfo->FullLoadFromFile();
5420 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5421 if ( aMeshDS == NULL )
5424 // try to find element
5425 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5429 ::SMESH_MeshEditor aMeshEditor(_impl);
5430 int index = aMeshEditor.FindShape( elem );
5438 //=============================================================================
5440 * Return number of nodes for given element
5441 * If there is not element for given ID - return -1
5443 //=============================================================================
5445 CORBA::Short SMESH_Mesh_i::GetElemNbNodes(const SMESH::smIdType id)
5448 _preMeshInfo->FullLoadFromFile();
5450 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5451 if ( aMeshDS == NULL ) return -1;
5452 // try to find element
5453 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5454 if(!elem) return -1;
5455 return elem->NbNodes();
5459 //=============================================================================
5461 * Return ID of node by given index for given element
5462 * If there is not element for given ID - return -1
5463 * If there is not node for given index - return -2
5465 //=============================================================================
5467 SMESH::smIdType SMESH_Mesh_i::GetElemNode(const SMESH::smIdType id, const CORBA::Short index)
5470 _preMeshInfo->FullLoadFromFile();
5472 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5473 if ( aMeshDS == NULL ) return -1;
5474 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5475 if(!elem) return -1;
5476 if( index>=elem->NbNodes() || index<0 ) return -1;
5477 return elem->GetNode(index)->GetID();
5480 //=============================================================================
5482 * Return IDs of nodes of given element
5484 //=============================================================================
5486 SMESH::smIdType_array* SMESH_Mesh_i::GetElemNodes(const SMESH::smIdType id)
5489 _preMeshInfo->FullLoadFromFile();
5491 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5492 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5494 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(id) )
5496 aResult->length( elem->NbNodes() );
5497 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5498 if ( const SMDS_MeshNode* n = elem->GetNode( i ))
5499 aResult[ i ] = n->GetID();
5502 return aResult._retn();
5505 //=============================================================================
5507 * Return true if given node is medium node
5508 * in given quadratic element
5510 //=============================================================================
5512 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const SMESH::smIdType ide, const SMESH::smIdType idn)
5515 _preMeshInfo->FullLoadFromFile();
5517 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5518 if ( aMeshDS == NULL ) return false;
5520 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5521 if(!aNode) return false;
5522 // try to find element
5523 const SMDS_MeshElement* elem = aMeshDS->FindElement(ide);
5524 if(!elem) return false;
5526 return elem->IsMediumNode(aNode);
5530 //=============================================================================
5532 * Return true if given node is medium node
5533 * in one of quadratic elements
5535 //=============================================================================
5537 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const SMESH::smIdType idn,
5538 SMESH::ElementType theElemType)
5541 _preMeshInfo->FullLoadFromFile();
5543 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5544 if ( aMeshDS == NULL ) return false;
5547 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5548 if(!aNode) return false;
5550 SMESH_MesherHelper aHelper( *(_impl) );
5552 SMDSAbs_ElementType aType;
5553 if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
5554 else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
5555 else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
5556 else aType = SMDSAbs_All;
5558 return aHelper.IsMedium(aNode,aType);
5562 //=============================================================================
5564 * Return number of edges for given element
5566 //=============================================================================
5568 CORBA::Long SMESH_Mesh_i::ElemNbEdges(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->NbEdges();
5581 //=============================================================================
5583 * Return number of faces for given element
5585 //=============================================================================
5587 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const SMESH::smIdType id)
5590 _preMeshInfo->FullLoadFromFile();
5592 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5593 if ( aMeshDS == NULL ) return -1;
5594 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5595 if(!elem) return -1;
5596 return elem->NbFaces();
5599 //================================================================================
5601 * \brief Return nodes of given face (counted from zero) for given element.
5603 //================================================================================
5605 SMESH::smIdType_array* SMESH_Mesh_i::GetElemFaceNodes(SMESH::smIdType elemId,
5606 CORBA::Short faceIndex)
5609 _preMeshInfo->FullLoadFromFile();
5611 SMESH::smIdType_array_var aResult = new SMESH::smIdType_array();
5612 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5614 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) )
5616 SMDS_VolumeTool vtool( elem, /*skipCentralNodes = */false );
5617 if ( faceIndex < vtool.NbFaces() )
5619 aResult->length( vtool.NbFaceNodes( faceIndex ));
5620 const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
5621 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5622 aResult[ i ] = nn[ i ]->GetID();
5626 return aResult._retn();
5629 //================================================================================
5631 * \brief Return three components of normal of given mesh face.
5633 //================================================================================
5635 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long elemId,
5636 CORBA::Boolean normalized)
5639 _preMeshInfo->FullLoadFromFile();
5641 SMESH::double_array_var aResult = new SMESH::double_array();
5643 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5646 if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
5648 aResult->length( 3 );
5649 aResult[ 0 ] = normal.X();
5650 aResult[ 1 ] = normal.Y();
5651 aResult[ 2 ] = normal.Z();
5654 return aResult._retn();
5657 //================================================================================
5659 * \brief Return an element based on all given nodes.
5661 //================================================================================
5663 SMESH::smIdType SMESH_Mesh_i::FindElementByNodes(const SMESH::smIdType_array& nodes)
5666 _preMeshInfo->FullLoadFromFile();
5668 CORBA::Long elemID(0);
5669 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5671 vector< const SMDS_MeshNode * > nn( nodes.length() );
5672 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5673 if ( !( nn[i] = mesh->FindNode( nodes[i] )))
5676 const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
5677 if ( !elem && ( _impl->NbEdges ( ORDER_QUADRATIC ) ||
5678 _impl->NbFaces ( ORDER_QUADRATIC ) ||
5679 _impl->NbVolumes( ORDER_QUADRATIC )))
5680 elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
5682 if ( elem ) elemID = CORBA::Long( elem->GetID() );
5687 //================================================================================
5689 * \brief Return elements including all given nodes.
5691 //================================================================================
5693 SMESH::smIdType_array* SMESH_Mesh_i::GetElementsByNodes(const SMESH::smIdType_array& nodes,
5694 SMESH::ElementType elemType)
5697 _preMeshInfo->FullLoadFromFile();
5699 SMESH::smIdType_array_var result = new SMESH::smIdType_array();
5701 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5703 vector< const SMDS_MeshNode * > nn( nodes.length() );
5704 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5705 nn[i] = mesh->FindNode( nodes[i] );
5707 std::vector<const SMDS_MeshElement *> elems;
5708 mesh->GetElementsByNodes( nn, elems, (SMDSAbs_ElementType) elemType );
5709 result->length( elems.size() );
5710 for ( size_t i = 0; i < elems.size(); ++i )
5711 result[i] = elems[i]->GetID();
5713 return result._retn();
5716 //=============================================================================
5718 * Return true if given element is polygon
5720 //=============================================================================
5722 CORBA::Boolean SMESH_Mesh_i::IsPoly(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->IsPoly();
5735 //=============================================================================
5737 * Return true if given element is quadratic
5739 //=============================================================================
5741 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const SMESH::smIdType id)
5744 _preMeshInfo->FullLoadFromFile();
5746 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5747 if ( aMeshDS == NULL ) return false;
5748 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5749 if(!elem) return false;
5750 return elem->IsQuadratic();
5753 //=============================================================================
5755 * Return diameter of ball discrete element or zero in case of an invalid \a id
5757 //=============================================================================
5759 CORBA::Double SMESH_Mesh_i::GetBallDiameter(SMESH::smIdType id)
5762 _preMeshInfo->FullLoadFromFile();
5764 if ( const SMDS_BallElement* ball =
5765 SMDS_Mesh::DownCast<SMDS_BallElement>( _impl->GetMeshDS()->FindElement( id )))
5766 return ball->GetDiameter();
5771 //=============================================================================
5773 * Return bary center for given element
5775 //=============================================================================
5777 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const SMESH::smIdType id)
5780 _preMeshInfo->FullLoadFromFile();
5782 SMESH::double_array_var aResult = new SMESH::double_array();
5783 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5784 if ( aMeshDS == NULL )
5785 return aResult._retn();
5787 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5789 return aResult._retn();
5791 if(elem->GetType()==SMDSAbs_Volume) {
5792 SMDS_VolumeTool aTool;
5793 if(aTool.Set(elem)) {
5795 if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
5800 SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
5802 double x=0., y=0., z=0.;
5803 for(; anIt->more(); ) {
5805 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
5819 return aResult._retn();
5822 //================================================================================
5824 * \brief Create a group of elements preventing computation of a sub-shape
5826 //================================================================================
5828 SMESH::ListOfGroups*
5829 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int theSubShapeID,
5830 const char* theGroupName )
5832 Unexpect aCatch(SALOME_SalomeException);
5834 if ( !theGroupName || strlen( theGroupName) == 0 )
5835 THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
5837 SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
5838 ::SMESH_MeshEditor::ElemFeatures elemType;
5840 // submesh by subshape id
5841 if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
5842 if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
5845 SMESH_ComputeErrorPtr error = sm->GetComputeError();
5846 if ( error && error->HasBadElems() )
5848 // sort bad elements by type
5849 vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
5850 const list<const SMDS_MeshElement*>& badElems =
5851 static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
5852 list<const SMDS_MeshElement*>::const_iterator elemIt = badElems.begin();
5853 list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
5854 for ( ; elemIt != elemEnd; ++elemIt )
5856 const SMDS_MeshElement* elem = *elemIt;
5857 if ( !elem ) continue;
5859 if ( elem->GetID() < 1 )
5861 // elem is a temporary element, make a real element
5862 vector< const SMDS_MeshNode* > nodes;
5863 SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
5864 while ( nIt->more() && elem )
5866 nodes.push_back( nIt->next() );
5867 if ( nodes.back()->GetID() < 1 )
5868 elem = 0; // a temporary element on temporary nodes
5872 ::SMESH_MeshEditor editor( _impl );
5873 elem = editor.AddElement( nodes, elemType.Init( elem ));
5877 elemsByType[ elem->GetType() ].push_back( elem );
5880 // how many groups to create?
5882 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5883 nbTypes += int( !elemsByType[ i ].empty() );
5884 groups->length( nbTypes );
5887 for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
5889 vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
5890 if ( elems.empty() ) continue;
5892 groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
5893 if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
5895 SMESH::SMESH_Mesh_var mesh = _this();
5896 SALOMEDS::SObject_wrap aSO =
5897 _gen_i->PublishGroup( mesh, groups[ iG ],
5898 GEOM::GEOM_Object::_nil(), theGroupName);
5900 SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
5901 if ( !grp_i ) continue;
5903 if ( SMESHDS_Group* grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
5904 for ( size_t iE = 0; iE < elems.size(); ++iE )
5905 grpDS->SMDSGroup().Add( elems[ iE ]);
5910 return groups._retn();
5913 //=============================================================================
5915 * Create and publish group servants if any groups were imported or created anyhow
5917 //=============================================================================
5919 void SMESH_Mesh_i::CreateGroupServants()
5921 SMESH::SMESH_Mesh_var aMesh = _this();
5924 ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
5925 while ( groupIt->more() )
5927 ::SMESH_Group* group = groupIt->next();
5928 int anId = group->GetID();
5930 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
5931 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5933 addedIDs.insert( anId );
5935 SMESH_GroupBase_i* aGroupImpl;
5937 if ( SMESHDS_GroupOnGeom* groupOnGeom =
5938 dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
5940 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
5941 shape = groupOnGeom->GetShape();
5944 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
5947 SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
5948 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
5949 aGroupImpl->Register();
5951 // register CORBA object for persistence
5952 int nextId = _gen_i->RegisterObject( groupVar );
5953 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
5954 else { (void)nextId; } // avoid "unused variable" warning in release mode
5956 // publishing the groups in the study
5957 GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
5958 _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName());
5961 if ( !addedIDs.empty() )
5964 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
5965 for ( int index = 0; i_grp != _mapGroups.end(); ++index, ++i_grp )
5967 set<int>::iterator it = addedIDs.find( i_grp->first );
5968 if ( it != addedIDs.end() )
5970 TPythonDump() << i_grp->second << " = " << aMesh << ".GetGroups()[ "<< index << " ]";
5971 addedIDs.erase( it );
5972 if ( addedIDs.empty() )
5979 //=============================================================================
5981 * \brief Return true if all sub-meshes are computed OK - to update an icon
5983 //=============================================================================
5985 bool SMESH_Mesh_i::IsComputedOK()
5987 return _impl->IsComputedOK();
5990 //=============================================================================
5992 * \brief Return groups cantained in _mapGroups by their IDs
5994 //=============================================================================
5996 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
5998 int nbGroups = groupIDs.size();
5999 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
6000 aList->length( nbGroups );
6002 list<int>::const_iterator ids = groupIDs.begin();
6003 for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
6005 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
6006 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
6007 aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
6009 aList->length( nbGroups );
6010 return aList._retn();
6013 //=============================================================================
6015 * \brief Return information about imported file
6017 //=============================================================================
6019 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
6021 SMESH::MedFileInfo_var res( _medFileInfo );
6022 if ( !res.operator->() ) {
6023 res = new SMESH::MedFileInfo;
6025 res->fileSize = res->major = res->minor = res->release = -1;
6030 //=======================================================================
6031 //function : FileInfoToString
6032 //purpose : Persistence of file info
6033 //=======================================================================
6035 std::string SMESH_Mesh_i::FileInfoToString()
6038 if ( &_medFileInfo.in() && _medFileInfo->fileName[0] )
6040 s = SMESH_Comment( _medFileInfo->fileSize )
6041 << " " << _medFileInfo->major
6042 << " " << _medFileInfo->minor
6043 << " " << _medFileInfo->release
6044 << " " << _medFileInfo->fileName;
6049 //=======================================================================
6050 //function : FileInfoFromString
6051 //purpose : Persistence of file info
6052 //=======================================================================
6054 void SMESH_Mesh_i::FileInfoFromString(const std::string& info)
6056 std::string size, major, minor, release, fileName;
6057 std::istringstream is(info);
6058 is >> size >> major >> minor >> release;
6059 fileName = info.data() + ( size.size() + 1 +
6062 release.size()+ 1 );
6064 _medFileInfo = new SMESH::MedFileInfo();
6065 _medFileInfo->fileName = fileName.c_str();
6066 _medFileInfo->fileSize = atoi( size.c_str() );
6067 _medFileInfo->major = atoi( major.c_str() );
6068 _medFileInfo->minor = atoi( minor.c_str() );
6069 _medFileInfo->release = atoi( release.c_str() );
6072 //=============================================================================
6074 * \brief Pass names of mesh groups from study to mesh DS
6076 //=============================================================================
6078 void SMESH_Mesh_i::checkGroupNames()
6080 int nbGrp = NbGroups();
6084 SMESH::ListOfGroups* grpList = 0;
6085 // avoid dump of "GetGroups"
6087 // store python dump into a local variable inside local scope
6088 SMESH::TPythonDump pDump; // do not delete this line of code
6089 grpList = GetGroups();
6092 for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
6093 SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
6096 SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aGrp );
6097 if ( aGrpSO->_is_nil() )
6099 // correct name of the mesh group if necessary
6100 const char* guiName = aGrpSO->GetName();
6101 if ( strcmp(guiName, aGrp->GetName()) )
6102 aGrp->SetName( guiName );
6106 //=============================================================================
6108 * \brief Set list of notebook variables used for Mesh operations separated by ":" symbol
6110 //=============================================================================
6111 void SMESH_Mesh_i::SetParameters(const char* theParameters)
6113 SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
6117 //=============================================================================
6119 * \brief Return list of notebook variables used for Mesh operations separated by ":" symbol
6121 //=============================================================================
6123 char* SMESH_Mesh_i::GetParameters()
6125 return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
6128 //=============================================================================
6130 * \brief Return list of notebook variables used for last Mesh operation
6132 //=============================================================================
6133 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
6135 SMESH::string_array_var aResult = new SMESH::string_array();
6136 SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
6138 CORBA::String_var aParameters = GetParameters();
6139 SALOMEDS::ListOfListOfStrings_var aSections = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->ParseVariables(aParameters);
6140 if ( aSections->length() > 0 ) {
6141 SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
6142 aResult->length( aVars.length() );
6143 for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
6144 aResult[i] = CORBA::string_dup( aVars[i] );
6147 return aResult._retn();
6150 //================================================================================
6152 * \brief Return types of elements it contains
6154 //================================================================================
6156 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
6159 return _preMeshInfo->GetTypes();
6161 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
6165 if (_impl->NbEdges()) types[nbTypes++] = SMESH::EDGE;
6166 if (_impl->NbFaces()) types[nbTypes++] = SMESH::FACE;
6167 if (_impl->NbVolumes()) types[nbTypes++] = SMESH::VOLUME;
6168 if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
6169 if (_impl->NbBalls()) types[nbTypes++] = SMESH::BALL;
6170 if (_impl->NbNodes() &&
6171 nbTypes == 0 ) types[nbTypes++] = SMESH::NODE;
6172 types->length( nbTypes );
6174 return types._retn();
6177 //================================================================================
6179 * \brief Return self
6181 //================================================================================
6183 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
6185 return SMESH::SMESH_Mesh::_duplicate( _this() );
6188 //================================================================================
6190 * \brief Return false if GetMeshInfo() return incorrect information that may
6191 * happen if mesh data is not yet fully loaded from the file of study.
6195 //================================================================================
6197 bool SMESH_Mesh_i::IsMeshInfoCorrect()
6199 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
6202 //=============================================================================
6204 * \brief Return number of mesh elements per each \a EntityType
6206 //=============================================================================
6208 SMESH::smIdType_array* SMESH_Mesh_i::GetMeshInfo()
6211 return _preMeshInfo->GetMeshInfo();
6213 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
6214 aRes->length(SMESH::Entity_Last);
6215 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6217 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6219 return aRes._retn();
6220 const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
6221 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6222 aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
6223 return aRes._retn();
6226 //=============================================================================
6228 * \brief Return number of mesh elements per each \a ElementType
6230 //=============================================================================
6232 SMESH::smIdType_array* SMESH_Mesh_i::GetNbElementsByType()
6234 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
6235 aRes->length(SMESH::NB_ELEMENT_TYPES);
6236 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6239 const SMDS_MeshInfo* meshInfo = 0;
6241 meshInfo = _preMeshInfo;
6242 else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
6243 meshInfo = & meshDS->GetMeshInfo();
6246 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6247 aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
6249 return aRes._retn();
6252 //=============================================================================
6254 * Collect statistic of mesh elements given by iterator
6256 //=============================================================================
6258 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
6259 SMESH::smIdType_array& theInfo)
6261 if (!theItr) return;
6262 while (theItr->more())
6263 theInfo[ theItr->next()->GetEntityType() ]++;
6265 //=============================================================================
6267 * Return mesh unstructed grid information.
6269 //=============================================================================
6271 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
6273 SALOMEDS::TMPFile_var SeqFile;
6274 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
6275 SMDS_UnstructuredGrid* aGrid = aMeshDS->GetGrid();
6277 vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
6278 aWriter->WriteToOutputStringOn();
6279 aWriter->SetInputData(aGrid);
6280 aWriter->SetFileTypeToBinary();
6282 char* str = aWriter->GetOutputString();
6283 int size = aWriter->GetOutputStringLength();
6285 //Allocate octet buffer of required size
6286 CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
6287 //Copy ostrstream content to the octet buffer
6288 memcpy(OctetBuf, str, size);
6289 //Create and return TMPFile
6290 SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
6294 return SeqFile._retn();
6297 //=============================================================================
6298 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
6299 * SMESH::ElementType type) */
6301 using namespace SMESH::Controls;
6302 //-----------------------------------------------------------------------------
6303 struct PredicateIterator : public SMDS_ElemIterator
6305 SMDS_ElemIteratorPtr _elemIter;
6306 PredicatePtr _predicate;
6307 const SMDS_MeshElement* _elem;
6308 SMDSAbs_ElementType _type;
6310 PredicateIterator( SMDS_ElemIteratorPtr iterator,
6311 PredicatePtr predicate,
6312 SMDSAbs_ElementType type):
6313 _elemIter(iterator), _predicate(predicate), _type(type)
6321 virtual const SMDS_MeshElement* next()
6323 const SMDS_MeshElement* res = _elem;
6325 while ( _elemIter->more() && !_elem )
6327 if ((_elem = _elemIter->next()) &&
6328 (( _type != SMDSAbs_All && _type != _elem->GetType() ) ||
6329 ( !_predicate->IsSatisfy( _elem->GetID() ))))
6336 //-----------------------------------------------------------------------------
6337 struct IDSourceIterator : public SMDS_ElemIterator
6339 const SMESH::smIdType* _idPtr;
6340 const SMESH::smIdType* _idEndPtr;
6341 SMESH::smIdType_array_var _idArray;
6342 const SMDS_Mesh* _mesh;
6343 const SMDSAbs_ElementType _type;
6344 const SMDS_MeshElement* _elem;
6346 IDSourceIterator( const SMDS_Mesh* mesh,
6347 const SMESH::smIdType* ids,
6348 const smIdType nbIds,
6349 SMDSAbs_ElementType type):
6350 _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
6352 if ( _idPtr && nbIds && _mesh )
6355 IDSourceIterator( const SMDS_Mesh* mesh,
6356 SMESH::smIdType_array* idArray,
6357 SMDSAbs_ElementType type):
6358 _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
6360 if ( idArray && _mesh )
6362 _idPtr = &_idArray[0];
6363 _idEndPtr = _idPtr + _idArray->length();
6371 virtual const SMDS_MeshElement* next()
6373 const SMDS_MeshElement* res = _elem;
6375 while ( _idPtr < _idEndPtr && !_elem )
6377 if ( _type == SMDSAbs_Node )
6379 _elem = _mesh->FindNode( *_idPtr++ );
6381 else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
6382 (_elem->GetType() != _type && _type != SMDSAbs_All ))
6390 //-----------------------------------------------------------------------------
6392 struct NodeOfElemIterator : public SMDS_ElemIterator
6394 TColStd_MapOfInteger _checkedNodeIDs;
6395 SMDS_ElemIteratorPtr _elemIter;
6396 SMDS_ElemIteratorPtr _nodeIter;
6397 const SMDS_MeshElement* _node;
6399 NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
6401 if ( _elemIter && _elemIter->more() )
6403 _nodeIter = _elemIter->next()->nodesIterator();
6411 virtual const SMDS_MeshElement* next()
6413 const SMDS_MeshElement* res = _node;
6415 while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
6417 if ( _nodeIter->more() )
6419 _node = _nodeIter->next();
6420 if ( !_checkedNodeIDs.Add( _node->GetID() ))
6425 _nodeIter = _elemIter->next()->nodesIterator();
6433 //=============================================================================
6435 * Return iterator on elements of given type in given object
6437 //=============================================================================
6439 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
6440 SMESH::ElementType theType)
6442 SMDS_ElemIteratorPtr elemIt;
6443 bool typeOK = ( theType == SMESH::ALL );
6444 SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
6446 SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
6447 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
6448 if ( !mesh_i ) return elemIt;
6449 SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
6451 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
6453 elemIt = meshDS->elementsIterator( elemType );
6456 else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
6458 SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
6461 elemIt = sm->GetElements();
6462 if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6464 typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
6465 elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
6469 else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
6471 SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
6472 if ( groupDS && ( elemType == groupDS->GetType() ||
6473 elemType == SMDSAbs_Node ||
6474 elemType == SMDSAbs_All ))
6476 elemIt = groupDS->GetElements();
6477 typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
6480 else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
6482 if ( filter_i->GetElementType() == theType ||
6483 filter_i->GetElementType() == SMESH::ALL ||
6484 elemType == SMDSAbs_Node ||
6485 elemType == SMDSAbs_All)
6487 SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
6488 if ( pred_i && pred_i->GetPredicate() )
6490 SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
6491 SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
6492 SMDSAbs_ElementType iterType = elemType == SMDSAbs_Node ? filterType : elemType;
6493 elemIt = SMDS_ElemIteratorPtr
6494 ( new PredicateIterator( allElemIt, pred_i->GetPredicate(), iterType ));
6495 typeOK = ( elemType == SMDSAbs_Node ? filterType == SMDSAbs_Node : elemIt->more() );
6501 SMESH::array_of_ElementType_var types = theObject->GetTypes();
6502 const bool isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
6503 if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6505 SMDSAbs_ElementType iterType = isNodes ? SMDSAbs_Node : elemType;
6506 if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
6508 SMESH::smIdType nbIds;
6509 if ( SMESH::smIdType* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
6510 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, iterType ));
6514 SMESH::smIdType_array_var ids = theObject->GetIDs();
6515 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), iterType ));
6517 typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
6520 if ( elemIt && elemIt->more() && !typeOK )
6522 if ( elemType == SMDSAbs_Node )
6524 elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
6528 elemIt = SMDS_ElemIteratorPtr();
6534 //=============================================================================
6535 namespace // Finding concurrent hypotheses
6536 //=============================================================================
6540 * \brief mapping of mesh dimension into shape type
6542 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
6544 TopAbs_ShapeEnum aType = TopAbs_SOLID;
6546 case 0: aType = TopAbs_VERTEX; break;
6547 case 1: aType = TopAbs_EDGE; break;
6548 case 2: aType = TopAbs_FACE; break;
6550 default:aType = TopAbs_SOLID; break;
6555 //-----------------------------------------------------------------------------
6557 * \brief Internal structure used to find concurrent submeshes
6559 * It represents a pair < submesh, concurrent dimension >, where
6560 * 'concurrent dimension' is dimension of shape where the submesh can concurrent
6561 * with another submesh. In other words, it is dimension of a hypothesis assigned
6568 int _dim; //!< a dimension the algo can build (concurrent dimension)
6569 int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
6570 TopTools_MapOfShape _shapeMap; //!< [sub-]shapes of dimension == _dim
6571 const SMESH_subMesh* _subMesh;
6572 list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
6574 //-----------------------------------------------------------------------------
6575 // Return the algorithm
6576 const SMESH_Algo* GetAlgo() const
6577 { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
6579 //-----------------------------------------------------------------------------
6581 SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
6583 const TopoDS_Shape& theShape)
6585 _subMesh = theSubMesh;
6586 SetShape( theDim, theShape );
6589 //-----------------------------------------------------------------------------
6591 void SetShape(const int theDim,
6592 const TopoDS_Shape& theShape)
6595 _ownDim = SMESH_Gen::GetShapeDim(theShape);
6596 if (_dim >= _ownDim)
6597 _shapeMap.Add( theShape );
6599 TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
6600 for( ; anExp.More(); anExp.Next() )
6601 _shapeMap.Add( anExp.Current() );
6605 //-----------------------------------------------------------------------------
6606 //! Check sharing of sub-shapes
6607 static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
6608 const TopTools_MapOfShape& theToFind,
6609 const TopAbs_ShapeEnum theType)
6611 bool isShared = false;
6612 TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
6613 for (; !isShared && anItr.More(); anItr.Next() )
6615 const TopoDS_Shape& aSubSh = anItr.Key();
6616 // check for case when concurrent dimensions are same
6617 isShared = theToFind.Contains( aSubSh );
6618 // check for sub-shape with concurrent dimension
6619 TopExp_Explorer anExp( aSubSh, theType );
6620 for ( ; !isShared && anExp.More(); anExp.Next() )
6621 isShared = theToFind.Contains( anExp.Current() );
6626 //-----------------------------------------------------------------------------
6627 //! check algorithms
6628 static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
6629 const SMESHDS_Hypothesis* theA2)
6631 if ( !theA1 || !theA2 ||
6632 theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
6633 theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
6634 return false; // one of the hypothesis is not algorithm
6635 // check algorithm names (should be equal)
6636 return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
6640 //-----------------------------------------------------------------------------
6641 //! Check if sub-shape hypotheses are concurrent
6642 bool IsConcurrent(const SMESH_DimHyp* theOther) const
6644 if ( _subMesh == theOther->_subMesh )
6645 return false; // same sub-shape - should not be
6647 // if ( <own dim of either of submeshes> == <concurrent dim> &&
6648 // any of the two submeshes is not on COMPOUND shape )
6649 // -> no concurrency
6650 bool meIsCompound = (_subMesh->GetSubMeshDS() &&
6651 _subMesh->GetSubMeshDS()->IsComplexSubmesh());
6652 bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
6653 theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
6654 if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
6657 bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
6658 if ( !checkSubShape )
6661 // check algorithms to be same
6662 const SMESH_Algo* a1 = this->GetAlgo();
6663 const SMESH_Algo* a2 = theOther->GetAlgo();
6664 bool isSame = checkAlgo( a1, a2 );
6668 // commented off for IPAL54678
6669 // if ( !a1 || !a2 )
6670 // return false; // pb?
6671 // return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency !
6674 // check hypothesises for concurrence (skip first as algorithm)
6676 // pointers should be same, because it is referened from mesh hypothesis partition
6677 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
6678 list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
6679 for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
6680 if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
6682 // the submeshes are concurrent if their algorithms has different parameters
6683 return nbSame != theOther->_hypotheses.size() - 1;
6686 // Return true if algorithm of this SMESH_DimHyp is used if no
6687 // sub-mesh order is imposed by the user
6688 bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
6690 // NeedDiscreteBoundary() algo has a higher priority
6691 if ( this ->GetAlgo()->NeedDiscreteBoundary() !=
6692 theOther->GetAlgo()->NeedDiscreteBoundary() )
6693 return !this->GetAlgo()->NeedDiscreteBoundary();
6695 return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
6698 }; // end of SMESH_DimHyp
6699 //-----------------------------------------------------------------------------
6701 typedef list<const SMESH_DimHyp*> TDimHypList;
6703 //-----------------------------------------------------------------------------
6705 void addDimHypInstance(const int theDim,
6706 const TopoDS_Shape& theShape,
6707 const SMESH_Algo* theAlgo,
6708 const SMESH_subMesh* theSubMesh,
6709 const list <const SMESHDS_Hypothesis*>& theHypList,
6710 TDimHypList* theDimHypListArr )
6712 if ( !theAlgo->NeedDiscreteBoundary() &&
6713 theAlgo->NeedLowerHyps( theDim )) // IPAL54678
6715 TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
6716 if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh )
6718 SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
6719 dimHyp->_hypotheses.push_front(theAlgo);
6720 listOfdimHyp.push_back( dimHyp );
6723 SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
6724 dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
6725 theHypList.begin(), theHypList.end() );
6728 //-----------------------------------------------------------------------------
6729 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
6730 TDimHypList& theListOfConcurr)
6732 if ( theListOfConcurr.empty() )
6734 theListOfConcurr.push_back( theDimHyp );
6738 TDimHypList::iterator hypIt = theListOfConcurr.begin();
6739 while ( hypIt != theListOfConcurr.end() &&
6740 !theDimHyp->IsHigherPriorityThan( *hypIt ))
6742 theListOfConcurr.insert( hypIt, theDimHyp );
6746 //-----------------------------------------------------------------------------
6747 void findConcurrents(const SMESH_DimHyp* theDimHyp,
6748 const TDimHypList& theListOfDimHyp,
6749 TDimHypList& theListOfConcurrHyp,
6750 set<int>& theSetOfConcurrId )
6752 TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
6753 for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
6755 const SMESH_DimHyp* curDimHyp = *rIt;
6756 if ( curDimHyp == theDimHyp )
6757 break; // meet own dimHyp pointer in same dimension
6759 if ( theDimHyp->IsConcurrent( curDimHyp ) &&
6760 theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
6762 addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
6767 //-----------------------------------------------------------------------------
6768 bool unionLists(TListOfInt& theListOfId,
6769 TListOfListOfInt& theListOfListOfId,
6772 bool changed = false;
6773 if ( theListOfId.empty() )
6775 TListOfListOfInt::iterator it = theListOfListOfId.begin();
6776 for ( int i = 0; it != theListOfListOfId.end(); it++, i++ )
6779 continue; //skip already treated lists
6780 // check if other list has any same submesh object
6781 TListOfInt& otherListOfId = *it;
6782 if ( find_first_of( theListOfId.begin(), theListOfId.end(),
6783 otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
6786 // union two lists (from source into target)
6787 TListOfInt::iterator it2 = otherListOfId.begin();
6788 for ( ; it2 != otherListOfId.end(); it2++ ) {
6789 if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
6791 theListOfId.push_back(*it2);
6795 // clear source list
6796 otherListOfId.clear();
6800 //-----------------------------------------------------------------------------
6802 //! free memory allocated for dimension-hypothesis objects
6803 void removeDimHyps( TDimHypList* theArrOfList )
6805 for (int i = 0; i < 4; i++ ) {
6806 TDimHypList& listOfdimHyp = theArrOfList[i];
6807 TDimHypList::const_iterator it = listOfdimHyp.begin();
6808 for ( ; it != listOfdimHyp.end(); it++ )
6813 //-----------------------------------------------------------------------------
6815 * \brief find common submeshes with given submesh
6816 * \param theSubMeshList list of already collected submesh to check
6817 * \param theSubMesh given submesh to intersect with other
6818 * \param theCommonSubMeshes collected common submeshes
6820 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
6821 const SMESH_subMesh* theSubMesh,
6822 set<const SMESH_subMesh*>& theCommon )
6826 list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
6827 for ( ; it != theSubMeshList.end(); it++ )
6828 theSubMesh->FindIntersection( *it, theCommon );
6829 theSubMeshList.push_back( theSubMesh );
6830 //theCommon.insert( theSubMesh );
6833 //-----------------------------------------------------------------------------
6834 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
6836 TListOfListOfInt::const_iterator listsIt = smLists.begin();
6837 for ( ; listsIt != smLists.end(); ++listsIt )
6839 const TListOfInt& smIDs = *listsIt;
6840 if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
6848 //=============================================================================
6850 * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
6852 //=============================================================================
6854 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
6856 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6857 if ( isSubMeshInList( submeshID, anOrder ))
6860 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6861 return isSubMeshInList( submeshID, allConurrent );
6864 //=============================================================================
6866 * \brief Return sub-mesh objects list in meshing order
6868 //=============================================================================
6870 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
6872 SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
6874 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6876 return aResult._retn();
6878 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6879 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6880 anOrder.splice( anOrder.end(), allConurrent );
6885 TListOfListOfInt::iterator listIt = anOrder.begin();
6886 for ( int listIndx = 1; listIt != anOrder.end(); listIt++, listIndx++ )
6887 if ( unionLists( *listIt, anOrder, listIndx ))
6892 // convert submesh ids into interface instances
6893 // and dump command into python
6894 convertMeshOrder( anOrder, aResult, false );
6896 return aResult._retn();
6899 //=============================================================================
6901 * \brief Finds concurrent sub-meshes
6903 //=============================================================================
6905 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
6907 TListOfListOfInt anOrder;
6908 ::SMESH_Mesh& mesh = GetImpl();
6910 // collect submeshes and detect concurrent algorithms and hypothesises
6911 TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
6913 map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
6914 for ( ; i_sm != _mapSubMesh.end(); i_sm++ )
6916 ::SMESH_subMesh* sm = (*i_sm).second;
6918 const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
6920 // list of assigned hypothesises
6921 const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
6922 // Find out dimensions where the submesh can be concurrent.
6923 // We define the dimensions by algo of each of hypotheses in hypList
6924 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
6925 for( ; hypIt != hypList.end(); hypIt++ )
6927 SMESH_Algo* anAlgo = 0;
6928 const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
6929 if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
6930 // hyp it-self is algo
6931 anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
6933 // try to find algorithm with help of sub-shapes
6934 TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
6935 for ( ; !anAlgo && anExp.More(); anExp.Next() )
6936 anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
6939 continue; // no algorithm assigned to a current submesh
6941 int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
6942 // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary()
6943 // and !anAlgo->NeedLowerHyps( dim ))
6945 // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
6946 for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
6947 addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
6949 } // end iterations on submesh
6951 // iterate on created dimension-hypotheses and check for concurrents
6952 for ( int i = 0; i < 4; i++ )
6954 const TDimHypList& listOfDimHyp = dimHypListArr[i];
6955 // check for concurrents in own and other dimensions (step-by-step)
6956 TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
6957 for ( ; dhIt != listOfDimHyp.end(); dhIt++ )
6959 const SMESH_DimHyp* dimHyp = *dhIt;
6960 TDimHypList listOfConcurr;
6961 set<int> setOfConcurrIds;
6962 // looking for concurrents and collect into own list
6963 for ( int j = i; j < 4; j++ )
6964 findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
6965 // check if any concurrents found
6966 if ( listOfConcurr.size() > 0 )
6968 // add own submesh to list of concurrent
6969 addInOrderOfPriority( dimHyp, listOfConcurr );
6970 list<int> listOfConcurrIds;
6971 TDimHypList::iterator hypIt = listOfConcurr.begin();
6972 for ( ; hypIt != listOfConcurr.end(); ++hypIt )
6973 listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
6974 anOrder.push_back( listOfConcurrIds );
6979 removeDimHyps(dimHypListArr);
6981 // now, minimize the number of concurrent groups
6982 // Here we assume that lists of submeshes can have same submesh
6983 // in case of multi-dimension algorithms, as result
6984 // list with common submesh has to be united into one list
6986 TListOfListOfInt::iterator listIt = anOrder.begin();
6987 for(; listIt != anOrder.end(); listIt++, listIndx++ )
6988 unionLists( *listIt, anOrder, listIndx + 1 );
6993 //=============================================================================
6995 * \brief Set submesh object order
6996 * \param theSubMeshArray submesh array order
6998 //=============================================================================
7000 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
7003 _preMeshInfo->ForgetOrLoad();
7006 ::SMESH_Mesh& mesh = GetImpl();
7008 TPythonDump aPythonDump; // prevent dump of called methods
7009 aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
7011 TListOfListOfInt subMeshOrder;
7012 for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
7014 const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
7015 TListOfInt subMeshIds;
7017 aPythonDump << ", ";
7018 aPythonDump << "[ ";
7019 // Collect subMeshes which should be clear
7020 // do it list-by-list, because modification of submesh order
7021 // take effect between concurrent submeshes only
7022 set<const SMESH_subMesh*> subMeshToClear;
7023 list<const SMESH_subMesh*> subMeshList;
7024 for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
7026 const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
7028 aPythonDump << ", ";
7029 aPythonDump << subMesh;
7030 subMeshIds.push_back( subMesh->GetId() );
7031 // detect common parts of submeshes
7032 if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
7033 findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
7035 aPythonDump << " ]";
7036 subMeshOrder.push_back( subMeshIds );
7038 // clear collected sub-meshes
7039 set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
7040 for ( ; clrIt != subMeshToClear.end(); clrIt++ )
7041 if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
7043 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
7044 if ( SMESH_Algo* algo = sm->GetAlgo() ) // #16748
7045 sm->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, algo ); // to clear a cached algo
7048 aPythonDump << " ])";
7050 mesh.SetMeshOrder( subMeshOrder );
7053 SMESH::SMESH_Mesh_var me = _this();
7054 _gen_i->UpdateIcons( me );
7059 //=============================================================================
7061 * \brief Convert submesh ids into submesh interfaces
7063 //=============================================================================
7065 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt& theIdsOrder,
7066 SMESH::submesh_array_array& theResOrder,
7067 const bool theIsDump)
7069 int nbSet = theIdsOrder.size();
7070 TPythonDump aPythonDump; // prevent dump of called methods
7072 aPythonDump << "[ ";
7073 theResOrder.length(nbSet);
7074 TListOfListOfInt::const_iterator it = theIdsOrder.begin();
7076 for( ; it != theIdsOrder.end(); it++ )
7078 // translate submesh identificators into submesh objects
7079 // takeing into account real number of concurrent lists
7080 const TListOfInt& aSubOrder = (*it);
7081 if (!aSubOrder.size())
7084 aPythonDump << "[ ";
7085 // convert shape indices into interfaces
7086 SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
7087 aResSubSet->length(aSubOrder.size());
7088 TListOfInt::const_iterator subIt = aSubOrder.begin();
7090 for( j = 0; subIt != aSubOrder.end(); subIt++ )
7092 if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
7094 SMESH::SMESH_subMesh_var subMesh =
7095 SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
7098 aPythonDump << ", ";
7099 aPythonDump << subMesh;
7101 aResSubSet[ j++ ] = subMesh;
7104 aPythonDump << " ]";
7106 theResOrder[ listIndx++ ] = aResSubSet;
7108 // correct number of lists
7109 theResOrder.length( listIndx );
7112 // finilise python dump
7113 aPythonDump << " ]";
7114 aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
7118 namespace // utils used by SMESH_MeshPartDS
7121 * \brief Class used to access to protected data of SMDS_MeshInfo
7123 struct TMeshInfo : public SMDS_MeshInfo
7125 void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
7128 * \brief Element holing its ID only
7130 struct TElemID : public SMDS_LinearEdge
7132 TElemID(int ID) : SMDS_LinearEdge(0,0) { setID( ID ); }
7136 //================================================================================
7138 // Implementation of SMESH_MeshPartDS
7140 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
7141 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
7143 SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
7144 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
7147 _meshDS = mesh_i->GetImpl().GetMeshDS();
7149 SetPersistentId( _meshDS->GetPersistentId() );
7151 if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
7153 // <meshPart> is the whole mesh
7154 myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
7156 set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
7157 myGroupSet = _meshDS->GetGroups();
7162 SMESH::smIdType_array_var anIDs = meshPart->GetIDs();
7163 SMESH::array_of_ElementType_var types = meshPart->GetTypes();
7164 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
7166 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7167 if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
7168 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7173 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
7174 if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
7175 if ( _elements[ e->GetType() ].insert( e ).second )
7178 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7179 while ( nIt->more() )
7181 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7182 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7189 ShapeToMesh( _meshDS->ShapeToMesh() );
7191 _meshDS = 0; // to enforce iteration on _elements and _nodes
7194 // -------------------------------------------------------------------------------------
7195 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
7196 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
7199 list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
7200 for ( ; partIt != meshPart.end(); ++partIt )
7201 if ( const SMDS_MeshElement * e = *partIt )
7202 if ( _elements[ e->GetType() ].insert( e ).second )
7205 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7206 while ( nIt->more() )
7208 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7209 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7215 // -------------------------------------------------------------------------------------
7216 const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const
7218 if ( _meshDS ) return _meshDS->FindElement( IDelem );
7220 TElemID elem( IDelem );
7221 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7222 if ( !_elements[ iType ].empty() )
7224 TIDSortedElemSet::const_iterator it = _elements[ iType ].find( &elem );
7225 if ( it != _elements[ iType ].end() )
7230 // -------------------------------------------------------------------------------------
7231 bool SMESH_MeshPartDS::HasNumerationHoles()
7233 if ( _meshDS ) return _meshDS->HasNumerationHoles();
7235 return ( MinNodeID() != 1 ||
7236 MaxNodeID() != NbNodes() ||
7237 MinElementID() != 1 ||
7238 MaxElementID() != NbElements() );
7240 // -------------------------------------------------------------------------------------
7241 smIdType SMESH_MeshPartDS::MaxNodeID() const
7243 if ( _meshDS ) return _meshDS->MaxNodeID();
7244 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].rbegin())->GetID();
7246 // -------------------------------------------------------------------------------------
7247 smIdType SMESH_MeshPartDS::MinNodeID() const
7249 if ( _meshDS ) return _meshDS->MinNodeID();
7250 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].begin())->GetID();
7252 // -------------------------------------------------------------------------------------
7253 smIdType SMESH_MeshPartDS::MaxElementID() const
7255 if ( _meshDS ) return _meshDS->MaxElementID();
7257 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7258 if ( !_elements[ iType ].empty() )
7259 maxID = std::max( maxID, (*_elements[ iType ].rbegin())->GetID() );
7262 // -------------------------------------------------------------------------------------
7263 smIdType SMESH_MeshPartDS::MinElementID() const
7265 if ( _meshDS ) return _meshDS->MinElementID();
7267 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7268 if ( !_elements[ iType ].empty() )
7269 minID = std::min( minID, (*_elements[ iType ].begin())->GetID() );
7272 // -------------------------------------------------------------------------------------
7273 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
7275 if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
7277 typedef SMDS_SetIterator
7278 <const SMDS_MeshElement*,
7279 TIDSortedElemSet::const_iterator,
7280 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7281 SMDS_MeshElement::GeomFilter
7284 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( geomType );
7286 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7287 _elements[type].end(),
7288 SMDS_MeshElement::GeomFilter( geomType )));
7290 // -------------------------------------------------------------------------------------
7291 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
7293 if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
7295 typedef SMDS_SetIterator
7296 <const SMDS_MeshElement*,
7297 TIDSortedElemSet::const_iterator,
7298 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7299 SMDS_MeshElement::EntityFilter
7302 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( entity );
7304 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7305 _elements[type].end(),
7306 SMDS_MeshElement::EntityFilter( entity )));
7308 // -------------------------------------------------------------------------------------
7309 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
7311 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
7312 if ( type == SMDSAbs_All && !_meshDS )
7314 typedef vector< SMDS_ElemIteratorPtr > TIterVec;
7316 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
7317 if ( !_elements[i].empty() && i != SMDSAbs_Node )
7319 ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
7321 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
7322 return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
7324 return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
7325 ( new TIter( _elements[type].begin(), _elements[type].end() ));
7327 // -------------------------------------------------------------------------------------
7328 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType) \
7329 iterType SMESH_MeshPartDS::methName() const \
7331 typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
7332 return _meshDS ? _meshDS->methName() : iterType \
7333 ( new TIter( _elements[elemType].begin(), _elements[elemType].end() )); \
7335 // -------------------------------------------------------------------------------------
7336 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
7337 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
7338 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
7339 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
7340 #undef _GET_ITER_DEFINE
7342 // END Implementation of SMESH_MeshPartDS
7344 //================================================================================