1 // Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_Mesh_i.cxx
23 // Author : Paul RASCLE, EDF
26 #include "SMESH_Mesh_i.hxx"
28 #include "DriverMED_R_SMESHDS_Mesh.h"
29 #include "DriverMED_W_Field.h"
30 #include "DriverMED_W_SMESHDS_Mesh.h"
31 #include "MED_Factory.hxx"
32 #include "SMDS_LinearEdge.hxx"
33 #include "SMDS_EdgePosition.hxx"
34 #include "SMDS_ElemIterator.hxx"
35 #include "SMDS_FacePosition.hxx"
36 #include "SMDS_IteratorOnIterators.hxx"
37 #include "SMDS_MeshGroup.hxx"
38 #include "SMDS_SetIterator.hxx"
39 #include "SMDS_StdIterator.hxx"
40 #include "SMDS_VolumeTool.hxx"
41 #include "SMESHDS_Command.hxx"
42 #include "SMESHDS_CommandType.hxx"
43 #include "SMESHDS_Group.hxx"
44 #include "SMESHDS_GroupOnGeom.hxx"
45 #include "SMESH_Controls.hxx"
46 #include "SMESH_File.hxx"
47 #include "SMESH_Filter_i.hxx"
48 #include "SMESH_Gen_i.hxx"
49 #include "SMESH_Group.hxx"
50 #include "SMESH_Group_i.hxx"
51 #include "SMESH_Mesh.hxx"
52 #include "SMESH_MeshAlgos.hxx"
53 #include "SMESH_MeshEditor.hxx"
54 #include "SMESH_MeshEditor_i.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PreMeshInfo.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <SALOMEDS_Attributes_wrap.hxx>
62 #include <SALOMEDS_wrap.hxx>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <utilities.h>
66 #include <GEOMImpl_Types.hxx>
67 #include <GEOM_wrap.hxx>
70 #include <BRep_Builder.hxx>
71 #include <Standard_ErrorHandler.hxx>
72 #include <TColStd_MapOfInteger.hxx>
74 #include <TopExp_Explorer.hxx>
75 #include <TopTools_DataMapOfShapeShape.hxx>
76 #include <TopTools_MapIteratorOfMapOfShape.hxx>
77 #include <TopTools_MapOfShape.hxx>
78 #include <TopoDS_Compound.hxx>
85 #include <vtkUnstructuredGridWriter.h>
87 // to pass CORBA exception through SMESH_TRY
88 #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
90 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
93 static int MYDEBUG = 0;
95 static int MYDEBUG = 0;
99 using SMESH::TPythonDump;
102 int SMESH_Mesh_i::_idGenerator = 0;
104 //=============================================================================
108 //=============================================================================
110 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
112 : SALOME::GenericObj_i( thePOA )
116 _id = _idGenerator++;
119 _previewEditor = NULL;
124 //=============================================================================
128 //=============================================================================
130 SMESH_Mesh_i::~SMESH_Mesh_i()
133 map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
134 for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
135 if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
137 aGroup->UnRegister();
138 SMESH::SMESH_GroupBase_var( itGr->second );
143 map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
144 for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
145 if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
147 aSubMesh->UnRegister();
148 SMESH::SMESH_subMesh_var( itSM->second );
150 _mapSubMeshIor.clear();
152 // destroy hypotheses. _mapHypo contains all hyps ever been assigned
153 map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
154 for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
155 if ( SMESH_Hypothesis_i* hyp_i = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
156 if ( SMESH_Hypothesis * smHyp = _impl->GetHypothesis( itH->first ))
157 if ( _impl->GetMeshDS()->IsUsedHypothesis( smHyp ))
160 SMESH::SMESH_Hypothesis_var( itH->second ); // decref CORBA object
164 // clear cached shapes if no more meshes remain; (the cache is blame,
165 // together with publishing, of spent time increasing in issue 22874)
166 if ( _impl->NbMeshes() == 1 )
167 _gen_i->GetShapeReader()->ClearClientBuffer();
169 delete _editor; _editor = NULL;
170 delete _previewEditor; _previewEditor = NULL;
171 delete _impl; _impl = NULL;
172 delete _preMeshInfo; _preMeshInfo = NULL;
175 //=============================================================================
179 * Associate <this> mesh with <theShape> and put a reference
180 * to <theShape> into the current study;
181 * the previous shape is substituted by the new one.
183 //=============================================================================
185 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
187 Unexpect aCatch(SALOME_SalomeException);
189 _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
191 catch(SALOME_Exception & S_ex) {
192 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
194 // to track changes of GEOM groups
195 SMESH::SMESH_Mesh_var mesh = _this();
196 addGeomGroupData( theShapeObject, mesh );
197 if ( !CORBA::is_nil( theShapeObject ))
198 _mainShapeTick = theShapeObject->GetTick();
201 //================================================================================
203 * \brief Return true if mesh has a shape to build a shape on
205 //================================================================================
207 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
209 Unexpect aCatch(SALOME_SalomeException);
212 res = _impl->HasShapeToMesh();
214 catch(SALOME_Exception & S_ex) {
215 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
220 //================================================================================
222 * \brief Return the shape to mesh
224 //================================================================================
226 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
228 Unexpect aCatch(SALOME_SalomeException);
229 GEOM::GEOM_Object_var aShapeObj;
231 TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
234 aShapeObj = _gen_i->ShapeToGeomObject( S );
235 if ( aShapeObj->_is_nil() )
237 // S was removed from GEOM_Client by newGroupShape() called by other mesh;
238 // find GEOM_Object by entry (IPAL52735)
239 list<TGeomGroupData>::iterator data = _geomGroupData.begin();
240 for ( ; data != _geomGroupData.end(); ++data )
241 if ( data->_smeshObject->_is_equivalent( _this() ))
243 SALOMEDS::SObject_wrap so = _gen_i->getStudyServant()->FindObjectID( data->_groupEntry.c_str() );
244 CORBA::Object_var obj = _gen_i->SObjectToObject( so );
245 aShapeObj = GEOM::GEOM_Object::_narrow( obj );
251 catch(SALOME_Exception & S_ex) {
252 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
254 return aShapeObj._retn();
257 //================================================================================
259 * \brief Return false if the mesh is not yet fully loaded from the study file
261 //================================================================================
263 CORBA::Boolean SMESH_Mesh_i::IsLoaded()
265 Unexpect aCatch(SALOME_SalomeException);
266 return !_preMeshInfo;
269 //================================================================================
271 * \brief Load full mesh data from the study file
273 //================================================================================
275 void SMESH_Mesh_i::Load()
277 Unexpect aCatch(SALOME_SalomeException);
279 _preMeshInfo->FullLoadFromFile();
282 //================================================================================
284 * \brief Remove all nodes and elements
286 //================================================================================
288 void SMESH_Mesh_i::Clear()
290 Unexpect aCatch(SALOME_SalomeException);
292 _preMeshInfo->ForgetOrLoad(); // load in case if !HasShapeToMesh()
296 //CheckGeomGroupModif(); // issue 20145
298 catch(SALOME_Exception & S_ex) {
299 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
302 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".Clear()";
304 SMESH::SMESH_Mesh_var mesh = _this();
305 _gen_i->UpdateIcons( mesh );
308 //================================================================================
310 * \brief Remove all nodes and elements for indicated shape
312 //================================================================================
314 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
316 Unexpect aCatch(SALOME_SalomeException);
318 _preMeshInfo->FullLoadFromFile();
321 _impl->ClearSubMesh( ShapeID );
323 catch(SALOME_Exception & S_ex) {
324 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
326 _impl->GetMeshDS()->Modified();
328 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ClearSubMesh( " << ShapeID << " )";
331 //=============================================================================
333 * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
335 //=============================================================================
337 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
339 SMESH::DriverMED_ReadStatus res;
342 case DriverMED_R_SMESHDS_Mesh::DRS_OK:
343 res = SMESH::DRS_OK; break;
344 case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
345 res = SMESH::DRS_EMPTY; break;
346 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
347 res = SMESH::DRS_WARN_RENUMBER; break;
348 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
349 res = SMESH::DRS_WARN_SKIP_ELEM; break;
350 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_DESCENDING:
351 res = SMESH::DRS_WARN_DESCENDING; break;
352 case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
354 res = SMESH::DRS_FAIL; break;
359 //=============================================================================
361 * Convert ::SMESH_ComputeError to SMESH::ComputeError
363 //=============================================================================
365 static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr )
367 SMESH::ComputeError_var errVar = new SMESH::ComputeError();
368 errVar->subShapeID = -1;
369 errVar->hasBadMesh = false;
371 if ( !errorPtr || errorPtr->IsOK() )
373 errVar->code = SMESH::COMPERR_OK;
377 errVar->code = ConvertDriverMEDReadStatus( errorPtr->myName );
378 errVar->comment = errorPtr->myComment.c_str();
380 return errVar._retn();
383 //=============================================================================
387 * Import mesh data from MED file
389 //=============================================================================
391 SMESH::DriverMED_ReadStatus
392 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
394 Unexpect aCatch(SALOME_SalomeException);
397 status = _impl->MEDToMesh( theFileName, theMeshName );
399 catch( SALOME_Exception& S_ex ) {
400 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
403 THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
406 CreateGroupServants();
408 int major, minor, release;
409 major = minor = release = 0;
410 MED::GetMEDVersion(theFileName, major, minor, release);
411 _medFileInfo = new SMESH::MedFileInfo();
412 _medFileInfo->fileName = theFileName;
413 _medFileInfo->fileSize = 0;
414 _medFileInfo->major = major;
415 _medFileInfo->minor = minor;
416 _medFileInfo->release = release;
417 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
419 return ConvertDriverMEDReadStatus(status);
422 //================================================================================
424 * \brief Import mesh data from the CGNS file
426 //================================================================================
428 SMESH::DriverMED_ReadStatus SMESH_Mesh_i::ImportCGNSFile( const char* theFileName,
429 const int theMeshIndex,
430 std::string& theMeshName )
432 Unexpect aCatch(SALOME_SalomeException);
435 status = _impl->CGNSToMesh( theFileName, theMeshIndex, theMeshName );
437 catch( SALOME_Exception& S_ex ) {
438 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
441 THROW_SALOME_CORBA_EXCEPTION("ImportCGNSFile(): unknown exception", SALOME::BAD_PARAM);
444 CreateGroupServants();
446 _medFileInfo = new SMESH::MedFileInfo();
447 _medFileInfo->fileName = theFileName;
448 _medFileInfo->major = 0;
449 _medFileInfo->minor = 0;
450 _medFileInfo->release = 0;
451 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
453 return ConvertDriverMEDReadStatus(status);
456 //================================================================================
458 * \brief Return string representation of a MED file version comprising nbDigits
460 //================================================================================
462 char* SMESH_Mesh_i::GetVersionString(CORBA::Long minor, CORBA::Short nbDigits)
464 string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(minor,
466 return CORBA::string_dup( ver.c_str() );
469 //================================================================================
471 * Return the list of med versions compatibles for write/append,
472 * encoded in 10*major+minor (for instance, code for med 3.2.1 is 32)
474 //================================================================================
476 SMESH::long_array* SMESH_Mesh_i::GetMEDVersionsCompatibleForAppend()
478 SMESH::long_array_var aResult = new SMESH::long_array();
479 std::vector<int> mvok = MED::GetMEDVersionsAppendCompatible();
480 long nbver = mvok.size();
481 aResult->length( nbver );
482 for ( int i = 0; i < nbver; i++ )
483 aResult[i] = mvok[i];
484 return aResult._retn();
487 //=============================================================================
491 * Import mesh data from MED file
493 //=============================================================================
495 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
499 // Read mesh with name = <theMeshName> into SMESH_Mesh
500 _impl->UNVToMesh( theFileName );
502 CreateGroupServants();
504 _medFileInfo = new SMESH::MedFileInfo();
505 _medFileInfo->fileName = theFileName;
506 _medFileInfo->major = 0;
507 _medFileInfo->minor = 0;
508 _medFileInfo->release = 0;
509 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
511 SMESH_CATCH( SMESH::throwCorbaException );
516 //=============================================================================
520 * Import mesh data from STL file
522 //=============================================================================
524 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
528 // Read mesh with name = <theMeshName> into SMESH_Mesh
529 std::string name = _impl->STLToMesh( theFileName );
532 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( _this() );
533 _gen_i->SetName( meshSO, name.c_str() );
535 _medFileInfo = new SMESH::MedFileInfo();
536 _medFileInfo->fileName = theFileName;
537 _medFileInfo->major = 0;
538 _medFileInfo->minor = 0;
539 _medFileInfo->release = 0;
540 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
542 SMESH_CATCH( SMESH::throwCorbaException );
547 //================================================================================
549 * \brief Function used in SMESH_CATCH by ImportGMFFile()
551 //================================================================================
555 SMESH_ComputeErrorPtr exceptionToComputeError(const char* excText)
557 return SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, excText );
561 //================================================================================
563 * \brief Import data from a GMF file and return an error description
565 //================================================================================
567 SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName,
568 bool theMakeRequiredGroups )
570 SMESH_ComputeErrorPtr error;
573 #define SMESH_CAUGHT error =
576 error = _impl->GMFToMesh( theFileName, theMakeRequiredGroups );
578 _medFileInfo = new SMESH::MedFileInfo();
579 _medFileInfo->fileName = theFileName;
580 _medFileInfo->major = 0;
581 _medFileInfo->minor = 0;
582 _medFileInfo->release = 0;
583 _medFileInfo->fileSize = SMESH_File( theFileName ).size();
585 SMESH_CATCH( exceptionToComputeError );
589 CreateGroupServants();
591 return ConvertComputeError( error );
594 //=============================================================================
596 * \brief Convert SMESH_Hypothesis::Hypothesis_Status into SMESH::Hypothesis_Status
598 //=============================================================================
600 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
602 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
603 (SMESH_Hypothesis::Hypothesis_Status theStatus)
606 RETURNCASE( HYP_OK );
607 RETURNCASE( HYP_MISSING );
608 RETURNCASE( HYP_CONCURRENT );
609 RETURNCASE( HYP_BAD_PARAMETER );
610 RETURNCASE( HYP_HIDDEN_ALGO );
611 RETURNCASE( HYP_HIDING_ALGO );
612 RETURNCASE( HYP_UNKNOWN_FATAL );
613 RETURNCASE( HYP_INCOMPATIBLE );
614 RETURNCASE( HYP_NOTCONFORM );
615 RETURNCASE( HYP_ALREADY_EXIST );
616 RETURNCASE( HYP_BAD_DIM );
617 RETURNCASE( HYP_BAD_SUBSHAPE );
618 RETURNCASE( HYP_BAD_GEOMETRY );
619 RETURNCASE( HYP_NEED_SHAPE );
620 RETURNCASE( HYP_INCOMPAT_HYPS );
623 return SMESH::HYP_UNKNOWN_FATAL;
626 //=============================================================================
630 * Call internal addHypothesis() and then add a reference to <anHyp> under
631 * the SObject actually having a reference to <aSubShape>.
632 * NB: For this method to work, it is necessary to add a reference to sub-shape first.
634 //=============================================================================
636 SMESH::Hypothesis_Status
637 SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShape,
638 SMESH::SMESH_Hypothesis_ptr anHyp,
639 CORBA::String_out anErrorText)
641 Unexpect aCatch(SALOME_SalomeException);
643 const int prevNbMeshEnt = NbNodes() + NbElements();
646 _preMeshInfo->ForgetOrLoad();
649 SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
650 anErrorText = error.c_str();
652 SMESH::SMESH_Mesh_var mesh( _this() );
653 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
655 _gen_i->AddHypothesisToShape( mesh, aSubShape, anHyp );
657 //int newNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements();
658 if ( prevNbMeshEnt > 0 /*newNbMeshEnt != prevNbMeshEnt*/ )
659 _gen_i->UpdateIcons( mesh );
661 if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
663 // Update Python script
664 TPythonDump() << "status = " << mesh << ".AddHypothesis( "
665 << aSubShape << ", " << anHyp << " )";
667 return ConvertHypothesisStatus(status);
670 //================================================================================
672 * \brief Create a sub-mesh and add a hypothesis to it
674 //================================================================================
676 SMESH_Hypothesis::Hypothesis_Status
677 SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShape,
678 SMESH::SMESH_Hypothesis_ptr anHyp,
679 std::string* anErrorText)
681 if(MYDEBUG) MESSAGE("addHypothesis");
683 if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
684 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
686 if (CORBA::is_nil( anHyp ))
687 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",SALOME::BAD_PARAM);
689 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
692 TopoDS_Shape myLocSubShape;
693 //use PseudoShape in case if mesh has no shape
695 myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
697 myLocSubShape = _impl->GetShapeToMesh();
699 const int hypId = anHyp->GetId();
701 status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
702 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
704 _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
706 // assure there is a corresponding submesh
707 if ( !_impl->IsMainShape( myLocSubShape )) {
708 int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
709 if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
710 SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
713 else if ( anErrorText )
715 *anErrorText = error;
718 catch(SALOME_Exception & S_ex)
720 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
725 //================================================================================
727 * \brief Un-assign a hypothesis from a sub-mesh dedicate to the given sub-shape
729 //================================================================================
731 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
732 SMESH::SMESH_Hypothesis_ptr anHyp)
734 Unexpect aCatch(SALOME_SalomeException);
736 _preMeshInfo->ForgetOrLoad();
738 SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
739 SMESH::SMESH_Mesh_var mesh = _this();
741 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
743 _gen_i->RemoveHypothesisFromShape( mesh, aSubShape, anHyp );
744 _gen_i->UpdateIcons( mesh );
746 // Update Python script
747 if(_impl->HasShapeToMesh())
748 TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
749 << aSubShape << ", " << anHyp << " )";
751 TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
754 return ConvertHypothesisStatus(status);
757 //=============================================================================
759 * \brief Un-assign a hypothesis from a sub-mesh dedicate to the given sub-shape
761 //=============================================================================
763 SMESH_Hypothesis::Hypothesis_Status
764 SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShape,
765 SMESH::SMESH_Hypothesis_ptr anHyp)
767 if(MYDEBUG) MESSAGE("removeHypothesis()");
769 if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
770 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
772 if (CORBA::is_nil( anHyp ))
773 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
776 _preMeshInfo->ForgetOrLoad();
778 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
781 TopoDS_Shape myLocSubShape;
782 //use PseudoShape in case if mesh has no shape
783 if( _impl->HasShapeToMesh() )
784 myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
786 myLocSubShape = _impl->GetShapeToMesh();
788 const int hypId = anHyp->GetId();
789 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
790 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
792 // _mapHypo.erase( hypId ); EAP: hyp can be used on many sub-shapes
796 catch(SALOME_Exception & S_ex)
798 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
803 //================================================================================
805 * \brief Return hypotheses assigned to a given sub-shape
807 //================================================================================
809 SMESH::ListOfHypothesis *
810 SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
812 Unexpect aCatch(SALOME_SalomeException);
813 if (MYDEBUG) MESSAGE("GetHypothesisList");
814 if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
815 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
817 SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
820 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
821 if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
822 myLocSubShape = _impl->GetShapeToMesh();
823 const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
824 int i = 0, n = aLocalList.size();
827 list<const SMESHDS_Hypothesis*>::const_iterator aHyp = aLocalList.begin();
828 std::map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id_hypptr;
829 for ( ; i < n && aHyp != aLocalList.end(); aHyp++ )
831 id_hypptr = _mapHypo.find( (*aHyp)->GetID() );
832 if ( id_hypptr != _mapHypo.end() )
833 aList[i++] = SMESH::SMESH_Hypothesis::_narrow( id_hypptr->second );
837 catch(SALOME_Exception & S_ex) {
838 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
841 return aList._retn();
844 //================================================================================
846 * \brief Return sub-meshes
848 //================================================================================
850 SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes()
852 Unexpect aCatch(SALOME_SalomeException);
853 if (MYDEBUG) MESSAGE("GetSubMeshes");
855 SMESH::submesh_array_var aList = new SMESH::submesh_array();
858 TPythonDump aPythonDump;
859 if ( !_mapSubMeshIor.empty() )
863 aList->length( _mapSubMeshIor.size() );
865 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.begin();
866 for ( ; it != _mapSubMeshIor.end(); it++ ) {
867 if ( CORBA::is_nil( it->second )) continue;
868 aList[i++] = SMESH::SMESH_subMesh::_duplicate( it->second );
870 if (i > 1) aPythonDump << ", ";
871 aPythonDump << it->second;
875 catch(SALOME_Exception & S_ex) {
876 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
879 // Update Python script
880 if ( !_mapSubMeshIor.empty() )
881 aPythonDump << " ] = " << SMESH::SMESH_Mesh_var( _this() ) << ".GetSubMeshes()";
883 return aList._retn();
886 //================================================================================
888 * \brief Create and return a sub-mesh on the given sub-shape
890 //================================================================================
892 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
893 const char* theName )
895 Unexpect aCatch(SALOME_SalomeException);
896 if (CORBA::is_nil(aSubShape))
897 THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
899 SMESH::SMESH_subMesh_var subMesh;
900 SMESH::SMESH_Mesh_var aMesh = _this();
902 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
904 //Get or Create the SMESH_subMesh object implementation
906 TopoDS_Iterator it( myLocSubShape );
907 int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
908 bool isValidSub = ( subMeshId || _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape ));
909 if ( isValidSub && myLocSubShape.ShapeType() == TopAbs_COMPOUND )
910 isValidSub = !it.Value().IsSame( _impl->GetShapeToMesh() );
914 THROW_SALOME_CORBA_EXCEPTION("Not a sub-shape of the main shape", SALOME::BAD_PARAM);
916 subMesh = getSubMesh( subMeshId );
918 // create a new subMesh object servant if there is none for the shape
919 if ( subMesh->_is_nil() )
920 subMesh = createSubMesh( aSubShape );
921 if ( _gen_i->CanPublishInStudy( subMesh ))
923 SALOMEDS::SObject_wrap aSO =
924 _gen_i->PublishSubMesh( aMesh, subMesh, aSubShape, theName );
925 if ( !aSO->_is_nil()) {
926 // Update Python script
927 TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
928 << aSubShape << ", '" << theName << "' )";
932 catch(SALOME_Exception & S_ex) {
933 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
935 return subMesh._retn();
938 //================================================================================
940 * \brief Remove a sub-mesh
942 //================================================================================
944 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
948 if ( theSubMesh->_is_nil() )
951 GEOM::GEOM_Object_var aSubShape;
952 // Remove submesh's SObject
953 SALOMEDS::SObject_wrap anSO = _gen_i->ObjectToSObject( theSubMesh );
954 if ( !anSO->_is_nil() ) {
955 long aTag = SMESH_Gen_i::GetRefOnShapeTag();
956 SALOMEDS::SObject_wrap anObj, aRef;
957 if ( anSO->FindSubObject( aTag, anObj.inout() ) &&
958 anObj->ReferencedObject( aRef.inout() ))
960 CORBA::Object_var obj = aRef->GetObject();
961 aSubShape = GEOM::GEOM_Object::_narrow( obj );
963 // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
964 // aSubShape = theSubMesh->GetSubShape();
966 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
967 builder->RemoveObjectWithChildren( anSO );
969 // Update Python script
970 TPythonDump() << SMESH::SMESH_Mesh_var( _this() ) << ".RemoveSubMesh( " << anSO << " )";
973 if ( removeSubMesh( theSubMesh, aSubShape.in() ))
975 _preMeshInfo->ForgetOrLoad();
977 SMESH_CATCH( SMESH::throwCorbaException );
980 //================================================================================
982 * \brief Create a standalone group
984 //================================================================================
986 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
987 const char* theName )
989 Unexpect aCatch(SALOME_SalomeException);
991 _preMeshInfo->FullLoadFromFile();
993 SMESH::SMESH_Group_var aNewGroup =
994 SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
996 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
998 SMESH::SMESH_Mesh_var mesh = _this();
999 SALOMEDS::SObject_wrap aSO =
1000 _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName);
1001 if ( !aSO->_is_nil())
1002 // Update Python script
1003 TPythonDump() << aSO << " = " << mesh << ".CreateGroup( "
1004 << theElemType << ", '" << theName << "' )";
1006 return aNewGroup._retn();
1009 //================================================================================
1011 * \brief Create a group based on the given geometry
1013 //================================================================================
1015 SMESH::SMESH_GroupOnGeom_ptr
1016 SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType theElemType,
1017 const char* theName,
1018 GEOM::GEOM_Object_ptr theGeomObj)
1020 Unexpect aCatch(SALOME_SalomeException);
1022 _preMeshInfo->FullLoadFromFile();
1024 SMESH::SMESH_GroupOnGeom_var aNewGroup;
1026 TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
1027 if ( !aShape.IsNull() )
1030 SMESH::SMESH_GroupOnGeom::_narrow( createGroup( theElemType, theName, /*id=*/-1, aShape ));
1032 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1034 SMESH::SMESH_Mesh_var mesh = _this();
1035 SALOMEDS::SObject_wrap aSO =
1036 _gen_i->PublishGroup( mesh, aNewGroup, theGeomObj, theName );
1037 if ( !aSO->_is_nil())
1038 TPythonDump() << aSO << " = " << mesh << ".CreateGroupFromGEOM( "
1039 << theElemType << ", '" << theName << "', " << theGeomObj << " )";
1043 return aNewGroup._retn();
1046 //================================================================================
1048 * \brief Creates a group whose contents is defined by filter
1049 * \param theElemType - group type
1050 * \param theName - group name
1051 * \param theFilter - the filter
1052 * \retval SMESH::SMESH_GroupOnFilter_ptr - group defined by filter
1054 //================================================================================
1056 SMESH::SMESH_GroupOnFilter_ptr
1057 SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
1058 const char* theName,
1059 SMESH::Filter_ptr theFilter )
1061 Unexpect aCatch(SALOME_SalomeException);
1063 _preMeshInfo->FullLoadFromFile();
1065 if ( CORBA::is_nil( theFilter ))
1066 THROW_SALOME_CORBA_EXCEPTION("NULL filter", SALOME::BAD_PARAM);
1068 SMESH_PredicatePtr predicate = SMESH_GroupOnFilter_i::GetPredicate( theFilter );
1070 THROW_SALOME_CORBA_EXCEPTION("Invalid filter", SALOME::BAD_PARAM);
1072 SMESH::SMESH_GroupOnFilter_var aNewGroup = SMESH::SMESH_GroupOnFilter::_narrow
1073 ( createGroup( theElemType, theName, /*id=*/-1, TopoDS_Shape(), predicate ));
1076 if ( !aNewGroup->_is_nil() )
1077 aNewGroup->SetFilter( theFilter );
1079 if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1081 SMESH::SMESH_Mesh_var mesh = _this();
1082 SALOMEDS::SObject_wrap aSO =
1083 _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName );
1085 if ( !aSO->_is_nil())
1086 pd << aSO << " = " << mesh << ".CreateGroupFromFilter( "
1087 << theElemType << ", '" << theName << "', " << theFilter << " )";
1089 return aNewGroup._retn();
1092 //================================================================================
1094 * \brief Remove a group
1096 //================================================================================
1098 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
1100 if ( theGroup->_is_nil() )
1105 SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
1109 if ( aGroup->GetMeshServant() != this )
1110 THROW_SALOME_CORBA_EXCEPTION( "RemoveGroup(): group does not belong to this mesh",
1111 SALOME::BAD_PARAM );
1113 SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( theGroup );
1114 if ( !aGroupSO->_is_nil() )
1116 // Update Python script
1117 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroup( " << aGroupSO << " )";
1119 // Remove group's SObject
1120 SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::getStudyServant()->NewBuilder();
1121 builder->RemoveObjectWithChildren( aGroupSO );
1123 aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
1125 // Remove the group from SMESH data structures
1126 removeGroup( aGroup->GetLocalID() );
1128 SMESH_CATCH( SMESH::throwCorbaException );
1131 //=============================================================================
1133 * Remove group with its contents
1135 //=============================================================================
1137 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
1141 _preMeshInfo->FullLoadFromFile();
1143 if ( theGroup->_is_nil() )
1146 SMESH_GroupBase_i* groupImpl = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup );
1147 if ( !groupImpl || groupImpl->GetMeshServant() != this )
1148 THROW_SALOME_CORBA_EXCEPTION( "RemoveGroupWithContents(): group does not belong to this mesh",
1151 vector<int> nodeIds; // to remove nodes becoming free
1152 bool isNodal = ( theGroup->GetType() == SMESH::NODE );
1153 if ( !isNodal && !theGroup->IsEmpty() )
1155 CORBA::Long elemID = theGroup->GetID( 1 );
1156 int nbElemNodes = GetElemNbNodes( elemID );
1157 if ( nbElemNodes > 0 )
1158 nodeIds.reserve( theGroup->Size() * nbElemNodes );
1161 // Retrieve contents
1162 SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );
1163 SMDS_ElemIteratorPtr elemIt = GetElements( idSrc, theGroup->GetType() );
1164 SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > elemBeg( elemIt ), elemEnd;
1165 std::vector< const SMDS_MeshElement* > elems( theGroup->Size() );
1166 elems.assign( elemBeg, elemEnd );
1168 TPythonDump pyDump; // Suppress dump from RemoveGroup()
1171 RemoveGroup( theGroup );
1174 for ( size_t i = 0; i < elems.size(); ++i )
1176 // if ( !_impl->GetMeshDS()->Contains( elems[i] ))
1180 for ( SMDS_ElemIteratorPtr nIt = elems[i]->nodesIterator(); nIt->more(); )
1181 nodeIds.push_back( nIt->next()->GetID() );
1183 _impl->GetMeshDS()->RemoveFreeElement( elems[i], /*sm=*/0 );
1187 _impl->GetMeshDS()->RemoveElement( elems[i] );
1191 // Remove free nodes
1192 for ( size_t i = 0 ; i < nodeIds.size(); ++i )
1193 if ( const SMDS_MeshNode* n = _impl->GetMeshDS()->FindNode( nodeIds[i] ))
1194 if ( n->NbInverseElements() == 0 )
1195 _impl->GetMeshDS()->RemoveFreeNode( n, /*sm=*/0 );
1197 _impl->GetMeshDS()->Modified();
1198 _impl->SetIsModified( true );
1200 // Update Python script (theGroup must be alive for this)
1201 pyDump << SMESH::SMESH_Mesh_var(_this())
1202 << ".RemoveGroupWithContents( " << theGroup << " )";
1204 SMESH_CATCH( SMESH::throwCorbaException );
1207 //================================================================================
1209 * \brief Get the list of groups existing in the mesh
1210 * \retval SMESH::ListOfGroups * - list of groups
1212 //================================================================================
1214 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups()
1216 Unexpect aCatch(SALOME_SalomeException);
1217 if (MYDEBUG) MESSAGE("GetGroups");
1219 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
1222 TPythonDump aPythonDump;
1223 if ( !_mapGroups.empty() )
1225 aPythonDump << "[ ";
1227 aList->length( _mapGroups.size() );
1229 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
1230 for ( ; it != _mapGroups.end(); it++ ) {
1231 if ( CORBA::is_nil( it->second )) continue;
1232 aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
1234 if (i > 1) aPythonDump << ", ";
1235 aPythonDump << it->second;
1239 catch(SALOME_Exception & S_ex) {
1240 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1242 aPythonDump << " ] = " << SMESH::SMESH_Mesh_var(_this()) << ".GetGroups()";
1244 return aList._retn();
1247 //=============================================================================
1249 * Get number of groups existing in the mesh
1251 //=============================================================================
1253 CORBA::Long SMESH_Mesh_i::NbGroups()
1255 Unexpect aCatch(SALOME_SalomeException);
1256 return _mapGroups.size();
1259 //=============================================================================
1261 * New group including all mesh elements present in initial groups is created.
1263 //=============================================================================
1265 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1266 SMESH::SMESH_GroupBase_ptr theGroup2,
1267 const char* theName )
1269 SMESH::SMESH_Group_var aResGrp;
1273 _preMeshInfo->FullLoadFromFile();
1275 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1276 THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): NULL Group",
1278 if ( theGroup1->GetType() != theGroup2->GetType() )
1279 THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): different group types",
1284 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1285 if ( aResGrp->_is_nil() )
1286 return SMESH::SMESH_Group::_nil();
1288 aResGrp->AddFrom( theGroup1 );
1289 aResGrp->AddFrom( theGroup2 );
1291 // Update Python script
1292 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this())
1293 << ".UnionGroups( " << theGroup1 << ", " << theGroup2 << ", '" << theName << "' )";
1295 SMESH_CATCH( SMESH::throwCorbaException );
1297 return aResGrp._retn();
1300 //=============================================================================
1302 * \brief New group including all mesh elements present in initial groups is created.
1303 * \param theGroups list of groups
1304 * \param theName name of group to be created
1305 * \return pointer to the new group
1307 //=============================================================================
1309 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
1310 const char* theName )
1312 SMESH::SMESH_Group_var aResGrp;
1315 _preMeshInfo->FullLoadFromFile();
1318 return SMESH::SMESH_Group::_nil();
1323 SMESH::ElementType aType = SMESH::ALL;
1324 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1326 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1327 if ( CORBA::is_nil( aGrp ) )
1329 if ( aType == SMESH::ALL )
1330 aType = aGrp->GetType();
1331 else if ( aType != aGrp->GetType() )
1332 THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1335 if ( aType == SMESH::ALL )
1336 return SMESH::SMESH_Group::_nil();
1341 aResGrp = CreateGroup( aType, theName );
1342 if ( aResGrp->_is_nil() )
1343 return SMESH::SMESH_Group::_nil();
1345 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".UnionListOfGroups([ ";
1346 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1348 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1349 if ( !CORBA::is_nil( aGrp ) )
1351 aResGrp->AddFrom( aGrp );
1352 if ( g > 0 ) pyDump << ", ";
1356 pyDump << " ], '" << theName << "' )";
1358 SMESH_CATCH( SMESH::throwCorbaException );
1360 return aResGrp._retn();
1363 //=============================================================================
1365 * New group is created. All mesh elements that are
1366 * present in both initial groups are added to the new one.
1368 //=============================================================================
1370 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1371 SMESH::SMESH_GroupBase_ptr theGroup2,
1372 const char* theName )
1374 SMESH::SMESH_Group_var aResGrp;
1379 _preMeshInfo->FullLoadFromFile();
1381 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1382 THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): NULL Group",
1384 if ( theGroup1->GetType() != theGroup2->GetType() )
1385 THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): different group types",
1389 // Create Intersection
1390 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1391 if ( aResGrp->_is_nil() )
1392 return aResGrp._retn();
1394 SMESHDS_GroupBase* groupDS1 = 0;
1395 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1396 groupDS1 = grp_i->GetGroupDS();
1398 SMESHDS_GroupBase* groupDS2 = 0;
1399 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1400 groupDS2 = grp_i->GetGroupDS();
1402 SMESHDS_Group* resGroupDS = 0;
1403 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1404 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1406 if ( groupDS1 && groupDS2 && resGroupDS && !groupDS2->IsEmpty() )
1408 SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1409 while ( elemIt1->more() )
1411 const SMDS_MeshElement* e = elemIt1->next();
1412 if ( groupDS2->Contains( e ))
1413 resGroupDS->SMDSGroup().Add( e );
1416 // Update Python script
1417 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".IntersectGroups( "
1418 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1420 SMESH_CATCH( SMESH::throwCorbaException );
1422 return aResGrp._retn();
1425 //=============================================================================
1427 \brief Intersect list of groups. New group is created. All mesh elements that
1428 are present in all initial groups simultaneously are added to the new one.
1429 \param theGroups list of groups
1430 \param theName name of group to be created
1431 \return pointer on the group
1433 //=============================================================================
1435 SMESH::SMESH_Group_ptr
1436 SMESH_Mesh_i::IntersectListOfGroups(const SMESH::ListOfGroups& theGroups,
1437 const char* theName )
1439 SMESH::SMESH_Group_var aResGrp;
1444 _preMeshInfo->FullLoadFromFile();
1447 return SMESH::SMESH_Group::_nil();
1449 // check types and get SMESHDS_GroupBase's
1450 SMESH::ElementType aType = SMESH::ALL;
1451 vector< SMESHDS_GroupBase* > groupVec;
1452 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1454 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1455 if ( CORBA::is_nil( aGrp ) )
1457 if ( aType == SMESH::ALL )
1458 aType = aGrp->GetType();
1459 else if ( aType != aGrp->GetType() )
1460 THROW_SALOME_CORBA_EXCEPTION("IntersectListOfGroups(): different group types",
1463 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1464 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1466 if ( grpDS->IsEmpty() )
1471 groupVec.push_back( grpDS );
1474 if ( aType == SMESH::ALL ) // all groups are nil
1475 return SMESH::SMESH_Group::_nil();
1480 aResGrp = CreateGroup( aType, theName );
1482 SMESHDS_Group* resGroupDS = 0;
1483 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1484 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1485 if ( !resGroupDS || groupVec.empty() )
1486 return aResGrp._retn();
1489 size_t i, nb = groupVec.size();
1490 SMDS_ElemIteratorPtr elemIt1 = groupVec[0]->GetElements();
1491 while ( elemIt1->more() )
1493 const SMDS_MeshElement* e = elemIt1->next();
1495 for ( i = 1; ( i < nb && inAll ); ++i )
1496 inAll = groupVec[i]->Contains( e );
1499 resGroupDS->SMDSGroup().Add( e );
1502 // Update Python script
1503 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1504 << ".IntersectListOfGroups( " << theGroups << ", '" << theName << "' )";
1506 SMESH_CATCH( SMESH::throwCorbaException );
1508 return aResGrp._retn();
1511 //=============================================================================
1513 * New group is created. All mesh elements that are present in
1514 * a main group but is not present in a tool group are added to the new one
1516 //=============================================================================
1518 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1519 SMESH::SMESH_GroupBase_ptr theGroup2,
1520 const char* theName )
1522 SMESH::SMESH_Group_var aResGrp;
1527 _preMeshInfo->FullLoadFromFile();
1529 if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1530 THROW_SALOME_CORBA_EXCEPTION("CutGroups(): NULL Group",
1532 if ( theGroup1->GetType() != theGroup2->GetType() )
1533 THROW_SALOME_CORBA_EXCEPTION("CutGroups(): different group types",
1537 aResGrp = CreateGroup( theGroup1->GetType(), theName );
1538 if ( aResGrp->_is_nil() )
1539 return aResGrp._retn();
1541 SMESHDS_GroupBase* groupDS1 = 0;
1542 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1543 groupDS1 = grp_i->GetGroupDS();
1545 SMESHDS_GroupBase* groupDS2 = 0;
1546 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1547 groupDS2 = grp_i->GetGroupDS();
1549 SMESHDS_Group* resGroupDS = 0;
1550 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1551 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1553 if ( groupDS1 && groupDS2 && resGroupDS )
1555 SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1556 while ( elemIt1->more() )
1558 const SMDS_MeshElement* e = elemIt1->next();
1559 if ( !groupDS2->Contains( e ))
1560 resGroupDS->SMDSGroup().Add( e );
1563 // Update Python script
1564 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".CutGroups( "
1565 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1567 SMESH_CATCH( SMESH::throwCorbaException );
1569 return aResGrp._retn();
1572 //=============================================================================
1574 \brief Cut lists of groups. New group is created. All mesh elements that are
1575 present in main groups but do not present in tool groups are added to the new one
1576 \param theMainGroups list of main groups
1577 \param theToolGroups list of tool groups
1578 \param theName name of group to be created
1579 \return pointer on the group
1581 //=============================================================================
1583 SMESH::SMESH_Group_ptr
1584 SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
1585 const SMESH::ListOfGroups& theToolGroups,
1586 const char* theName )
1588 SMESH::SMESH_Group_var aResGrp;
1593 _preMeshInfo->FullLoadFromFile();
1596 return SMESH::SMESH_Group::_nil();
1598 // check types and get SMESHDS_GroupBase's
1599 SMESH::ElementType aType = SMESH::ALL;
1600 vector< SMESHDS_GroupBase* > toolGroupVec;
1601 vector< SMDS_ElemIteratorPtr > mainIterVec;
1603 for ( int g = 0, n = theMainGroups.length(); g < n; g++ )
1605 SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1606 if ( CORBA::is_nil( aGrp ) )
1608 if ( aType == SMESH::ALL )
1609 aType = aGrp->GetType();
1610 else if ( aType != aGrp->GetType() )
1611 THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1613 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1614 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1615 if ( !grpDS->IsEmpty() )
1616 mainIterVec.push_back( grpDS->GetElements() );
1618 if ( aType == SMESH::ALL ) // all main groups are nil
1619 return SMESH::SMESH_Group::_nil();
1620 if ( mainIterVec.empty() ) // all main groups are empty
1621 return aResGrp._retn();
1623 for ( int g = 0, n = theToolGroups.length(); g < n; g++ )
1625 SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1626 if ( CORBA::is_nil( aGrp ) )
1628 if ( aType != aGrp->GetType() )
1629 THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1631 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1632 if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1633 toolGroupVec.push_back( grpDS );
1639 aResGrp = CreateGroup( aType, theName );
1641 SMESHDS_Group* resGroupDS = 0;
1642 if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1643 resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1645 return aResGrp._retn();
1648 size_t i, nb = toolGroupVec.size();
1649 SMDS_ElemIteratorPtr mainElemIt
1650 ( new SMDS_IteratorOnIterators
1651 < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > >( mainIterVec ));
1652 while ( mainElemIt->more() )
1654 const SMDS_MeshElement* e = mainElemIt->next();
1656 for ( i = 0; ( i < nb && !isIn ); ++i )
1657 isIn = toolGroupVec[i]->Contains( e );
1660 resGroupDS->SMDSGroup().Add( e );
1663 // Update Python script
1664 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1665 << ".CutListOfGroups( " << theMainGroups << ", "
1666 << theToolGroups << ", '" << theName << "' )";
1668 SMESH_CATCH( SMESH::throwCorbaException );
1670 return aResGrp._retn();
1673 namespace // functions making checks according to SMESH::NB_COMMON_NODES_ENUM
1675 bool isAllNodesCommon(int nbChecked, int nbCommon, int nbNodes, int /*nbCorners*/,
1676 bool & toStopChecking )
1678 toStopChecking = ( nbCommon < nbChecked );
1679 return nbCommon == nbNodes;
1681 bool isMainNodesCommon(int nbChecked, int nbCommon, int /*nbNodes*/, int nbCorners,
1682 bool & toStopChecking )
1684 toStopChecking = ( nbCommon < nbChecked || nbChecked >= nbCorners );
1685 return nbCommon == nbCorners;
1687 bool isAtLeastOneNodeCommon(int /*nbChecked*/, int nbCommon, int /*nbNodes*/, int /*nbCorners*/,
1688 bool & /*toStopChecking*/ )
1690 return nbCommon > 0;
1692 bool isMajorityOfNodesCommon(int /*nbChecked*/, int nbCommon, int nbNodes, int /*nbCorners*/,
1693 bool & /*toStopChecking*/ )
1695 return nbCommon >= (nbNodes+1) / 2;
1699 //=============================================================================
1701 * Create a group of entities basing on nodes of other groups.
1702 * \param [in] theGroups - list of either groups, sub-meshes or filters.
1703 * \param [in] anElemType - a type of elements to include to the new group.
1704 * \param [in] theName - a name of the new group.
1705 * \param [in] theNbCommonNodes - criterion of inclusion of an element to the new group.
1706 * \param [in] theUnderlyingOnly - if \c True, an element is included to the
1707 * new group provided that it is based on nodes of an element of \a aListOfGroups
1708 * \return SMESH_Group - the created group
1710 // IMP 19939, bug 22010, IMP 22635
1711 //=============================================================================
1713 SMESH::SMESH_Group_ptr
1714 SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfIDSources& theGroups,
1715 SMESH::ElementType theElemType,
1716 const char* theName,
1717 SMESH::NB_COMMON_NODES_ENUM theNbCommonNodes,
1718 CORBA::Boolean theUnderlyingOnly)
1720 SMESH::SMESH_Group_var aResGrp;
1724 _preMeshInfo->FullLoadFromFile();
1726 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1728 if ( !theName || !aMeshDS )
1729 return SMESH::SMESH_Group::_nil();
1731 SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1733 bool (*isToInclude)(int nbChecked, int nbCommon, int nbNodes, int nbCorners, bool & toStop);
1734 SMESH_Comment nbCoNoStr( "SMESH.");
1735 switch ( theNbCommonNodes ) {
1736 case SMESH::ALL_NODES : isToInclude = isAllNodesCommon; nbCoNoStr<<"ALL_NODES" ;break;
1737 case SMESH::MAIN : isToInclude = isMainNodesCommon; nbCoNoStr<<"MAIN" ;break;
1738 case SMESH::AT_LEAST_ONE: isToInclude = isAtLeastOneNodeCommon; nbCoNoStr<<"AT_LEAST_ONE";break;
1739 case SMESH::MAJORITY : isToInclude = isMajorityOfNodesCommon; nbCoNoStr<<"MAJORITY" ;break;
1740 default: return aResGrp._retn();
1742 int nbChecked, nbCommon, nbNodes, nbCorners;
1748 aResGrp = CreateGroup( theElemType, theName );
1749 if ( aResGrp->_is_nil() )
1750 return SMESH::SMESH_Group::_nil();
1752 SMESHDS_GroupBase* groupBaseDS =
1753 SMESH::DownCast<SMESH_GroupBase_i*>( aResGrp )->GetGroupDS();
1754 SMDS_MeshGroup& resGroupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1756 vector<bool> isNodeInGroups;
1758 for ( int g = 0, n = theGroups.length(); g < n; g++ ) // loop on theGroups
1760 SMESH::SMESH_IDSource_var aGrp = theGroups[ g ];
1761 if ( CORBA::is_nil( aGrp ) )
1763 SMESH::SMESH_Mesh_var mesh = aGrp->GetMesh();
1764 if ( mesh->_is_nil() || mesh->GetId() != this->GetId() )
1767 SMDS_ElemIteratorPtr elIt = GetElements( aGrp, SMESH::ALL );
1768 if ( !elIt ) continue;
1770 if ( theElemType == SMESH::NODE ) // get all nodes of elements
1772 while ( elIt->more() ) {
1773 const SMDS_MeshElement* el = elIt->next();
1774 SMDS_ElemIteratorPtr nIt = el->nodesIterator();
1775 while ( nIt->more() )
1776 resGroupCore.Add( nIt->next() );
1779 // get elements of theElemType based on nodes of every element of group
1780 else if ( theUnderlyingOnly )
1782 while ( elIt->more() )
1784 const SMDS_MeshElement* el = elIt->next(); // an element of ref group
1785 TIDSortedElemSet elNodes( el->begin_nodes(), el->end_nodes() );
1786 TIDSortedElemSet checkedElems;
1787 SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1788 while ( nIt->more() )
1790 const SMDS_MeshNode* n = nIt->next();
1791 SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1792 // check nodes of elements of theElemType around el
1793 while ( elOfTypeIt->more() )
1795 const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1796 if ( !checkedElems.insert( elOfType ).second ) continue;
1797 nbNodes = elOfType->NbNodes();
1798 nbCorners = elOfType->NbCornerNodes();
1800 bool toStopChecking = false;
1801 SMDS_ElemIteratorPtr nIt2 = elOfType->nodesIterator();
1802 for ( nbChecked = 1; nIt2->more() && !toStopChecking; ++nbChecked )
1803 if ( elNodes.count( nIt2->next() ) &&
1804 isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1806 resGroupCore.Add( elOfType );
1813 // get all nodes of elements of groups
1816 while ( elIt->more() )
1818 const SMDS_MeshElement* el = elIt->next(); // an element of group
1819 SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1820 while ( nIt->more() )
1822 const SMDS_MeshNode* n = nIt->next();
1823 if ( n->GetID() >= (int) isNodeInGroups.size() )
1824 isNodeInGroups.resize( n->GetID() + 1, false );
1825 isNodeInGroups[ n->GetID() ] = true;
1831 // Get elements of theElemType based on a certain number of nodes of elements of groups
1832 if ( !theUnderlyingOnly && !isNodeInGroups.empty() )
1834 const SMDS_MeshNode* n;
1835 vector<bool> isElemChecked( aMeshDS->MaxElementID() + 1 );
1836 const int isNodeInGroupsSize = isNodeInGroups.size();
1837 for ( int iN = 0; iN < isNodeInGroupsSize; ++iN )
1839 if ( !isNodeInGroups[ iN ] ||
1840 !( n = aMeshDS->FindNode( iN )))
1843 // check nodes of elements of theElemType around n
1844 SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1845 while ( elOfTypeIt->more() )
1847 const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1848 vector<bool>::reference isChecked = isElemChecked[ elOfType->GetID() ];
1853 nbNodes = elOfType->NbNodes();
1854 nbCorners = elOfType->NbCornerNodes();
1856 bool toStopChecking = false;
1857 SMDS_ElemIteratorPtr nIt = elOfType->nodesIterator();
1858 for ( nbChecked = 1; nIt->more() && !toStopChecking; ++nbChecked )
1860 const int nID = nIt->next()->GetID();
1861 if ( nID < isNodeInGroupsSize && isNodeInGroups[ nID ] &&
1862 isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1864 resGroupCore.Add( elOfType );
1872 // Update Python script
1873 pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this())
1874 << ".CreateDimGroup( "
1875 << theGroups << ", " << theElemType << ", '" << theName << "', "
1876 << nbCoNoStr << ", " << theUnderlyingOnly << ")";
1878 SMESH_CATCH( SMESH::throwCorbaException );
1880 return aResGrp._retn();
1883 //================================================================================
1885 * \brief Distribute all faces of the mesh between groups using sharp edges and optionally
1886 * existing 1D elements as group boundaries.
1887 * \param [in] theSharpAngle - edge is considered sharp if an angle between normals of
1888 * adjacent faces is more than \a sharpAngle in degrees.
1889 * \param [in] theCreateEdges - to create 1D elements for detected sharp edges.
1890 * \param [in] theUseExistingEdges - to use existing edges as group boundaries
1891 * \return ListOfGroups - the created groups
1893 //================================================================================
1895 SMESH::ListOfGroups*
1896 SMESH_Mesh_i::FaceGroupsSeparatedByEdges( CORBA::Double theSharpAngle,
1897 CORBA::Boolean theCreateEdges,
1898 CORBA::Boolean theUseExistingEdges )
1900 if ( theSharpAngle < 0 || theSharpAngle > 180 )
1901 THROW_SALOME_CORBA_EXCEPTION("Invalid sharp angle, it must be between 0 and 180 degrees",
1904 SMESH::ListOfGroups_var resultGroups = new SMESH::ListOfGroups;
1910 _preMeshInfo->FullLoadFromFile();
1912 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1914 std::vector< SMESH_MeshAlgos::Edge > edges =
1915 SMESH_MeshAlgos::FindSharpEdges( meshDS, theSharpAngle, theUseExistingEdges );
1917 if ( theCreateEdges )
1919 std::vector<const SMDS_MeshNode *> nodes(2);
1920 for ( size_t i = 0; i < edges.size(); ++i )
1922 nodes[0] = edges[i]._node1;
1923 nodes[1] = edges[i]._node2;
1924 if ( meshDS->FindElement( nodes, SMDSAbs_Edge ))
1926 if ( edges[i]._medium )
1927 meshDS->AddEdge( edges[i]._node1, edges[i]._node2, edges[i]._medium );
1929 meshDS->AddEdge( edges[i]._node1, edges[i]._node2 );
1933 std::vector< std::vector< const SMDS_MeshElement* > > faceGroups =
1934 SMESH_MeshAlgos::SeparateFacesByEdges( meshDS, edges );
1936 SMESH::SMESH_MeshEditor_var editor = GetMeshEditor(); // create _editor
1938 resultGroups->length( faceGroups.size() );
1939 for ( size_t iG = 0; iG < faceGroups.size(); ++iG )
1941 SMESH::SMESH_Group_var group = CreateGroup( SMESH::FACE,
1942 _editor->GenerateGroupName("Group").c_str());
1943 resultGroups[iG] = SMESH::SMESH_Group::_duplicate( group );
1945 SMESHDS_GroupBase* groupBaseDS =
1946 SMESH::DownCast<SMESH_GroupBase_i*>( group )->GetGroupDS();
1947 SMDS_MeshGroup& groupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1949 std::vector< const SMDS_MeshElement* >& faces = faceGroups[ iG ];
1950 for ( size_t i = 0; i < faces.size(); ++i )
1951 groupCore.Add( faces[i] );
1954 pyDump << resultGroups << " = " << SMESH::SMESH_Mesh_var(_this())
1955 << ".FaceGroupsSeparatedByEdges( "
1956 << TVar( theSharpAngle ) << ", "
1957 << theCreateEdges << ", "
1958 << theUseExistingEdges << " )";
1960 SMESH_CATCH( SMESH::throwCorbaException );
1961 return resultGroups._retn();
1965 //================================================================================
1967 * \brief Remember GEOM group data
1969 //================================================================================
1971 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1972 CORBA::Object_ptr theSmeshObj)
1974 if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1977 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( theGeomObj );
1978 if ( groupSO->_is_nil() )
1981 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( theGeomObj );
1982 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
1983 GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
1986 _geomGroupData.push_back( TGeomGroupData() );
1987 TGeomGroupData & groupData = _geomGroupData.back();
1989 CORBA::String_var entry = groupSO->GetID();
1990 groupData._groupEntry = entry.in();
1992 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
1993 groupData._indices.insert( ids[i] );
1995 groupData._smeshObject = CORBA::Object::_duplicate( theSmeshObj );
1996 // shape index in SMESHDS
1997 // TopoDS_Shape shape = _gen_i->GeomObjectToShape( theGeomObj );
1998 // groupData._dsID = shape.IsNull() ? 0 : _impl->GetSubMesh( shape )->GetId();
2001 //================================================================================
2003 * Remove GEOM group data relating to removed smesh object
2005 //================================================================================
2007 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
2009 list<TGeomGroupData>::iterator
2010 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2011 for ( ; data != dataEnd; ++data ) {
2012 if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
2013 _geomGroupData.erase( data );
2019 //================================================================================
2021 * \brief Replace a shape in the mesh upon Break Link
2023 //================================================================================
2025 void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom)
2027 // check if geometry changed
2028 bool geomChanged = true;
2029 GEOM::GEOM_Object_var oldGeom = GetShapeToMesh();
2030 if ( !theNewGeom->_is_nil() && !oldGeom->_is_nil() )
2031 geomChanged = ( oldGeom->GetTick() != theNewGeom->GetTick() );
2033 TopoDS_Shape S = _impl->GetShapeToMesh();
2034 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2035 TCollection_AsciiString aIOR;
2036 if ( geomClient->Find( S, aIOR ))
2037 geomClient->RemoveShapeFromBuffer( aIOR );
2039 // clear buffer also for sub-groups
2040 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2041 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2042 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2043 for (; g != groups.end(); ++g)
2044 if (const SMESHDS_GroupOnGeom* group = dynamic_cast<SMESHDS_GroupOnGeom*>(*g))
2046 const TopoDS_Shape& s = group->GetShape();
2047 if ( geomClient->Find( s, aIOR ))
2048 geomClient->RemoveShapeFromBuffer( aIOR );
2051 // clear buffer also for sub-meshes
2052 std::map<int, SMESH_subMesh_i*>::const_iterator aSubMeshIter = _mapSubMesh_i.cbegin();
2053 for(; aSubMeshIter != _mapSubMesh_i.cend(); aSubMeshIter++) {
2054 int aShapeID = aSubMeshIter->first;
2055 const TopoDS_Shape& aSubShape = meshDS->IndexToShape(aShapeID);
2056 TCollection_AsciiString aShapeIOR;
2057 if ( geomClient->Find( aSubShape, aShapeIOR ))
2058 geomClient->RemoveShapeFromBuffer( aShapeIOR );
2062 int shapeID, fromID, toID; // indices of elements of a sub-mesh
2064 std::vector< TRange > elemRanges, nodeRanges; // elements of sub-meshes
2065 std::vector< SMDS_PositionPtr > positions; // node positions
2068 // store positions of elements on geometry
2070 if ( meshDS->MaxNodeID() > meshDS->NbNodes() ||
2071 meshDS->MaxElementID() > meshDS->NbElements() )
2074 meshDS->CompactMesh();
2076 positions.resize( meshDS->NbNodes() + 1 );
2077 for ( SMDS_NodeIteratorPtr nodeIt = meshDS->nodesIterator(); nodeIt->more(); )
2079 const SMDS_MeshNode* n = nodeIt->next();
2080 positions[ n->GetID() ] = n->GetPosition();
2083 // remove elements from sub-meshes to avoid their removal at hypotheses addition
2084 for ( int isNode = 0; isNode < 2; ++isNode )
2086 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2087 ranges.reserve( meshDS->MaxShapeIndex() + 10 );
2088 ranges.push_back( TRange{ 0,0,0 });
2089 SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
2090 while ( elemIt->more() )
2092 const SMDS_MeshElement* e = elemIt->next();
2093 const int elemID = e->GetID();
2094 const int shapeID = e->GetShapeID();
2095 TRange & lastRange = ranges.back();
2096 if ( lastRange.shapeID != shapeID ||
2097 lastRange.toID != elemID )
2098 ranges.push_back( TRange{ shapeID, elemID, elemID + 1 });
2100 lastRange.toID = elemID + 1;
2102 if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( shapeID ))
2104 if ( isNode ) sm->RemoveNode( static_cast< const SMDS_MeshNode *>( e ));
2105 else sm->RemoveElement( e );
2112 // update the reference to theNewGeom (needed for correct execution of a dumped python script)
2113 SMESH::SMESH_Mesh_var me = _this();
2114 SALOMEDS::SObject_wrap aSO = _gen_i->ObjectToSObject( me );
2115 CORBA::String_var entry = theNewGeom->GetStudyEntry();
2116 if ( !aSO->_is_nil() )
2118 SALOMEDS::SObject_wrap aShapeRefSO;
2119 if ( aSO->FindSubObject( _gen_i->GetRefOnShapeTag(), aShapeRefSO.inout() ))
2121 SALOMEDS::SObject_wrap aShapeSO = _gen_i->getStudyServant()->FindObjectID( entry );
2122 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2123 builder->Addreference( aShapeRefSO, aShapeSO );
2127 // re-assign global hypotheses to the new shape
2128 _mainShapeTick = geomChanged ? -1 : theNewGeom->GetTick();
2129 CheckGeomModif( true );
2133 // restore positions of elements on geometry
2134 for ( int isNode = 0; isNode < 2; ++isNode )
2136 std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
2137 for ( size_t i = 1; i < ranges.size(); ++i )
2139 int elemID = ranges[ i ].fromID;
2140 int toID = ranges[ i ].toID;
2141 SMESHDS_SubMesh * smDS = meshDS->NewSubMesh( ranges[ i ].shapeID );
2143 for ( ; elemID < toID; ++elemID )
2144 smDS->AddNode( meshDS->FindNode( elemID ));
2146 for ( ; elemID < toID; ++elemID )
2147 smDS->AddElement( meshDS->FindElement( elemID ));
2149 if ( SMESH_subMesh* sm = _impl->GetSubMeshContaining( ranges[ i ].shapeID ))
2150 sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
2153 for ( unsigned int nodeID = 1; nodeID < positions.size(); ++nodeID )
2154 if ( positions[ nodeID ])
2155 if ( SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( meshDS->FindNode( nodeID )))
2156 n->SetPosition( positions[ nodeID ], n->GetShapeID() );
2159 _gen_i->UpdateIcons( SMESH::SMESH_Mesh_var( _this() ));
2162 TPythonDump() << "SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject("
2163 << me <<".GetMesh()), " << entry.in() << ")";
2165 TPythonDump() << me << ".ReplaceShape( " << entry.in() << " )";
2169 //================================================================================
2171 * \brief Return new group contents if it has been changed and update group data
2173 //================================================================================
2175 enum { ONLY_IF_CHANGED, IS_BREAK_LINK, MAIN_TRANSFORMED };
2177 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData, int how )
2179 TopoDS_Shape newShape;
2180 SALOMEDS::SObject_wrap groupSO;
2182 if ( how == IS_BREAK_LINK )
2184 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( groupData._smeshObject );
2185 SALOMEDS::SObject_wrap geomRefSO;
2186 if ( !meshSO->_is_nil() &&
2187 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ))
2189 geomRefSO->ReferencedObject( groupSO.inout() );
2195 groupSO = _gen_i->getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
2198 if ( groupSO->_is_nil() )
2201 CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
2202 GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
2203 if ( geomGroup->_is_nil() )
2206 // get indices of group items
2207 set<int> curIndices;
2208 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( geomGroup );
2209 GEOM::GEOM_IGroupOperations_wrap groupOp = geomGen->GetIGroupOperations();
2210 GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
2211 for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2212 curIndices.insert( ids[i] );
2214 bool sameIndices = ( groupData._indices == curIndices );
2215 if ( how == ONLY_IF_CHANGED && sameIndices )
2216 return newShape; // group not changed
2219 CORBA::String_var entry = geomGroup->GetStudyEntry();
2220 groupData._groupEntry = entry.in();
2221 groupData._indices = curIndices;
2223 newShape = _gen_i->GeomObjectToShape( geomGroup );
2225 // check if newShape is up-to-date
2226 if ( !newShape.IsNull() && ids->length() > 0 )
2228 bool toUpdate = ! _impl->GetMeshDS()->IsGroupOfSubShapes( newShape );
2231 TopExp_Explorer exp( newShape, (TopAbs_ShapeEnum)( groupOp->GetType( geomGroup )));
2232 for ( ; exp.More() && !toUpdate; exp.Next() )
2234 int ind = _impl->GetMeshDS()->ShapeToIndex( exp.Current() );
2235 toUpdate = ( curIndices.erase( ind ) == 0 );
2237 if ( !curIndices.empty() )
2242 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2243 CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
2244 geomClient->RemoveShapeFromBuffer( groupIOR.in() );
2245 newShape = _gen_i->GeomObjectToShape( geomGroup );
2250 // geom group becomes empty - return empty compound
2251 TopoDS_Compound compound;
2252 BRep_Builder().MakeCompound(compound);
2253 newShape = compound;
2261 //-----------------------------------------------------------------------------
2263 * \brief Storage of shape and index used in CheckGeomGroupModif()
2265 struct TIndexedShape
2268 TopoDS_Shape _shape;
2269 TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
2271 //-----------------------------------------------------------------------------
2273 * \brief Data to re-create a group on geometry
2275 struct TGroupOnGeomData
2278 TopoDS_Shape _shape;
2279 SMDSAbs_ElementType _type;
2281 Quantity_Color _color;
2283 TGroupOnGeomData( const SMESHDS_GroupOnGeom* group )
2285 _oldID = group->GetID();
2286 _type = group->GetType();
2287 _name = group->GetStoreName();
2288 _color = group->GetColor();
2292 //-----------------------------------------------------------------------------
2294 * \brief Check if a filter is still valid after geometry removal
2296 bool isValidGeomFilter( SMESH::Filter_var theFilter )
2298 if ( theFilter->_is_nil() )
2300 SMESH::Filter::Criteria_var criteria;
2301 theFilter->GetCriteria( criteria.out() );
2303 for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
2305 const char* thresholdID = criteria[ iCr ].ThresholdID.in();
2307 switch ( criteria[ iCr ].Type )
2309 case SMESH::FT_BelongToGeom:
2310 case SMESH::FT_BelongToPlane:
2311 case SMESH::FT_BelongToCylinder:
2312 case SMESH::FT_BelongToGenSurface:
2313 case SMESH::FT_LyingOnGeom:
2314 entry = thresholdID;
2316 case SMESH::FT_ConnectedElements:
2319 entry = thresholdID;
2325 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
2326 SALOMEDS::SObject_wrap so = gen->getStudyServant()->FindObjectID( entry.c_str() );
2327 if ( so->_is_nil() )
2329 CORBA::Object_var obj = so->GetObject();
2330 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj );
2331 if ( gen->GeomObjectToShape( geom ).IsNull() )
2334 } // loop on criteria
2340 //=============================================================================
2342 * \brief Update data if geometry changes
2346 //=============================================================================
2348 void SMESH_Mesh_i::CheckGeomModif( bool theIsBreakLink )
2350 SMESH::SMESH_Mesh_var me = _this();
2351 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2353 TPythonDump dumpNothing; // prevent any dump
2355 //bool removedFromClient = false;
2357 if ( mainGO->_is_nil() ) // GEOM_Client cleared or geometry removed? (IPAL52735, PAL23636)
2359 //removedFromClient = _impl->HasShapeToMesh();
2361 // try to find geometry by study reference
2362 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2363 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2364 if ( !meshSO->_is_nil() &&
2365 meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2366 geomRefSO->ReferencedObject( geomSO.inout() ))
2368 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2369 mainGO = GEOM::GEOM_Object::_narrow( geomObj );
2372 if ( mainGO->_is_nil() && // geometry removed ==>
2373 !geomRefSO->_is_nil() ) // remove geom dependent data: sub-meshes etc.
2375 // convert geom dependent groups into standalone ones
2376 CheckGeomGroupModif();
2378 _impl->ShapeToMesh( TopoDS_Shape() );
2380 // remove sub-meshes
2381 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2382 while ( i_sm != _mapSubMeshIor.end() )
2384 SMESH::SMESH_subMesh_ptr sm = i_sm->second;
2386 RemoveSubMesh( sm );
2388 // remove all children except groups in the study
2389 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2390 SALOMEDS::SObject_wrap so;
2391 for ( CORBA::Long tag = SMESH::Tag_RefOnShape; tag <= SMESH::Tag_LastSubMesh; ++tag )
2392 if ( meshSO->FindSubObject( tag, so.inout() ))
2393 builder->RemoveObjectWithChildren( so );
2395 _gen_i->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED" );
2401 if ( !_impl->HasShapeToMesh() ) return;
2404 // Update after group modification
2406 const bool geomChanged = ( mainGO->GetTick() != _mainShapeTick );
2407 if ( !theIsBreakLink )
2408 if ( mainGO->GetType() == GEOM_GROUP || !geomChanged ) // is group or not modified
2410 int nb = NbNodes() + NbElements();
2411 CheckGeomGroupModif();
2412 if ( nb != NbNodes() + NbElements() ) // something removed due to hypotheses change
2413 _gen_i->UpdateIcons( me );
2417 // Update after shape modification or breakLink w/o geometry change
2419 GEOM_Client* geomClient = _gen_i->GetShapeReader();
2420 if ( !geomClient ) return;
2421 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( mainGO );
2422 if ( geomGen->_is_nil() ) return;
2423 CORBA::String_var geomComponentType = geomGen->ComponentDataType();
2424 bool isShaper = ( strcmp( geomComponentType.in(), "SHAPERSTUDY" ) == 0 );
2426 SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
2428 TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
2429 if ( meshDS->ShapeToIndex( newShape ) == 1 ) // not yet updated
2431 CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
2432 geomClient->RemoveShapeFromBuffer( ior.in() );
2433 newShape = _gen_i->GeomObjectToShape( mainGO );
2436 // Update data taking into account that if topology doesn't change
2437 // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
2440 _preMeshInfo->ForgetAllData();
2442 if ( geomChanged || !isShaper )
2444 if ( newShape.IsNull() )
2447 _mainShapeTick = mainGO->GetTick();
2449 // store data of groups on geometry including new TopoDS_Shape's
2450 std::vector< TGroupOnGeomData > groupsData;
2451 const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2452 groupsData.reserve( groups.size() );
2453 TopTools_DataMapOfShapeShape old2newShapeMap;
2454 std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2455 for ( ; g != groups.end(); ++g )
2457 if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
2459 groupsData.push_back( TGroupOnGeomData( group ));
2462 SMESH::SMESH_GroupOnGeom_var gog;
2463 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.find( group->GetID() );
2464 if ( i_grp != _mapGroups.end() )
2465 gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second );
2467 GEOM::GEOM_Object_var geom;
2468 if ( !gog->_is_nil() )
2470 if ( !theIsBreakLink )
2471 geom = gog->GetShape();
2473 if ( theIsBreakLink || geom->_is_nil() )
2475 SALOMEDS::SObject_wrap grpSO = _gen_i->ObjectToSObject( gog );
2476 SALOMEDS::SObject_wrap geomRefSO, geomSO;
2477 if ( !grpSO->_is_nil() &&
2478 grpSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2479 geomRefSO->ReferencedObject( geomSO.inout() ))
2481 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2482 geom = GEOM::GEOM_Object::_narrow( geomObj );
2486 if ( old2newShapeMap.IsBound( group->GetShape() ))
2488 groupsData.back()._shape = old2newShapeMap( group->GetShape() );
2490 else if ( !geom->_is_nil() )
2492 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2493 if ( meshDS->IsGroupOfSubShapes( groupsData.back()._shape ))
2495 CORBA::String_var ior = geomGen->GetStringFromIOR( geom );
2496 geomClient->RemoveShapeFromBuffer( ior.in() );
2497 groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2499 old2newShapeMap.Bind( group->GetShape(), groupsData.back()._shape );
2504 // store assigned hypotheses
2505 std::vector< pair< int, THypList > > ids2Hyps;
2506 const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
2507 for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
2509 const TopoDS_Shape& s = s2hyps.Key();
2510 const THypList& hyps = s2hyps.ChangeValue();
2511 ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
2514 std::multimap< std::set<int>, int > ii2iMap; // group sub-ids to group id in SMESHDS
2516 // count shapes excluding compounds corresponding to geom groups
2517 int oldNbSubShapes = meshDS->MaxShapeIndex();
2518 for ( ; oldNbSubShapes > 0; --oldNbSubShapes )
2520 const TopoDS_Shape& s = meshDS->IndexToShape( oldNbSubShapes );
2521 if ( s.IsNull() || s.ShapeType() != TopAbs_COMPOUND )
2524 std::set<int> subIds;
2525 for ( TopoDS_Iterator it( s ); it.More(); it.Next() )
2526 subIds.insert( meshDS->ShapeToIndex( it.Value() ));
2527 ii2iMap.insert( std::make_pair( subIds, oldNbSubShapes ));
2530 // check if shape topology changes - save shape type per shape ID
2531 std::vector< TopAbs_ShapeEnum > shapeTypes( Max( oldNbSubShapes + 1, 1 ));
2532 for ( int shapeID = oldNbSubShapes; shapeID > 0; --shapeID )
2533 shapeTypes[ shapeID ] = meshDS->IndexToShape( shapeID ).ShapeType();
2535 // change shape to mesh
2536 _impl->ShapeToMesh( TopoDS_Shape() );
2537 _impl->ShapeToMesh( newShape );
2539 // check if shape topology changes - check new shape types
2540 bool sameTopology = ( oldNbSubShapes == meshDS->MaxShapeIndex() );
2541 for ( int shapeID = oldNbSubShapes; shapeID > 0 && sameTopology; --shapeID )
2543 const TopoDS_Shape& s = meshDS->IndexToShape( shapeID );
2544 sameTopology = ( !s.IsNull() && s.ShapeType() == shapeTypes[ shapeID ]);
2547 // re-add shapes (compounds) of geom groups
2548 typedef std::map< std::vector< int >, TGeomGroupData* > TIndices2GroupData;
2549 TIndices2GroupData ii2grData;
2550 std::vector< int > ii;
2551 std::map< int, int > old2newIDs; // group IDs
2552 std::list<TGeomGroupData>::iterator dataIt = _geomGroupData.begin();
2553 for ( ; dataIt != _geomGroupData.end(); ++dataIt )
2555 TGeomGroupData* data = &(*dataIt);
2556 ii.reserve( data->_indices.size() );
2557 ii.assign( data->_indices.begin(), data->_indices.end() );
2558 TIndices2GroupData::iterator ii2gd = ii2grData.insert( std::make_pair( ii, data )).first;
2559 if ( ii2gd->second != data )
2561 data->_groupEntry = ii2gd->second->_groupEntry;
2562 data->_indices = ii2gd->second->_indices;
2565 const int oldNbSub = data->_indices.size();
2566 const int soleOldID = oldNbSub == 1 ? *data->_indices.begin() : 0;
2568 std::multimap< std::set<int>, int >::iterator ii2i = ii2iMap.find( data->_indices );
2569 if ( ii2i != ii2iMap.end() )
2571 oldID = ii2i->second;
2572 ii2iMap.erase( ii2i );
2574 if ( !oldID && oldNbSub == 1 )
2576 if ( old2newIDs.count( oldID ))
2579 int how = ( theIsBreakLink || !sameTopology ) ? IS_BREAK_LINK : MAIN_TRANSFORMED;
2580 newShape = newGroupShape( *data, how );
2582 if ( !newShape.IsNull() )
2584 if ( oldNbSub > 1 && meshDS->ShapeToIndex( newShape ) > 0 ) // group reduced to one sub-shape
2586 TopoDS_Compound compound;
2587 BRep_Builder().MakeCompound( compound );
2588 BRep_Builder().Add( compound, newShape );
2589 newShape = compound;
2591 int newID = _impl->GetSubMesh( newShape )->GetId();
2592 if ( oldID /*&& oldID != newID*/ )
2593 old2newIDs.insert( std::make_pair( oldID, newID ));
2594 if ( oldNbSub == 1 )
2595 old2newIDs.insert( std::make_pair( soleOldID, newID ));
2599 // re-assign hypotheses
2600 for ( size_t i = 0; i < ids2Hyps.size(); ++i )
2602 int sID = ids2Hyps[i].first;
2605 std::map< int, int >::iterator o2n = old2newIDs.find( sID );
2606 if ( o2n != old2newIDs.end() )
2608 else if ( !sameTopology )
2611 const TopoDS_Shape& s = meshDS->IndexToShape( sID );
2614 const THypList& hyps = ids2Hyps[i].second;
2615 THypList::const_iterator h = hyps.begin();
2616 for ( ; h != hyps.end(); ++h )
2617 _impl->AddHypothesis( s, (*h)->GetID() );
2621 // restore groups on geometry
2622 for ( size_t i = 0; i < groupsData.size(); ++i )
2624 const TGroupOnGeomData& data = groupsData[i];
2625 if ( data._shape.IsNull() )
2628 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
2629 if ( i2g == _mapGroups.end() ) continue;
2631 SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
2632 if ( !gr_i ) continue;
2634 SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape );
2636 _mapGroups.erase( i2g );
2638 g->GetGroupDS()->SetColor( data._color );
2641 if ( !sameTopology )
2643 std::map< int, int >::iterator o2n = old2newIDs.begin();
2644 for ( ; o2n != old2newIDs.end(); ++o2n )
2646 int newID = o2n->second, oldID = o2n->first;
2647 if ( newID == oldID || !_mapSubMesh.count( oldID ))
2651 _mapSubMesh [ newID ] = _impl->GetSubMeshContaining( newID );
2652 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2653 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2655 _mapSubMesh. erase(oldID);
2656 _mapSubMesh_i. erase(oldID);
2657 _mapSubMeshIor.erase(oldID);
2659 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2663 // update _mapSubMesh
2664 std::map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
2665 for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
2666 i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
2669 if ( !sameTopology )
2671 // remove invalid study sub-objects
2672 CheckGeomGroupModif();
2675 _gen_i->UpdateIcons( me );
2677 if ( !theIsBreakLink && isShaper )
2679 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2680 if ( !meshSO->_is_nil() )
2681 _gen_i->SetPixMap(meshSO, "ICON_SMESH_TREE_GEOM_MODIF");
2685 //=============================================================================
2687 * \brief Update objects depending on changed geom groups
2689 * NPAL16168: geometrical group edition from a submesh don't modify mesh computation
2690 * issue 0020210: Update of a smesh group after modification of the associated geom group
2692 //=============================================================================
2694 void SMESH_Mesh_i::CheckGeomGroupModif()
2696 // remove sub-meshes referring a removed sub-shapes (if main shape still exists)
2697 SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2698 GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2699 SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() ));
2700 if ( !mainGO->_is_nil() && !meshSO->_is_nil() )
2702 SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO;
2703 for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag )
2704 if ( meshSO->FindSubObject( tag, rootSO.inout() ))
2706 int nbValid = 0, nbRemoved = 0;
2707 SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO );
2708 for ( ; chItr->More(); chItr->Next() )
2710 SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO
2711 if ( !smSO->_is_nil() &&
2712 smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2713 geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference
2715 CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2716 GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj );
2717 if ( !geom->_non_existent() )
2720 continue; // keep the sub-mesh
2723 CORBA::Object_var smObj = _gen_i->SObjectToObject( smSO );
2724 SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj );
2725 if ( !sm->_is_nil() && !sm->_non_existent() )
2727 GEOM::GEOM_Object_var smGeom = sm->GetSubShape();
2728 if ( smGeom->_is_nil() )
2730 RemoveSubMesh( sm );
2737 _preMeshInfo->ForgetAllData(); // unknown hypothesis modified
2738 builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH
2742 if ( /*nbRemoved > 0 &&*/ nbValid == 0 )
2743 builder->RemoveObjectWithChildren( rootSO );
2747 // check for removed sub-shapes and convert geom dependent groups into standalone ones
2748 std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2749 while ( i_gr != _mapGroups.end())
2751 SMESH::SMESH_GroupBase_ptr group = i_gr->second;
2753 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( group ), refSO, geomSO;
2754 SMESH::SMESH_GroupOnGeom_var onGeom = SMESH::SMESH_GroupOnGeom::_narrow ( group );
2755 SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group );
2756 bool isValidGeom = false;
2757 if ( !onGeom->_is_nil() )
2759 isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() ); // check TopoDS
2760 if ( !isValidGeom ) // check reference
2762 isValidGeom = ( ! groupSO->_is_nil() &&
2763 groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ) &&
2764 refSO->ReferencedObject( geomSO.inout() ) &&
2765 ! geomSO->_is_nil() &&
2766 !CORBA::is_nil( CORBA::Object_var( geomSO->GetObject() )));
2769 else if ( !onFilt->_is_nil() )
2771 isValidGeom = isValidGeomFilter( onFilt->GetFilter() );
2775 isValidGeom = ( !groupSO->_is_nil() &&
2776 !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ));
2780 if ( !IsLoaded() || group->IsEmpty() )
2782 RemoveGroup( group );
2784 else if ( !onGeom->_is_nil() || !onFilt->_is_nil() )
2786 SMESH::SMESH_Group_var ( ConvertToStandalone( group ));
2788 else // is it possible?
2790 builder->RemoveObjectWithChildren( refSO );
2796 if ( !_impl->HasShapeToMesh() ) return;
2798 CORBA::Long nbEntities = NbNodes() + NbElements();
2800 // Check if group contents changed
2802 typedef map< string, TopoDS_Shape > TEntry2Geom;
2803 TEntry2Geom newGroupContents;
2805 list<TGeomGroupData>::iterator
2806 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2807 for ( ; data != dataEnd; ++data )
2809 pair< TEntry2Geom::iterator, bool > it_new =
2810 newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
2811 bool processedGroup = !it_new.second;
2812 TopoDS_Shape& newShape = it_new.first->second;
2813 if ( !processedGroup )
2814 newShape = newGroupShape( *data, ONLY_IF_CHANGED );
2815 if ( newShape.IsNull() )
2816 continue; // no changes
2819 _preMeshInfo->ForgetOrLoad();
2821 if ( processedGroup ) { // update group indices
2822 list<TGeomGroupData>::iterator data2 = data;
2823 for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
2824 data->_indices = data2->_indices;
2827 // Update SMESH objects according to new GEOM group contents
2829 SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2830 if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2832 int oldID = submesh->GetId();
2833 if ( !_mapSubMeshIor.count( oldID ))
2835 TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2837 // update hypotheses
2838 list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2839 list <const SMESHDS_Hypothesis * >::iterator hypIt;
2840 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2842 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2843 _impl->AddHypothesis ( newShape, (*hypIt)->GetID());
2845 // care of submeshes
2846 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2847 int newID = newSubmesh->GetId();
2848 if ( newID != oldID ) {
2849 _mapSubMesh [ newID ] = newSubmesh;
2850 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2851 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2852 _mapSubMesh. erase(oldID);
2853 _mapSubMesh_i. erase(oldID);
2854 _mapSubMeshIor.erase(oldID);
2855 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2860 SMESH::SMESH_GroupOnGeom_var smeshGroup =
2861 SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2862 if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2864 SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2866 ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2867 SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2868 ds->SetShape( newShape );
2873 SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2874 if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2876 // Remove groups and submeshes basing on removed sub-shapes
2878 TopTools_MapOfShape newShapeMap;
2879 TopoDS_Iterator shapeIt( newShape );
2880 for ( ; shapeIt.More(); shapeIt.Next() )
2881 newShapeMap.Add( shapeIt.Value() );
2883 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2884 for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2886 if ( newShapeMap.Contains( shapeIt.Value() ))
2888 TopTools_IndexedMapOfShape oldShapeMap;
2889 TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2890 for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2892 const TopoDS_Shape& oldShape = oldShapeMap(i);
2893 int oldInd = meshDS->ShapeToIndex( oldShape );
2895 map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2896 if ( i_smIor != _mapSubMeshIor.end() ) {
2897 RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2900 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2901 for ( ; i_grp != _mapGroups.end(); ++i_grp )
2903 // check if a group bases on oldInd shape
2904 SMESHDS_GroupOnGeom* grpOnGeom = 0;
2905 if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2906 grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2907 if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2909 RemoveGroup( i_grp->second ); // several groups can base on same shape
2910 i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2915 // Reassign hypotheses and update groups after setting the new shape to mesh
2917 // collect anassigned hypotheses
2918 typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2919 list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2920 TShapeHypList assignedHyps;
2921 for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2923 const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2924 list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2925 if ( !hyps.empty() ) {
2926 assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2927 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2928 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2931 // collect shapes supporting groups
2932 typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2933 TShapeTypeList groupData;
2934 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2935 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2936 for ( ; grIt != groups.end(); ++grIt )
2938 if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2940 ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2942 // set new shape to mesh -> DS of sub-meshes and geom groups is deleted
2944 _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
2945 _impl->ShapeToMesh( newShape );
2947 // reassign hypotheses
2948 TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2949 for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2951 TIndexedShape& geom = indS_hyps->first;
2952 list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2953 int oldID = geom._index;
2954 int newID = meshDS->ShapeToIndex( geom._shape );
2955 if ( oldID == 1 ) { // main shape
2957 geom._shape = newShape;
2961 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2962 _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2963 // care of sub-meshes
2964 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2965 if ( newID != oldID ) {
2966 _mapSubMesh [ newID ] = newSubmesh;
2967 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2968 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2969 _mapSubMesh. erase(oldID);
2970 _mapSubMesh_i. erase(oldID);
2971 _mapSubMeshIor.erase(oldID);
2972 _mapSubMesh_i [ newID ]->changeLocalId( newID );
2976 TShapeTypeList::iterator geomType = groupData.begin();
2977 for ( ; geomType != groupData.end(); ++geomType )
2979 const TIndexedShape& geom = geomType->first;
2980 int oldID = geom._index;
2981 if ( _mapGroups.find( oldID ) == _mapGroups.end() )
2984 SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( _mapGroups[oldID] );
2985 CORBA::String_var name = groupSO->GetName();
2987 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID]))
2988 if ( SMESH_Group* group = _impl->AddGroup( geomType->second, name.in(),
2989 /*id=*/-1, geom._shape ))
2990 group_i->changeLocalId( group->GetID() );
2993 break; // everything has been updated
2996 } // loop on group data
3000 CORBA::Long newNbEntities = NbNodes() + NbElements();
3001 list< SALOMEDS::SObject_wrap > soToUpdateIcons;
3002 if ( newNbEntities != nbEntities )
3004 // Add all SObjects with icons to soToUpdateIcons
3005 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( _this() )); // mesh
3007 for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
3008 i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
3009 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_sm->second ));
3011 for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
3012 i_gr != _mapGroups.end(); ++i_gr ) // groups
3013 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_gr->second ));
3016 list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
3017 for ( ; so != soToUpdateIcons.end(); ++so )
3018 _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
3021 //=============================================================================
3023 * \brief Create standalone group from a group on geometry or filter
3025 //=============================================================================
3027 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
3029 SMESH::SMESH_Group_var aGroup;
3034 _preMeshInfo->FullLoadFromFile();
3036 if ( theGroup->_is_nil() )
3037 return aGroup._retn();
3039 SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
3041 return aGroup._retn();
3043 const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
3045 const int anId = aGroupToRem->GetLocalID();
3046 if ( !_impl->ConvertToStandalone( anId ) )
3047 return aGroup._retn();
3048 removeGeomGroupData( theGroup );
3050 SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3052 // remove old instance of group from own map
3053 { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
3054 _mapGroups.erase( anId );
3056 SALOMEDS::StudyBuilder_var builder;
3057 SALOMEDS::SObject_wrap aGroupSO;
3058 SALOMEDS::Study_var aStudy = SMESH_Gen_i::getStudyServant();
3059 if ( !aStudy->_is_nil() ) {
3060 builder = aStudy->NewBuilder();
3061 aGroupSO = _gen_i->ObjectToSObject( theGroup );
3062 if ( !aGroupSO->_is_nil() )
3064 // remove reference to geometry
3065 SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
3066 for ( ; chItr->More(); chItr->Next() )
3068 // Remove group's child SObject
3069 SALOMEDS::SObject_wrap so = chItr->Value();
3070 builder->RemoveObject( so );
3072 // Update Python script
3073 TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
3074 << ".ConvertToStandalone( " << aGroupSO << " )";
3076 // change icon of Group on Filter
3079 // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
3080 // const int isEmpty = ( elemTypes->length() == 0 );
3083 SALOMEDS::GenericAttribute_wrap anAttr =
3084 builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
3085 SALOMEDS::AttributePixMap_wrap pm = anAttr;
3086 pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
3092 // remember new group in own map
3093 aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
3094 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3096 // register CORBA object for persistence
3097 _gen_i->RegisterObject( aGroup );
3099 CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
3100 builder->SetIOR( aGroupSO, ior.in() ); // == aGroup->Register();
3101 //aGroup->Register();
3102 aGroupToRem->UnRegister();
3104 SMESH_CATCH( SMESH::throwCorbaException );
3106 return aGroup._retn();
3109 //================================================================================
3111 * \brief Create a sub-mesh on a given sub-shape
3113 //================================================================================
3115 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
3117 if(MYDEBUG) MESSAGE( "createSubMesh" );
3118 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
3119 ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
3122 SMESH_subMesh_i * subMeshServant;
3125 subMeshId = mySubMesh->GetId();
3126 subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
3128 else // "invalid sub-mesh"
3130 // The invalid sub-mesh is created for the case where a valid sub-shape not found
3131 // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0.
3132 if ( _mapSubMesh.empty() )
3135 subMeshId = _mapSubMesh.begin()->first - 1;
3136 subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject);
3139 SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
3141 _mapSubMesh [subMeshId] = mySubMesh;
3142 _mapSubMesh_i [subMeshId] = subMeshServant;
3143 _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
3145 subMeshServant->Register();
3147 // register CORBA object for persistence
3148 int nextId = _gen_i->RegisterObject( subMesh );
3149 if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
3150 else { (void)nextId; } // avoid "unused variable" warning
3152 // to track changes of GEOM groups
3153 if ( subMeshId > 0 )
3154 addGeomGroupData( theSubShapeObject, subMesh );
3156 return subMesh._retn();
3159 //================================================================================
3161 * \brief Return an existing sub-mesh based on a sub-shape with the given ID
3163 //================================================================================
3165 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
3167 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
3168 if ( it == _mapSubMeshIor.end() )
3169 return SMESH::SMESH_subMesh::_nil();
3171 return SMESH::SMESH_subMesh::_duplicate( (*it).second );
3174 //================================================================================
3176 * \brief Remove a sub-mesh based on the given sub-shape
3178 //================================================================================
3180 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
3181 GEOM::GEOM_Object_ptr theSubShapeObject )
3183 bool isHypChanged = false;
3184 if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
3185 return isHypChanged;
3187 const int subMeshId = theSubMesh->GetId();
3189 if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
3192 if (( _mapSubMesh.count( subMeshId )) &&
3193 ( sm = _impl->GetSubMeshContaining( subMeshId )))
3195 TopoDS_Shape S = sm->GetSubShape();
3198 list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
3199 isHypChanged = !hyps.empty();
3200 if ( isHypChanged && _preMeshInfo )
3201 _preMeshInfo->ForgetOrLoad();
3202 list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
3203 for ( ; hyp != hyps.end(); ++hyp )
3204 _impl->RemoveHypothesis(S, (*hyp)->GetID());
3211 SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
3212 isHypChanged = ( aHypList->length() > 0 );
3213 for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
3214 removeHypothesis( theSubShapeObject, aHypList[i] );
3217 catch( const SALOME::SALOME_Exception& ) {
3218 INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
3220 removeGeomGroupData( theSubShapeObject );
3224 std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
3225 if ( id_smi != _mapSubMesh_i.end() )
3226 id_smi->second->UnRegister();
3228 // remove a CORBA object
3229 std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
3230 if ( id_smptr != _mapSubMeshIor.end() )
3231 SMESH::SMESH_subMesh_var( id_smptr->second );
3233 _mapSubMesh.erase(subMeshId);
3234 _mapSubMesh_i.erase(subMeshId);
3235 _mapSubMeshIor.erase(subMeshId);
3237 return isHypChanged;
3240 //================================================================================
3242 * \brief Create a group. Group type depends on given arguments
3244 //================================================================================
3246 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
3247 const char* theName,
3249 const TopoDS_Shape& theShape,
3250 const SMESH_PredicatePtr& thePredicate )
3252 std::string newName;
3253 if ( !theName || !theName[0] )
3255 std::set< std::string > presentNames;
3256 std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
3257 for ( ; i_gr != _mapGroups.end(); ++i_gr )
3259 CORBA::String_var name = i_gr->second->GetName();
3260 presentNames.insert( name.in() );
3263 newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
3264 } while ( !presentNames.insert( newName ).second );
3265 theName = newName.c_str();
3267 SMESH::SMESH_GroupBase_var aGroup;
3268 if ( SMESH_Group* g = _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName,
3269 theID, theShape, thePredicate ))
3271 int anId = g->GetID();
3272 SMESH_GroupBase_i* aGroupImpl;
3273 if ( !theShape.IsNull() )
3274 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3275 else if ( thePredicate )
3276 aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
3278 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3280 aGroup = aGroupImpl->_this();
3281 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
3282 aGroupImpl->Register();
3284 // register CORBA object for persistence
3285 int nextId = _gen_i->RegisterObject( aGroup );
3286 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
3287 else { nextId = ( nextId > 0 ); } // avoid "unused variable" warning in release mode
3289 // to track changes of GEOM groups
3290 if ( !theShape.IsNull() ) {
3291 GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
3292 addGeomGroupData( geom, aGroup );
3295 return aGroup._retn();
3298 //=============================================================================
3300 * SMESH_Mesh_i::removeGroup
3302 * Should be called by ~SMESH_Group_i()
3304 //=============================================================================
3306 void SMESH_Mesh_i::removeGroup( const int theId )
3308 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
3309 if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
3310 SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
3311 _mapGroups.erase( theId );
3312 removeGeomGroupData( group );
3313 if ( !_impl->RemoveGroup( theId ))
3315 // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
3316 RemoveGroup( group );
3318 group->UnRegister();
3322 //================================================================================
3324 * \brief Return a log that can be used to move another mesh to the same state as this one
3326 //================================================================================
3328 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
3330 SMESH::log_array_var aLog;
3334 _preMeshInfo->FullLoadFromFile();
3336 list < SMESHDS_Command * >logDS = _impl->GetLog();
3337 aLog = new SMESH::log_array;
3339 int lg = logDS.size();
3341 list < SMESHDS_Command * >::iterator its = logDS.begin();
3342 while(its != logDS.end()){
3343 SMESHDS_Command *com = *its;
3344 int comType = com->GetType();
3345 int lgcom = com->GetNumber();
3346 const list < int >&intList = com->GetIndexes();
3347 int inum = intList.size();
3348 list < int >::const_iterator ii = intList.begin();
3349 const list < double >&coordList = com->GetCoords();
3350 int rnum = coordList.size();
3351 list < double >::const_iterator ir = coordList.begin();
3352 aLog[indexLog].commandType = comType;
3353 aLog[indexLog].number = lgcom;
3354 aLog[indexLog].coords.length(rnum);
3355 aLog[indexLog].indexes.length(inum);
3356 for(int i = 0; i < rnum; i++){
3357 aLog[indexLog].coords[i] = *ir;
3360 for(int i = 0; i < inum; i++){
3361 aLog[indexLog].indexes[i] = *ii;
3370 SMESH_CATCH( SMESH::throwCorbaException );
3372 return aLog._retn();
3375 //================================================================================
3377 * \brief Remove the log of commands
3379 //================================================================================
3381 void SMESH_Mesh_i::ClearLog()
3385 SMESH_CATCH( SMESH::throwCorbaException );
3388 //================================================================================
3390 * \brief Return a mesh ID
3392 //================================================================================
3394 CORBA::Long SMESH_Mesh_i::GetId()
3399 //=============================================================================
3402 //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
3403 // issue 0020918: groups removal is caused by hyp modification
3404 // issue 0021208: to forget not loaded mesh data at hyp modification
3405 struct TCallUp_i : public SMESH_Mesh::TCallUp
3407 SMESH_Mesh_i* _mesh;
3408 TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
3409 void RemoveGroup (const int theGroupID) override { _mesh->removeGroup( theGroupID ); }
3410 void HypothesisModified( int hypID,
3411 bool updIcons) override { _mesh->onHypothesisModified( hypID,
3413 void Load () override { _mesh->Load(); }
3414 bool IsLoaded() override { return _mesh->IsLoaded(); }
3415 TopoDS_Shape GetShapeByEntry(const std::string& entry) override
3417 GEOM::GEOM_Object_var go = SMESH_Gen_i::GetGeomObjectByEntry( entry );
3418 return SMESH_Gen_i::GeomObjectToShape( go );
3423 //================================================================================
3425 * \brief callback from _impl to
3426 * 1) forget not loaded mesh data (issue 0021208)
3427 * 2) mark hypothesis as valid
3429 //================================================================================
3431 void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons)
3434 _preMeshInfo->ForgetOrLoad();
3436 if ( theUpdateIcons )
3438 SMESH::SMESH_Mesh_var mesh = _this();
3439 _gen_i->UpdateIcons( mesh );
3442 if ( _nbInvalidHypos != 0 )
3444 // mark a hypothesis as valid after edition
3446 SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
3447 SALOMEDS::SObject_wrap hypRoot;
3448 if ( !smeshComp->_is_nil() &&
3449 smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
3451 SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
3452 for ( ; anIter->More(); anIter->Next() )
3454 SALOMEDS::SObject_wrap hypSO = anIter->Value();
3455 CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO );
3456 SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
3457 if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
3458 _gen_i->HighLightInvalid( hyp, false );
3460 nbInvalid += _gen_i->IsInvalid( hypSO );
3463 _nbInvalidHypos = nbInvalid;
3467 //================================================================================
3469 * \brief Set mesh implementation
3471 //================================================================================
3473 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
3475 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
3478 _impl->SetCallUp( new TCallUp_i(this));
3481 //=============================================================================
3483 * Return a mesh implementation
3485 //=============================================================================
3487 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
3489 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
3493 //=============================================================================
3495 * Return mesh editor
3497 //=============================================================================
3499 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
3501 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3505 _preMeshInfo->FullLoadFromFile();
3507 // Create MeshEditor
3509 _editor = new SMESH_MeshEditor_i( this, false );
3510 aMeshEdVar = _editor->_this();
3512 // Update Python script
3513 TPythonDump() << _editor << " = "
3514 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
3516 SMESH_CATCH( SMESH::throwCorbaException );
3518 return aMeshEdVar._retn();
3521 //=============================================================================
3523 * Return mesh edition previewer
3525 //=============================================================================
3527 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
3529 SMESH::SMESH_MeshEditor_var aMeshEdVar;
3533 _preMeshInfo->FullLoadFromFile();
3535 if ( !_previewEditor )
3536 _previewEditor = new SMESH_MeshEditor_i( this, true );
3537 aMeshEdVar = _previewEditor->_this();
3539 SMESH_CATCH( SMESH::throwCorbaException );
3541 return aMeshEdVar._retn();
3544 //================================================================================
3546 * \brief Return true if the mesh has been edited since a last total re-compute
3547 * and those modifications may prevent successful partial re-compute
3549 //================================================================================
3551 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard()
3553 Unexpect aCatch(SALOME_SalomeException);
3554 return _impl->HasModificationsToDiscard();
3557 //================================================================================
3559 * \brief Return a random unique color
3561 //================================================================================
3563 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
3565 const int MAX_ATTEMPTS = 100;
3567 double tolerance = 0.5;
3568 SALOMEDS::Color col;
3572 // generate random color
3573 double red = (double)rand() / RAND_MAX;
3574 double green = (double)rand() / RAND_MAX;
3575 double blue = (double)rand() / RAND_MAX;
3576 // check existence in the list of the existing colors
3577 bool matched = false;
3578 std::list<SALOMEDS::Color>::const_iterator it;
3579 for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
3580 SALOMEDS::Color color = *it;
3581 double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B - blue );
3582 matched = tol < tolerance;
3584 if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
3585 ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
3593 //=============================================================================
3595 * Set auto-color mode. If it is on, groups get unique random colors
3597 //=============================================================================
3599 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor)
3601 Unexpect aCatch(SALOME_SalomeException);
3602 _impl->SetAutoColor(theAutoColor);
3604 TPythonDump pyDump; // not to dump group->SetColor() from below code
3605 pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
3607 std::list<SALOMEDS::Color> aReservedColors;
3608 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
3609 for ( ; it != _mapGroups.end(); it++ ) {
3610 if ( CORBA::is_nil( it->second )) continue;
3611 SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
3612 it->second->SetColor( aColor );
3613 aReservedColors.push_back( aColor );
3617 //=============================================================================
3619 * Return true if auto-color mode is on
3621 //=============================================================================
3623 CORBA::Boolean SMESH_Mesh_i::GetAutoColor()
3625 Unexpect aCatch(SALOME_SalomeException);
3626 return _impl->GetAutoColor();
3629 //=============================================================================
3631 * Check if there are groups with equal names
3633 //=============================================================================
3635 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
3637 return _impl->HasDuplicatedGroupNamesMED();
3640 //================================================================================
3642 * \brief Care of a file before exporting mesh into it
3644 //================================================================================
3646 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
3648 SMESH_File aFile( file, false );
3650 if ( aFile.exists() ) {
3651 // existing filesystem node
3652 if ( !aFile.isDirectory() ) {
3653 if ( aFile.openForWriting() ) {
3654 if ( overwrite && ! aFile.remove()) {
3655 msg << "Can't replace " << aFile.getName();
3658 msg << "Can't write into " << aFile.getName();
3661 msg << "Location " << aFile.getName() << " is not a file";
3665 // nonexisting file; check if it can be created
3666 if ( !aFile.openForWriting() ) {
3667 msg << "You cannot create the file "
3669 << ". Check the directory existence and access rights";
3677 THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
3681 //================================================================================
3683 * \brief Prepare a file for export and pass names of mesh groups from study to mesh DS
3684 * \param file - file name
3685 * \param overwrite - to erase the file or not
3686 * \retval string - mesh name
3688 //================================================================================
3690 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char* file,
3691 CORBA::Boolean overwrite)
3694 PrepareForWriting(file, overwrite);
3695 string aMeshName = "Mesh";
3696 SALOMEDS::Study_var aStudy = SMESH_Gen_i::getStudyServant();
3697 if ( !aStudy->_is_nil() ) {
3698 SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( _this() );
3699 if ( !aMeshSO->_is_nil() ) {
3700 CORBA::String_var name = aMeshSO->GetName();
3702 // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
3703 if ( !aStudy->GetProperties()->IsLocked() )
3705 SALOMEDS::GenericAttribute_wrap anAttr;
3706 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3707 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
3708 SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
3709 ASSERT(!aFileName->_is_nil());
3710 aFileName->SetValue(file);
3711 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
3712 SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
3713 ASSERT(!aFileType->_is_nil());
3714 aFileType->SetValue("FICHIERMED");
3718 // Update Python script
3719 // set name of mesh before export
3720 TPythonDump() << _gen_i << ".SetName("
3721 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
3723 // check names of groups
3729 //================================================================================
3731 * \brief Export to MED file
3733 //================================================================================
3735 void SMESH_Mesh_i::ExportMED(const char* file,
3736 CORBA::Boolean auto_groups,
3737 CORBA::Long version,
3738 CORBA::Boolean overwrite,
3739 CORBA::Boolean autoDimension)
3741 //MESSAGE("MED minor version: "<< minor);
3744 _preMeshInfo->FullLoadFromFile();
3746 string aMeshName = prepareMeshNameAndGroups(file, overwrite);
3747 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, 0, autoDimension );
3749 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportMED( r'"
3751 << "auto_groups=" <<auto_groups << ", "
3752 << "version=" << version << ", "
3753 << "overwrite=" << overwrite << ", "
3754 << "meshPart=None, "
3755 << "autoDimension=" << autoDimension << " )";
3757 SMESH_CATCH( SMESH::throwCorbaException );
3760 //================================================================================
3762 * \brief Export a mesh to a SAUV file
3764 //================================================================================
3766 void SMESH_Mesh_i::ExportSAUV (const char* file,
3767 CORBA::Boolean auto_groups)
3769 Unexpect aCatch(SALOME_SalomeException);
3771 _preMeshInfo->FullLoadFromFile();
3773 string aMeshName = prepareMeshNameAndGroups(file, true);
3774 TPythonDump() << SMESH::SMESH_Mesh_var( _this())
3775 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
3776 _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
3780 //================================================================================
3782 * \brief Export a mesh to a DAT file
3784 //================================================================================
3786 void SMESH_Mesh_i::ExportDAT (const char *file)
3788 Unexpect aCatch(SALOME_SalomeException);
3790 _preMeshInfo->FullLoadFromFile();
3792 // Update Python script
3793 // check names of groups
3795 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
3798 PrepareForWriting(file);
3799 _impl->ExportDAT(file);
3802 //================================================================================
3804 * \brief Export a mesh to an UNV file
3806 //================================================================================
3808 void SMESH_Mesh_i::ExportUNV (const char *file)
3810 Unexpect aCatch(SALOME_SalomeException);
3812 _preMeshInfo->FullLoadFromFile();
3814 // Update Python script
3815 // check names of groups
3817 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
3820 PrepareForWriting(file);
3821 _impl->ExportUNV(file);
3824 //================================================================================
3826 * \brief Export a mesh to an STL file
3828 //================================================================================
3830 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3832 Unexpect aCatch(SALOME_SalomeException);
3834 _preMeshInfo->FullLoadFromFile();
3836 // Update Python script
3837 // check names of groups
3839 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3840 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3842 CORBA::String_var name;
3843 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( _this() );
3844 if ( !so->_is_nil() )
3845 name = so->GetName();
3848 PrepareForWriting( file );
3849 _impl->ExportSTL( file, isascii, name.in() );
3852 //================================================================================
3854 * \brief Export a part of mesh to a med file
3856 //================================================================================
3858 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
3860 CORBA::Boolean auto_groups,
3861 CORBA::Long version,
3862 CORBA::Boolean overwrite,
3863 CORBA::Boolean autoDimension,
3864 const GEOM::ListOfFields& fields,
3865 const char* geomAssocFields,
3866 CORBA::Double ZTolerance)
3868 MESSAGE("MED version: "<< version);
3871 _preMeshInfo->FullLoadFromFile();
3874 bool have0dField = false;
3875 if ( fields.length() > 0 )
3877 GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3878 if ( shapeToMesh->_is_nil() )
3879 THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3881 for ( size_t i = 0; i < fields.length(); ++i )
3883 if ( fields[i]->GetDataType() == GEOM::FDT_String )
3884 THROW_SALOME_CORBA_EXCEPTION
3885 ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3886 GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3887 if ( fieldShape->_is_nil() )
3888 THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3889 if ( !fieldShape->IsSame( shapeToMesh ) )
3890 THROW_SALOME_CORBA_EXCEPTION
3891 ( "Field defined not on shape", SALOME::BAD_PARAM);
3892 if ( fields[i]->GetDimension() == 0 )
3895 if ( geomAssocFields )
3896 for ( int i = 0; geomAssocFields[i]; ++i )
3897 switch ( geomAssocFields[i] ) {
3898 case 'v':case 'e':case 'f':case 's': break;
3899 case 'V':case 'E':case 'F':case 'S': break;
3900 default: THROW_SALOME_CORBA_EXCEPTION
3901 ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3905 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3909 string aMeshName = "Mesh";
3910 SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3911 if ( CORBA::is_nil( meshPart ) ||
3912 SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3914 aMeshName = prepareMeshNameAndGroups(file, overwrite);
3915 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3916 0, autoDimension, /*addODOnVertices=*/have0dField,
3918 meshDS = _impl->GetMeshDS();
3923 _preMeshInfo->FullLoadFromFile();
3925 PrepareForWriting(file, overwrite);
3927 SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( meshPart );
3928 if ( !SO->_is_nil() ) {
3929 CORBA::String_var name = SO->GetName();
3933 SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
3934 _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3935 partDS, autoDimension, /*addODOnVertices=*/have0dField, ZTolerance);
3936 meshDS = tmpDSDeleter._obj = partDS;
3941 if ( _impl->HasShapeToMesh() )
3943 DriverMED_W_Field fieldWriter;
3944 fieldWriter.SetFile( file );
3945 fieldWriter.SetMeshName( aMeshName );
3946 fieldWriter.AddODOnVertices( have0dField );
3948 exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3952 GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
3953 goList->length( fields.length() );
3954 for ( size_t i = 0; i < fields.length(); ++i )
3956 GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
3959 TPythonDump() << _this() << ".ExportPartToMED( "
3960 << meshPart << ", r'"
3962 << auto_groups << ", "
3964 << overwrite << ", "
3965 << autoDimension << ", "
3967 << ( geomAssocFields ? geomAssocFields : "" ) << "',"
3968 << TVar( ZTolerance )
3971 SMESH_CATCH( SMESH::throwCorbaException );
3974 //================================================================================
3976 * Write GEOM fields to MED file
3978 //================================================================================
3980 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field& fieldWriter,
3981 SMESHDS_Mesh* meshDS,
3982 const GEOM::ListOfFields& fields,
3983 const char* geomAssocFields)
3985 #define METH "SMESH_Mesh_i::exportMEDFields() "
3987 if (( fields.length() < 1 ) &&
3988 ( !geomAssocFields || !geomAssocFields[0] ))
3991 std::vector< std::vector< double > > dblVals;
3992 std::vector< std::vector< int > > intVals;
3993 std::vector< int > subIdsByDim[ 4 ];
3994 const double noneDblValue = 0.;
3995 const double noneIntValue = 0;
3997 for ( size_t iF = 0; iF < fields.length(); ++iF )
4001 int dim = fields[ iF ]->GetDimension();
4002 SMDSAbs_ElementType elemType;
4003 TopAbs_ShapeEnum shapeType;
4005 case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
4006 case 1: elemType = SMDSAbs_Edge; shapeType = TopAbs_EDGE; break;
4007 case 2: elemType = SMDSAbs_Face; shapeType = TopAbs_FACE; break;
4008 case 3: elemType = SMDSAbs_Volume; shapeType = TopAbs_SOLID; break;
4010 continue; // skip fields on whole shape
4012 GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
4013 if ( dataType == GEOM::FDT_String )
4015 GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
4016 if ( stepIDs->length() < 1 )
4018 GEOM::string_array_var comps = fields[ iF ]->GetComponents();
4019 if ( comps->length() < 1 )
4021 CORBA::String_var name = fields[ iF ]->GetName();
4023 if ( !fieldWriter.Set( meshDS,
4027 /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
4030 for ( size_t iC = 0; iC < comps->length(); ++iC )
4031 fieldWriter.SetCompName( iC, comps[ iC ].in() );
4033 dblVals.resize( comps->length() );
4034 intVals.resize( comps->length() );
4036 // find sub-shape IDs
4038 std::vector< int >& subIds = subIdsByDim[ dim ];
4039 if ( subIds.empty() )
4040 for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
4041 if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
4042 subIds.push_back( id );
4046 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4050 for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
4052 GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
4053 if ( step->_is_nil() )
4056 CORBA::Long stamp = step->GetStamp();
4057 CORBA::Long id = step->GetID();
4058 fieldWriter.SetDtIt( int( stamp ), int( id ));
4060 // fill dblVals or intVals
4061 for ( size_t iC = 0; iC < comps->length(); ++iC )
4062 if ( dataType == GEOM::FDT_Double )
4064 dblVals[ iC ].clear();
4065 dblVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4069 intVals[ iC ].clear();
4070 intVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
4074 case GEOM::FDT_Double:
4076 GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
4077 if ( dblStep->_is_nil() ) continue;
4078 GEOM::ListOfDouble_var vv = dblStep->GetValues();
4079 if ( vv->length() != subIds.size() * comps->length() )
4080 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4081 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4082 for ( size_t iC = 0; iC < comps->length(); ++iC )
4083 dblVals[ iC ][ subIds[ iS ]] = vv[ iV++ ];
4088 GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
4089 if ( intStep->_is_nil() ) continue;
4090 GEOM::ListOfLong_var vv = intStep->GetValues();
4091 if ( vv->length() != subIds.size() * comps->length() )
4092 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4093 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4094 for ( size_t iC = 0; iC < comps->length(); ++iC )
4095 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4098 case GEOM::FDT_Bool:
4100 GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
4101 if ( boolStep->_is_nil() ) continue;
4102 GEOM::short_array_var vv = boolStep->GetValues();
4103 if ( vv->length() != subIds.size() * comps->length() )
4104 THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
4105 for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
4106 for ( size_t iC = 0; iC < comps->length(); ++iC )
4107 intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
4113 // pass values to fieldWriter
4114 elemIt = fieldWriter.GetOrderedElems();
4115 if ( dataType == GEOM::FDT_Double )
4116 while ( elemIt->more() )
4118 const SMDS_MeshElement* e = elemIt->next();
4119 const int shapeID = e->getshapeId();
4120 if ( shapeID < 1 || shapeID >= (int) dblVals[0].size() )
4121 for ( size_t iC = 0; iC < comps->length(); ++iC )
4122 fieldWriter.AddValue( noneDblValue );
4124 for ( size_t iC = 0; iC < comps->length(); ++iC )
4125 fieldWriter.AddValue( dblVals[ iC ][ shapeID ]);
4128 while ( elemIt->more() )
4130 const SMDS_MeshElement* e = elemIt->next();
4131 const int shapeID = e->getshapeId();
4132 if ( shapeID < 1 || shapeID >= (int) intVals[0].size() )
4133 for ( size_t iC = 0; iC < comps->length(); ++iC )
4134 fieldWriter.AddValue( (double) noneIntValue );
4136 for ( size_t iC = 0; iC < comps->length(); ++iC )
4137 fieldWriter.AddValue( (double) intVals[ iC ][ shapeID ]);
4141 fieldWriter.Perform();
4142 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4143 if ( res && res->IsKO() )
4145 if ( res->myComment.empty() )
4146 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4148 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4154 if ( !geomAssocFields || !geomAssocFields[0] )
4157 // write geomAssocFields
4159 std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
4160 shapeDim[ TopAbs_COMPOUND ] = 3;
4161 shapeDim[ TopAbs_COMPSOLID ] = 3;
4162 shapeDim[ TopAbs_SOLID ] = 3;
4163 shapeDim[ TopAbs_SHELL ] = 2;
4164 shapeDim[ TopAbs_FACE ] = 2;
4165 shapeDim[ TopAbs_WIRE ] = 1;
4166 shapeDim[ TopAbs_EDGE ] = 1;
4167 shapeDim[ TopAbs_VERTEX ] = 0;
4168 shapeDim[ TopAbs_SHAPE ] = 3;
4170 for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
4172 std::vector< std::string > compNames;
4173 switch ( geomAssocFields[ iF ]) {
4175 fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
4176 compNames.push_back( "dim" );
4179 fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
4182 fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
4185 fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
4189 compNames.push_back( "id" );
4190 for ( size_t iC = 0; iC < compNames.size(); ++iC )
4191 fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
4193 fieldWriter.SetDtIt( -1, -1 );
4195 SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
4199 if ( compNames.size() == 2 ) // _vertices_
4200 while ( elemIt->more() )
4202 const SMDS_MeshElement* e = elemIt->next();
4203 const int shapeID = e->getshapeId();
4206 fieldWriter.AddValue( (double) -1 );
4207 fieldWriter.AddValue( (double) -1 );
4211 const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
4212 fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
4213 fieldWriter.AddValue( (double) shapeID );
4217 while ( elemIt->more() )
4219 const SMDS_MeshElement* e = elemIt->next();
4220 const int shapeID = e->getshapeId();
4222 fieldWriter.AddValue( (double) -1 );
4224 fieldWriter.AddValue( (double) shapeID );
4228 fieldWriter.Perform();
4229 SMESH_ComputeErrorPtr res = fieldWriter.GetError();
4230 if ( res && res->IsKO() )
4232 if ( res->myComment.empty() )
4233 { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
4235 { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
4238 } // loop on geomAssocFields
4243 //================================================================================
4245 * \brief Export a part of mesh to a DAT file
4247 //================================================================================
4249 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
4252 Unexpect aCatch(SALOME_SalomeException);
4254 _preMeshInfo->FullLoadFromFile();
4256 PrepareForWriting(file);
4258 SMESH_MeshPartDS partDS( meshPart );
4259 _impl->ExportDAT(file,&partDS);
4261 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4262 << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
4264 //================================================================================
4266 * \brief Export a part of mesh to an UNV file
4268 //================================================================================
4270 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
4273 Unexpect aCatch(SALOME_SalomeException);
4275 _preMeshInfo->FullLoadFromFile();
4277 PrepareForWriting(file);
4279 SMESH_MeshPartDS partDS( meshPart );
4280 _impl->ExportUNV(file, &partDS);
4282 TPythonDump() << SMESH::SMESH_Mesh_var(_this())
4283 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
4285 //================================================================================
4287 * \brief Export a part of mesh to an STL file
4289 //================================================================================
4291 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
4293 ::CORBA::Boolean isascii)
4295 Unexpect aCatch(SALOME_SalomeException);
4297 _preMeshInfo->FullLoadFromFile();
4299 PrepareForWriting(file);
4301 CORBA::String_var name;
4302 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4303 if ( !so->_is_nil() )
4304 name = so->GetName();
4306 SMESH_MeshPartDS partDS( meshPart );
4307 _impl->ExportSTL( file, isascii, name.in(), &partDS );
4309 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
4310 << meshPart<< ", r'" << file << "', " << isascii << ")";
4313 //================================================================================
4315 * \brief Export a part of mesh to an STL file
4317 //================================================================================
4319 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
4321 CORBA::Boolean overwrite,
4322 CORBA::Boolean groupElemsByType)
4325 Unexpect aCatch(SALOME_SalomeException);
4327 _preMeshInfo->FullLoadFromFile();
4329 PrepareForWriting(file,overwrite);
4331 std::string meshName("");
4332 SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4333 if ( !so->_is_nil() )
4335 CORBA::String_var name = so->GetName();
4336 meshName = name.in();
4340 SMESH_MeshPartDS partDS( meshPart );
4341 _impl->ExportCGNS(file, &partDS, meshName.c_str(), groupElemsByType );
4343 SMESH_CATCH( SMESH::throwCorbaException );
4345 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
4346 << meshPart<< ", r'" << file << "', " << overwrite << ")";
4348 THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
4352 //================================================================================
4354 * \brief Export a part of mesh to a GMF file
4356 //================================================================================
4358 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
4360 bool withRequiredGroups)
4362 Unexpect aCatch(SALOME_SalomeException);
4364 _preMeshInfo->FullLoadFromFile();
4366 PrepareForWriting(file,/*overwrite=*/true);
4368 SMESH_MeshPartDS partDS( meshPart );
4369 _impl->ExportGMF(file, &partDS, withRequiredGroups);
4371 TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
4372 << meshPart<< ", r'"
4374 << withRequiredGroups << ")";
4377 //=============================================================================
4379 * Return computation progress [0.,1]
4381 //=============================================================================
4383 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
4387 return _impl->GetComputeProgress();
4389 SMESH_CATCH( SMESH::doNothing );
4393 //================================================================================
4395 * \brief Return nb of nodes
4397 //================================================================================
4399 CORBA::Long SMESH_Mesh_i::NbNodes()
4401 Unexpect aCatch(SALOME_SalomeException);
4403 return _preMeshInfo->NbNodes();
4405 return _impl->NbNodes();
4408 //================================================================================
4410 * \brief Return nb of elements
4412 //================================================================================
4414 CORBA::Long SMESH_Mesh_i::NbElements()
4416 Unexpect aCatch(SALOME_SalomeException);
4418 return _preMeshInfo->NbElements();
4420 return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
4423 //================================================================================
4425 * \brief Return nb of 0D elements
4427 //================================================================================
4429 CORBA::Long SMESH_Mesh_i::Nb0DElements()
4431 Unexpect aCatch(SALOME_SalomeException);
4433 return _preMeshInfo->Nb0DElements();
4435 return _impl->Nb0DElements();
4438 //================================================================================
4440 * \brief Return nb of BALL elements
4442 //================================================================================
4444 CORBA::Long SMESH_Mesh_i::NbBalls()
4446 Unexpect aCatch(SALOME_SalomeException);
4448 return _preMeshInfo->NbBalls();
4450 return _impl->NbBalls();
4453 //================================================================================
4455 * \brief Return nb of 1D elements
4457 //================================================================================
4459 CORBA::Long SMESH_Mesh_i::NbEdges()
4461 Unexpect aCatch(SALOME_SalomeException);
4463 return _preMeshInfo->NbEdges();
4465 return _impl->NbEdges();
4468 //================================================================================
4470 * \brief Return nb of edges
4472 //================================================================================
4474 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
4476 Unexpect aCatch(SALOME_SalomeException);
4478 return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
4480 return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
4483 //================================================================================
4485 * \brief Return nb of faces
4487 //================================================================================
4489 CORBA::Long SMESH_Mesh_i::NbFaces()
4491 Unexpect aCatch(SALOME_SalomeException);
4493 return _preMeshInfo->NbFaces();
4495 return _impl->NbFaces();
4498 //================================================================================
4500 * \brief Return nb of tringles
4502 //================================================================================
4504 CORBA::Long SMESH_Mesh_i::NbTriangles()
4506 Unexpect aCatch(SALOME_SalomeException);
4508 return _preMeshInfo->NbTriangles();
4510 return _impl->NbTriangles();
4513 //================================================================================
4515 * \brief Return nb of bi-quadratic triangles
4517 //================================================================================
4519 CORBA::Long SMESH_Mesh_i::NbBiQuadTriangles()
4521 Unexpect aCatch(SALOME_SalomeException);
4523 return _preMeshInfo->NbBiQuadTriangles();
4525 return _impl->NbBiQuadTriangles();
4528 CORBA::Long SMESH_Mesh_i::NbQuadrangles()
4530 Unexpect aCatch(SALOME_SalomeException);
4532 return _preMeshInfo->NbQuadrangles();
4534 return _impl->NbQuadrangles();
4537 CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()
4539 Unexpect aCatch(SALOME_SalomeException);
4541 return _preMeshInfo->NbBiQuadQuadrangles();
4543 return _impl->NbBiQuadQuadrangles();
4546 CORBA::Long SMESH_Mesh_i::NbPolygons()
4548 Unexpect aCatch(SALOME_SalomeException);
4550 return _preMeshInfo->NbPolygons();
4552 return _impl->NbPolygons();
4555 CORBA::Long SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order)
4557 Unexpect aCatch(SALOME_SalomeException);
4559 return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
4561 return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
4564 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
4566 Unexpect aCatch(SALOME_SalomeException);
4568 return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
4570 return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
4573 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
4575 Unexpect aCatch(SALOME_SalomeException);
4577 return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
4579 return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
4582 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
4584 Unexpect aCatch(SALOME_SalomeException);
4586 return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
4588 return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
4591 //=============================================================================
4593 CORBA::Long SMESH_Mesh_i::NbVolumes()
4595 Unexpect aCatch(SALOME_SalomeException);
4597 return _preMeshInfo->NbVolumes();
4599 return _impl->NbVolumes();
4602 CORBA::Long SMESH_Mesh_i::NbTetras()
4604 Unexpect aCatch(SALOME_SalomeException);
4606 return _preMeshInfo->NbTetras();
4608 return _impl->NbTetras();
4611 CORBA::Long SMESH_Mesh_i::NbHexas()
4613 Unexpect aCatch(SALOME_SalomeException);
4615 return _preMeshInfo->NbHexas();
4617 return _impl->NbHexas();
4620 CORBA::Long SMESH_Mesh_i::NbTriQuadraticHexas()
4622 Unexpect aCatch(SALOME_SalomeException);
4624 return _preMeshInfo->NbTriQuadHexas();
4626 return _impl->NbTriQuadraticHexas();
4629 CORBA::Long SMESH_Mesh_i::NbPyramids()
4631 Unexpect aCatch(SALOME_SalomeException);
4633 return _preMeshInfo->NbPyramids();
4635 return _impl->NbPyramids();
4638 CORBA::Long SMESH_Mesh_i::NbPrisms()
4640 Unexpect aCatch(SALOME_SalomeException);
4642 return _preMeshInfo->NbPrisms();
4644 return _impl->NbPrisms();
4647 CORBA::Long SMESH_Mesh_i::NbHexagonalPrisms()
4649 Unexpect aCatch(SALOME_SalomeException);
4651 return _preMeshInfo->NbHexPrisms();
4653 return _impl->NbHexagonalPrisms();
4656 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()
4658 Unexpect aCatch(SALOME_SalomeException);
4660 return _preMeshInfo->NbPolyhedrons();
4662 return _impl->NbPolyhedrons();
4665 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
4667 Unexpect aCatch(SALOME_SalomeException);
4669 return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
4671 return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
4674 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
4676 Unexpect aCatch(SALOME_SalomeException);
4678 return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
4680 return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
4683 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
4685 Unexpect aCatch(SALOME_SalomeException);
4687 return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
4689 return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
4692 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
4694 Unexpect aCatch(SALOME_SalomeException);
4696 return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
4698 return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
4701 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
4703 Unexpect aCatch(SALOME_SalomeException);
4705 return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
4707 return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
4710 //=============================================================================
4712 * Return nb of published sub-meshes
4714 //=============================================================================
4716 CORBA::Long SMESH_Mesh_i::NbSubMesh()
4718 Unexpect aCatch(SALOME_SalomeException);
4719 return _mapSubMesh_i.size();
4722 //=============================================================================
4724 * Dumps mesh into a string
4726 //=============================================================================
4728 char* SMESH_Mesh_i::Dump()
4732 return CORBA::string_dup( os.str().c_str() );
4735 //=============================================================================
4737 * Method of SMESH_IDSource interface
4739 //=============================================================================
4741 SMESH::long_array* SMESH_Mesh_i::GetIDs()
4743 return GetElementsId();
4746 //=============================================================================
4748 * Return ids of all elements
4750 //=============================================================================
4752 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
4754 Unexpect aCatch(SALOME_SalomeException);
4756 _preMeshInfo->FullLoadFromFile();
4758 SMESH::long_array_var aResult = new SMESH::long_array();
4759 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4761 if ( aSMESHDS_Mesh == NULL )
4762 return aResult._retn();
4764 long nbElements = NbElements();
4765 aResult->length( nbElements );
4766 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
4767 for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
4768 aResult[i] = anIt->next()->GetID();
4770 return aResult._retn();
4774 //=============================================================================
4776 * Return ids of all elements of given type
4778 //=============================================================================
4780 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
4782 Unexpect aCatch(SALOME_SalomeException);
4784 _preMeshInfo->FullLoadFromFile();
4786 SMESH::long_array_var aResult = new SMESH::long_array();
4787 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4789 if ( aSMESHDS_Mesh == NULL )
4790 return aResult._retn();
4792 long nbElements = NbElements();
4794 // No sense in returning ids of elements along with ids of nodes:
4795 // when theElemType == SMESH::ALL, return node ids only if
4796 // there are no elements
4797 if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
4798 return GetNodesId();
4800 aResult->length( nbElements );
4804 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
4805 while ( i < nbElements && anIt->more() )
4806 aResult[i++] = anIt->next()->GetID();
4808 aResult->length( i );
4810 return aResult._retn();
4813 //=============================================================================
4815 * Return ids of all nodes
4817 //=============================================================================
4819 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
4821 Unexpect aCatch(SALOME_SalomeException);
4823 _preMeshInfo->FullLoadFromFile();
4825 SMESH::long_array_var aResult = new SMESH::long_array();
4826 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4828 if ( aMeshDS == NULL )
4829 return aResult._retn();
4831 long nbNodes = NbNodes();
4832 aResult->length( nbNodes );
4833 SMDS_NodeIteratorPtr anIt = aMeshDS->nodesIterator();
4834 for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
4835 aResult[i] = anIt->next()->GetID();
4837 return aResult._retn();
4840 //=============================================================================
4842 * Return type of the given element
4844 //=============================================================================
4846 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
4848 SMESH::ElementType type = SMESH::ALL;
4852 _preMeshInfo->FullLoadFromFile();
4854 type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
4856 SMESH_CATCH( SMESH::throwCorbaException );
4861 //=============================================================================
4863 * Return geometric type of the given element
4865 //=============================================================================
4867 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
4870 _preMeshInfo->FullLoadFromFile();
4872 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4874 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4876 return ( SMESH::EntityType ) e->GetEntityType();
4879 //=============================================================================
4881 * Return type of the given element
4883 //=============================================================================
4885 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const CORBA::Long id )
4888 _preMeshInfo->FullLoadFromFile();
4890 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4892 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4894 return ( SMESH::GeometryType ) e->GetGeomType();
4897 //=============================================================================
4899 * Return ID of elements for given submesh
4901 //=============================================================================
4903 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
4905 SMESH::long_array_var aResult = new SMESH::long_array();
4909 _preMeshInfo->FullLoadFromFile();
4911 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4912 if(!SM) return aResult._retn();
4914 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4915 if(!SDSM) return aResult._retn();
4917 aResult->length(SDSM->NbElements());
4919 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4921 while ( eIt->more() ) {
4922 aResult[i++] = eIt->next()->GetID();
4925 SMESH_CATCH( SMESH::throwCorbaException );
4927 return aResult._retn();
4930 //=============================================================================
4932 * Return ID of nodes for given sub-mesh
4933 * If param all==true - return all nodes, else -
4934 * Return only nodes on shapes.
4936 //=============================================================================
4938 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
4941 SMESH::long_array_var aResult = new SMESH::long_array();
4945 _preMeshInfo->FullLoadFromFile();
4947 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4948 if(!SM) return aResult._retn();
4950 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4951 if(!SDSM) return aResult._retn();
4954 if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
4955 SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
4956 while ( nIt->more() ) {
4957 const SMDS_MeshNode* elem = nIt->next();
4958 theElems.insert( elem->GetID() );
4961 else { // all nodes of submesh elements
4962 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4963 while ( eIt->more() ) {
4964 const SMDS_MeshElement* anElem = eIt->next();
4965 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
4966 while ( nIt->more() ) {
4967 const SMDS_MeshElement* elem = nIt->next();
4968 theElems.insert( elem->GetID() );
4973 aResult->length(theElems.size());
4974 set<int>::iterator itElem;
4976 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
4977 aResult[i++] = *itElem;
4979 SMESH_CATCH( SMESH::throwCorbaException );
4981 return aResult._retn();
4984 //=============================================================================
4986 * Return type of elements for given sub-mesh
4988 //=============================================================================
4990 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
4992 SMESH::ElementType type = SMESH::ALL;
4996 _preMeshInfo->FullLoadFromFile();
4998 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4999 if(!SM) return SMESH::ALL;
5001 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
5002 if(!SDSM) return SMESH::ALL;
5004 if(SDSM->NbElements()==0)
5005 return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
5007 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
5008 const SMDS_MeshElement* anElem = eIt->next();
5010 type = ( SMESH::ElementType ) anElem->GetType();
5012 SMESH_CATCH( SMESH::throwCorbaException );
5018 //=============================================================================
5020 * Return pointer to _impl as an integer value. Is called from constructor of SMESH_Client
5022 //=============================================================================
5024 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
5027 _preMeshInfo->FullLoadFromFile();
5029 CORBA::LongLong pointeur = CORBA::LongLong(_impl);
5030 if ( MYDEBUG ) MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
5035 //=============================================================================
5037 * Get XYZ coordinates of node as list of double
5038 * If there is not node for given ID - return empty list
5040 //=============================================================================
5042 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
5045 _preMeshInfo->FullLoadFromFile();
5047 SMESH::double_array_var aResult = new SMESH::double_array();
5048 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5049 if ( aMeshDS == NULL )
5050 return aResult._retn();
5053 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5055 return aResult._retn();
5059 aResult[0] = aNode->X();
5060 aResult[1] = aNode->Y();
5061 aResult[2] = aNode->Z();
5062 return aResult._retn();
5066 //=============================================================================
5068 * For given node return list of IDs of inverse elements
5069 * If there is not node for given ID - return empty list
5071 //=============================================================================
5073 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id,
5074 SMESH::ElementType elemType)
5077 _preMeshInfo->FullLoadFromFile();
5079 SMESH::long_array_var aResult = new SMESH::long_array();
5080 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5081 if ( aMeshDS == NULL )
5082 return aResult._retn();
5085 const SMDS_MeshNode* aNode = aMeshDS->FindNode( id );
5087 return aResult._retn();
5089 // find inverse elements
5090 SMDSAbs_ElementType type = SMDSAbs_ElementType( elemType );
5091 SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator( type );
5092 aResult->length( aNode->NbInverseElements( type ));
5093 for( int i = 0; eIt->more(); ++i )
5095 const SMDS_MeshElement* elem = eIt->next();
5096 aResult[ i ] = elem->GetID();
5098 return aResult._retn();
5101 //=============================================================================
5103 * \brief Return position of a node on shape
5105 //=============================================================================
5107 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
5110 _preMeshInfo->FullLoadFromFile();
5112 SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
5113 aNodePosition->shapeID = 0;
5114 aNodePosition->shapeType = GEOM::SHAPE;
5116 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5117 if ( !mesh ) return aNodePosition;
5119 if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
5121 if ( SMDS_PositionPtr pos = aNode->GetPosition() )
5123 aNodePosition->shapeID = aNode->getshapeId();
5124 switch ( pos->GetTypeOfPosition() ) {
5126 aNodePosition->shapeType = GEOM::EDGE;
5127 aNodePosition->params.length(1);
5128 aNodePosition->params[0] = SMDS_EdgePositionPtr( pos )->GetUParameter();
5130 case SMDS_TOP_FACE: {
5131 SMDS_FacePositionPtr fPos = pos;
5132 aNodePosition->shapeType = GEOM::FACE;
5133 aNodePosition->params.length(2);
5134 aNodePosition->params[0] = fPos->GetUParameter();
5135 aNodePosition->params[1] = fPos->GetVParameter();
5138 case SMDS_TOP_VERTEX:
5139 aNodePosition->shapeType = GEOM::VERTEX;
5141 case SMDS_TOP_3DSPACE:
5142 if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
5143 aNodePosition->shapeType = GEOM::SOLID;
5144 else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
5145 aNodePosition->shapeType = GEOM::SHELL;
5151 return aNodePosition;
5154 //=============================================================================
5156 * \brief Return position of an element on shape
5158 //=============================================================================
5160 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
5163 _preMeshInfo->FullLoadFromFile();
5165 SMESH::ElementPosition anElementPosition;
5166 anElementPosition.shapeID = 0;
5167 anElementPosition.shapeType = GEOM::SHAPE;
5169 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
5170 if ( !mesh ) return anElementPosition;
5172 if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
5174 anElementPosition.shapeID = anElem->getshapeId();
5175 const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
5176 if ( !aSp.IsNull() ) {
5177 switch ( aSp.ShapeType() ) {
5179 anElementPosition.shapeType = GEOM::EDGE;
5182 anElementPosition.shapeType = GEOM::FACE;
5185 anElementPosition.shapeType = GEOM::VERTEX;
5188 anElementPosition.shapeType = GEOM::SOLID;
5191 anElementPosition.shapeType = GEOM::SHELL;
5197 return anElementPosition;
5200 //=============================================================================
5202 * If given element is node return IDs of shape from position
5203 * If there is not node for given ID - return -1
5205 //=============================================================================
5207 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
5210 _preMeshInfo->FullLoadFromFile();
5212 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5213 if ( aMeshDS == NULL )
5217 const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
5219 return aNode->getshapeId();
5226 //=============================================================================
5228 * For given element return ID of result shape after
5229 * ::FindShape() from SMESH_MeshEditor
5230 * If there is not element for given ID - return -1
5232 //=============================================================================
5234 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
5237 _preMeshInfo->FullLoadFromFile();
5239 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5240 if ( aMeshDS == NULL )
5243 // try to find element
5244 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5248 ::SMESH_MeshEditor aMeshEditor(_impl);
5249 int index = aMeshEditor.FindShape( elem );
5257 //=============================================================================
5259 * Return number of nodes for given element
5260 * If there is not element for given ID - return -1
5262 //=============================================================================
5264 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
5267 _preMeshInfo->FullLoadFromFile();
5269 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5270 if ( aMeshDS == NULL ) return -1;
5271 // try to find element
5272 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5273 if(!elem) return -1;
5274 return elem->NbNodes();
5278 //=============================================================================
5280 * Return ID of node by given index for given element
5281 * If there is not element for given ID - return -1
5282 * If there is not node for given index - return -2
5284 //=============================================================================
5286 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
5289 _preMeshInfo->FullLoadFromFile();
5291 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5292 if ( aMeshDS == NULL ) return -1;
5293 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5294 if(!elem) return -1;
5295 if( index>=elem->NbNodes() || index<0 ) return -1;
5296 return elem->GetNode(index)->GetID();
5299 //=============================================================================
5301 * Return IDs of nodes of given element
5303 //=============================================================================
5305 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
5308 _preMeshInfo->FullLoadFromFile();
5310 SMESH::long_array_var aResult = new SMESH::long_array();
5311 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5313 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(id) )
5315 aResult->length( elem->NbNodes() );
5316 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5317 if ( const SMDS_MeshNode* n = elem->GetNode( i ))
5318 aResult[ i ] = n->GetID();
5321 return aResult._retn();
5324 //=============================================================================
5326 * Return true if given node is medium node
5327 * in given quadratic element
5329 //=============================================================================
5331 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
5334 _preMeshInfo->FullLoadFromFile();
5336 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5337 if ( aMeshDS == NULL ) return false;
5339 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5340 if(!aNode) return false;
5341 // try to find element
5342 const SMDS_MeshElement* elem = aMeshDS->FindElement(ide);
5343 if(!elem) return false;
5345 return elem->IsMediumNode(aNode);
5349 //=============================================================================
5351 * Return true if given node is medium node
5352 * in one of quadratic elements
5354 //=============================================================================
5356 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
5357 SMESH::ElementType theElemType)
5360 _preMeshInfo->FullLoadFromFile();
5362 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5363 if ( aMeshDS == NULL ) return false;
5366 const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5367 if(!aNode) return false;
5369 SMESH_MesherHelper aHelper( *(_impl) );
5371 SMDSAbs_ElementType aType;
5372 if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
5373 else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
5374 else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
5375 else aType = SMDSAbs_All;
5377 return aHelper.IsMedium(aNode,aType);
5381 //=============================================================================
5383 * Return number of edges for given element
5385 //=============================================================================
5387 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
5390 _preMeshInfo->FullLoadFromFile();
5392 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5393 if ( aMeshDS == NULL ) return -1;
5394 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5395 if(!elem) return -1;
5396 return elem->NbEdges();
5400 //=============================================================================
5402 * Return number of faces for given element
5404 //=============================================================================
5406 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
5409 _preMeshInfo->FullLoadFromFile();
5411 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5412 if ( aMeshDS == NULL ) return -1;
5413 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5414 if(!elem) return -1;
5415 return elem->NbFaces();
5418 //================================================================================
5420 * \brief Return nodes of given face (counted from zero) for given element.
5422 //================================================================================
5424 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long elemId,
5425 CORBA::Short faceIndex)
5428 _preMeshInfo->FullLoadFromFile();
5430 SMESH::long_array_var aResult = new SMESH::long_array();
5431 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5433 if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) )
5435 SMDS_VolumeTool vtool( elem, /*skipCentralNodes = */false );
5436 if ( faceIndex < vtool.NbFaces() )
5438 aResult->length( vtool.NbFaceNodes( faceIndex ));
5439 const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
5440 for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5441 aResult[ i ] = nn[ i ]->GetID();
5445 return aResult._retn();
5448 //================================================================================
5450 * \brief Return three components of normal of given mesh face.
5452 //================================================================================
5454 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long elemId,
5455 CORBA::Boolean normalized)
5458 _preMeshInfo->FullLoadFromFile();
5460 SMESH::double_array_var aResult = new SMESH::double_array();
5462 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5465 if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
5467 aResult->length( 3 );
5468 aResult[ 0 ] = normal.X();
5469 aResult[ 1 ] = normal.Y();
5470 aResult[ 2 ] = normal.Z();
5473 return aResult._retn();
5476 //================================================================================
5478 * \brief Return an element based on all given nodes.
5480 //================================================================================
5482 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
5485 _preMeshInfo->FullLoadFromFile();
5487 CORBA::Long elemID(0);
5488 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5490 vector< const SMDS_MeshNode * > nn( nodes.length() );
5491 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5492 if ( !( nn[i] = mesh->FindNode( nodes[i] )))
5495 const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
5496 if ( !elem && ( _impl->NbEdges ( ORDER_QUADRATIC ) ||
5497 _impl->NbFaces ( ORDER_QUADRATIC ) ||
5498 _impl->NbVolumes( ORDER_QUADRATIC )))
5499 elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
5501 if ( elem ) elemID = CORBA::Long( elem->GetID() );
5506 //================================================================================
5508 * \brief Return elements including all given nodes.
5510 //================================================================================
5512 SMESH::long_array* SMESH_Mesh_i::GetElementsByNodes(const SMESH::long_array& nodes,
5513 SMESH::ElementType elemType)
5516 _preMeshInfo->FullLoadFromFile();
5518 SMESH::long_array_var result = new SMESH::long_array();
5520 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5522 vector< const SMDS_MeshNode * > nn( nodes.length() );
5523 for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5524 nn[i] = mesh->FindNode( nodes[i] );
5526 std::vector<const SMDS_MeshElement *> elems;
5527 mesh->GetElementsByNodes( nn, elems, (SMDSAbs_ElementType) elemType );
5528 result->length( elems.size() );
5529 for ( size_t i = 0; i < elems.size(); ++i )
5530 result[i] = elems[i]->GetID();
5532 return result._retn();
5535 //=============================================================================
5537 * Return true if given element is polygon
5539 //=============================================================================
5541 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
5544 _preMeshInfo->FullLoadFromFile();
5546 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5547 if ( aMeshDS == NULL ) return false;
5548 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5549 if(!elem) return false;
5550 return elem->IsPoly();
5554 //=============================================================================
5556 * Return true if given element is quadratic
5558 //=============================================================================
5560 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
5563 _preMeshInfo->FullLoadFromFile();
5565 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5566 if ( aMeshDS == NULL ) return false;
5567 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5568 if(!elem) return false;
5569 return elem->IsQuadratic();
5572 //=============================================================================
5574 * Return diameter of ball discrete element or zero in case of an invalid \a id
5576 //=============================================================================
5578 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
5581 _preMeshInfo->FullLoadFromFile();
5583 if ( const SMDS_BallElement* ball =
5584 SMDS_Mesh::DownCast<SMDS_BallElement>( _impl->GetMeshDS()->FindElement( id )))
5585 return ball->GetDiameter();
5590 //=============================================================================
5592 * Return bary center for given element
5594 //=============================================================================
5596 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
5599 _preMeshInfo->FullLoadFromFile();
5601 SMESH::double_array_var aResult = new SMESH::double_array();
5602 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5603 if ( aMeshDS == NULL )
5604 return aResult._retn();
5606 const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5608 return aResult._retn();
5610 if(elem->GetType()==SMDSAbs_Volume) {
5611 SMDS_VolumeTool aTool;
5612 if(aTool.Set(elem)) {
5614 if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
5619 SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
5621 double x=0., y=0., z=0.;
5622 for(; anIt->more(); ) {
5624 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
5638 return aResult._retn();
5641 //================================================================================
5643 * \brief Create a group of elements preventing computation of a sub-shape
5645 //================================================================================
5647 SMESH::ListOfGroups*
5648 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int theSubShapeID,
5649 const char* theGroupName )
5651 Unexpect aCatch(SALOME_SalomeException);
5653 if ( !theGroupName || strlen( theGroupName) == 0 )
5654 THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
5656 SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
5657 ::SMESH_MeshEditor::ElemFeatures elemType;
5659 // submesh by subshape id
5660 if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
5661 if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
5664 SMESH_ComputeErrorPtr error = sm->GetComputeError();
5665 if ( error && error->HasBadElems() )
5667 // sort bad elements by type
5668 vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
5669 const list<const SMDS_MeshElement*>& badElems =
5670 static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
5671 list<const SMDS_MeshElement*>::const_iterator elemIt = badElems.begin();
5672 list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
5673 for ( ; elemIt != elemEnd; ++elemIt )
5675 const SMDS_MeshElement* elem = *elemIt;
5676 if ( !elem ) continue;
5678 if ( elem->GetID() < 1 )
5680 // elem is a temporary element, make a real element
5681 vector< const SMDS_MeshNode* > nodes;
5682 SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
5683 while ( nIt->more() && elem )
5685 nodes.push_back( nIt->next() );
5686 if ( nodes.back()->GetID() < 1 )
5687 elem = 0; // a temporary element on temporary nodes
5691 ::SMESH_MeshEditor editor( _impl );
5692 elem = editor.AddElement( nodes, elemType.Init( elem ));
5696 elemsByType[ elem->GetType() ].push_back( elem );
5699 // how many groups to create?
5701 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5702 nbTypes += int( !elemsByType[ i ].empty() );
5703 groups->length( nbTypes );
5706 for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
5708 vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
5709 if ( elems.empty() ) continue;
5711 groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
5712 if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
5714 SMESH::SMESH_Mesh_var mesh = _this();
5715 SALOMEDS::SObject_wrap aSO =
5716 _gen_i->PublishGroup( mesh, groups[ iG ],
5717 GEOM::GEOM_Object::_nil(), theGroupName);
5719 SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
5720 if ( !grp_i ) continue;
5722 if ( SMESHDS_Group* grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
5723 for ( size_t iE = 0; iE < elems.size(); ++iE )
5724 grpDS->SMDSGroup().Add( elems[ iE ]);
5729 return groups._retn();
5732 //=============================================================================
5734 * Create and publish group servants if any groups were imported or created anyhow
5736 //=============================================================================
5738 void SMESH_Mesh_i::CreateGroupServants()
5740 SMESH::SMESH_Mesh_var aMesh = _this();
5743 ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
5744 while ( groupIt->more() )
5746 ::SMESH_Group* group = groupIt->next();
5747 int anId = group->GetID();
5749 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
5750 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5752 addedIDs.insert( anId );
5754 SMESH_GroupBase_i* aGroupImpl;
5756 if ( SMESHDS_GroupOnGeom* groupOnGeom =
5757 dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
5759 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
5760 shape = groupOnGeom->GetShape();
5763 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
5766 SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
5767 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
5768 aGroupImpl->Register();
5770 // register CORBA object for persistence
5771 int nextId = _gen_i->RegisterObject( groupVar );
5772 if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
5773 else { (void)nextId; } // avoid "unused variable" warning in release mode
5775 // publishing the groups in the study
5776 GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
5777 _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName());
5780 if ( !addedIDs.empty() )
5783 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
5784 for ( int index = 0; i_grp != _mapGroups.end(); ++index, ++i_grp )
5786 set<int>::iterator it = addedIDs.find( i_grp->first );
5787 if ( it != addedIDs.end() )
5789 TPythonDump() << i_grp->second << " = " << aMesh << ".GetGroups()[ "<< index << " ]";
5790 addedIDs.erase( it );
5791 if ( addedIDs.empty() )
5798 //=============================================================================
5800 * \brief Return true if all sub-meshes are computed OK - to update an icon
5802 //=============================================================================
5804 bool SMESH_Mesh_i::IsComputedOK()
5806 return _impl->IsComputedOK();
5809 //=============================================================================
5811 * \brief Return groups cantained in _mapGroups by their IDs
5813 //=============================================================================
5815 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
5817 int nbGroups = groupIDs.size();
5818 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
5819 aList->length( nbGroups );
5821 list<int>::const_iterator ids = groupIDs.begin();
5822 for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
5824 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
5825 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5826 aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
5828 aList->length( nbGroups );
5829 return aList._retn();
5832 //=============================================================================
5834 * \brief Return information about imported file
5836 //=============================================================================
5838 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
5840 SMESH::MedFileInfo_var res( _medFileInfo );
5841 if ( !res.operator->() ) {
5842 res = new SMESH::MedFileInfo;
5844 res->fileSize = res->major = res->minor = res->release = -1;
5849 //=======================================================================
5850 //function : FileInfoToString
5851 //purpose : Persistence of file info
5852 //=======================================================================
5854 std::string SMESH_Mesh_i::FileInfoToString()
5857 if ( &_medFileInfo.in() && _medFileInfo->fileName[0] )
5859 s = SMESH_Comment( _medFileInfo->fileSize )
5860 << " " << _medFileInfo->major
5861 << " " << _medFileInfo->minor
5862 << " " << _medFileInfo->release
5863 << " " << _medFileInfo->fileName;
5868 //=======================================================================
5869 //function : FileInfoFromString
5870 //purpose : Persistence of file info
5871 //=======================================================================
5873 void SMESH_Mesh_i::FileInfoFromString(const std::string& info)
5875 std::string size, major, minor, release, fileName;
5876 std::istringstream is(info);
5877 is >> size >> major >> minor >> release;
5878 fileName = info.data() + ( size.size() + 1 +
5881 release.size()+ 1 );
5883 _medFileInfo = new SMESH::MedFileInfo();
5884 _medFileInfo->fileName = fileName.c_str();
5885 _medFileInfo->fileSize = atoi( size.c_str() );
5886 _medFileInfo->major = atoi( major.c_str() );
5887 _medFileInfo->minor = atoi( minor.c_str() );
5888 _medFileInfo->release = atoi( release.c_str() );
5891 //=============================================================================
5893 * \brief Pass names of mesh groups from study to mesh DS
5895 //=============================================================================
5897 void SMESH_Mesh_i::checkGroupNames()
5899 int nbGrp = NbGroups();
5903 SMESH::ListOfGroups* grpList = 0;
5904 // avoid dump of "GetGroups"
5906 // store python dump into a local variable inside local scope
5907 SMESH::TPythonDump pDump; // do not delete this line of code
5908 grpList = GetGroups();
5911 for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
5912 SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
5915 SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aGrp );
5916 if ( aGrpSO->_is_nil() )
5918 // correct name of the mesh group if necessary
5919 const char* guiName = aGrpSO->GetName();
5920 if ( strcmp(guiName, aGrp->GetName()) )
5921 aGrp->SetName( guiName );
5925 //=============================================================================
5927 * \brief Set list of notebook variables used for Mesh operations separated by ":" symbol
5929 //=============================================================================
5930 void SMESH_Mesh_i::SetParameters(const char* theParameters)
5932 SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
5936 //=============================================================================
5938 * \brief Return list of notebook variables used for Mesh operations separated by ":" symbol
5940 //=============================================================================
5942 char* SMESH_Mesh_i::GetParameters()
5944 return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
5947 //=============================================================================
5949 * \brief Return list of notebook variables used for last Mesh operation
5951 //=============================================================================
5952 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
5954 SMESH::string_array_var aResult = new SMESH::string_array();
5955 SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
5957 CORBA::String_var aParameters = GetParameters();
5958 SALOMEDS::ListOfListOfStrings_var aSections = SMESH_Gen_i::getStudyServant()->ParseVariables(aParameters);
5959 if ( aSections->length() > 0 ) {
5960 SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
5961 aResult->length( aVars.length() );
5962 for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
5963 aResult[i] = CORBA::string_dup( aVars[i] );
5966 return aResult._retn();
5969 //================================================================================
5971 * \brief Return types of elements it contains
5973 //================================================================================
5975 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
5978 return _preMeshInfo->GetTypes();
5980 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
5984 if (_impl->NbEdges()) types[nbTypes++] = SMESH::EDGE;
5985 if (_impl->NbFaces()) types[nbTypes++] = SMESH::FACE;
5986 if (_impl->NbVolumes()) types[nbTypes++] = SMESH::VOLUME;
5987 if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
5988 if (_impl->NbBalls()) types[nbTypes++] = SMESH::BALL;
5989 if (_impl->NbNodes() &&
5990 nbTypes == 0 ) types[nbTypes++] = SMESH::NODE;
5991 types->length( nbTypes );
5993 return types._retn();
5996 //================================================================================
5998 * \brief Return self
6000 //================================================================================
6002 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
6004 return SMESH::SMESH_Mesh::_duplicate( _this() );
6007 //================================================================================
6009 * \brief Return false if GetMeshInfo() return incorrect information that may
6010 * happen if mesh data is not yet fully loaded from the file of study.
6014 //================================================================================
6016 bool SMESH_Mesh_i::IsMeshInfoCorrect()
6018 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
6021 //=============================================================================
6023 * \brief Return number of mesh elements per each \a EntityType
6025 //=============================================================================
6027 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
6030 return _preMeshInfo->GetMeshInfo();
6032 SMESH::long_array_var aRes = new SMESH::long_array();
6033 aRes->length(SMESH::Entity_Last);
6034 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6036 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6038 return aRes._retn();
6039 const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
6040 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
6041 aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
6042 return aRes._retn();
6045 //=============================================================================
6047 * \brief Return number of mesh elements per each \a ElementType
6049 //=============================================================================
6051 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
6053 SMESH::long_array_var aRes = new SMESH::long_array();
6054 aRes->length(SMESH::NB_ELEMENT_TYPES);
6055 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6058 const SMDS_MeshInfo* meshInfo = 0;
6060 meshInfo = _preMeshInfo;
6061 else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
6062 meshInfo = & meshDS->GetMeshInfo();
6065 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
6066 aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
6068 return aRes._retn();
6071 //=============================================================================
6073 * Collect statistic of mesh elements given by iterator
6075 //=============================================================================
6077 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
6078 SMESH::long_array& theInfo)
6080 if (!theItr) return;
6081 while (theItr->more())
6082 theInfo[ theItr->next()->GetEntityType() ]++;
6084 //=============================================================================
6086 * Return mesh unstructed grid information.
6088 //=============================================================================
6090 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
6092 SALOMEDS::TMPFile_var SeqFile;
6093 if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
6094 SMDS_UnstructuredGrid* aGrid = aMeshDS->GetGrid();
6096 vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
6097 aWriter->WriteToOutputStringOn();
6098 aWriter->SetInputData(aGrid);
6099 aWriter->SetFileTypeToBinary();
6101 char* str = aWriter->GetOutputString();
6102 int size = aWriter->GetOutputStringLength();
6104 //Allocate octet buffer of required size
6105 CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
6106 //Copy ostrstream content to the octet buffer
6107 memcpy(OctetBuf, str, size);
6108 //Create and return TMPFile
6109 SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
6113 return SeqFile._retn();
6116 //=============================================================================
6117 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
6118 * SMESH::ElementType type) */
6120 using namespace SMESH::Controls;
6121 //-----------------------------------------------------------------------------
6122 struct PredicateIterator : public SMDS_ElemIterator
6124 SMDS_ElemIteratorPtr _elemIter;
6125 PredicatePtr _predicate;
6126 const SMDS_MeshElement* _elem;
6127 SMDSAbs_ElementType _type;
6129 PredicateIterator( SMDS_ElemIteratorPtr iterator,
6130 PredicatePtr predicate,
6131 SMDSAbs_ElementType type):
6132 _elemIter(iterator), _predicate(predicate), _type(type)
6140 virtual const SMDS_MeshElement* next()
6142 const SMDS_MeshElement* res = _elem;
6144 while ( _elemIter->more() && !_elem )
6146 if ((_elem = _elemIter->next()) &&
6147 (( _type != SMDSAbs_All && _type != _elem->GetType() ) ||
6148 ( !_predicate->IsSatisfy( _elem->GetID() ))))
6155 //-----------------------------------------------------------------------------
6156 struct IDSourceIterator : public SMDS_ElemIterator
6158 const CORBA::Long* _idPtr;
6159 const CORBA::Long* _idEndPtr;
6160 SMESH::long_array_var _idArray;
6161 const SMDS_Mesh* _mesh;
6162 const SMDSAbs_ElementType _type;
6163 const SMDS_MeshElement* _elem;
6165 IDSourceIterator( const SMDS_Mesh* mesh,
6166 const CORBA::Long* ids,
6168 SMDSAbs_ElementType type):
6169 _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
6171 if ( _idPtr && nbIds && _mesh )
6174 IDSourceIterator( const SMDS_Mesh* mesh,
6175 SMESH::long_array* idArray,
6176 SMDSAbs_ElementType type):
6177 _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
6179 if ( idArray && _mesh )
6181 _idPtr = &_idArray[0];
6182 _idEndPtr = _idPtr + _idArray->length();
6190 virtual const SMDS_MeshElement* next()
6192 const SMDS_MeshElement* res = _elem;
6194 while ( _idPtr < _idEndPtr && !_elem )
6196 if ( _type == SMDSAbs_Node )
6198 _elem = _mesh->FindNode( *_idPtr++ );
6200 else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
6201 (_elem->GetType() != _type && _type != SMDSAbs_All ))
6209 //-----------------------------------------------------------------------------
6211 struct NodeOfElemIterator : public SMDS_ElemIterator
6213 TColStd_MapOfInteger _checkedNodeIDs;
6214 SMDS_ElemIteratorPtr _elemIter;
6215 SMDS_ElemIteratorPtr _nodeIter;
6216 const SMDS_MeshElement* _node;
6218 NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
6220 if ( _elemIter && _elemIter->more() )
6222 _nodeIter = _elemIter->next()->nodesIterator();
6230 virtual const SMDS_MeshElement* next()
6232 const SMDS_MeshElement* res = _node;
6234 while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
6236 if ( _nodeIter->more() )
6238 _node = _nodeIter->next();
6239 if ( !_checkedNodeIDs.Add( _node->GetID() ))
6244 _nodeIter = _elemIter->next()->nodesIterator();
6252 //=============================================================================
6254 * Return iterator on elements of given type in given object
6256 //=============================================================================
6258 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
6259 SMESH::ElementType theType)
6261 SMDS_ElemIteratorPtr elemIt;
6262 bool typeOK = ( theType == SMESH::ALL );
6263 SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
6265 SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
6266 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
6267 if ( !mesh_i ) return elemIt;
6268 SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
6270 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
6272 elemIt = meshDS->elementsIterator( elemType );
6275 else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
6277 SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
6280 elemIt = sm->GetElements();
6281 if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6283 typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
6284 elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
6288 else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
6290 SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
6291 if ( groupDS && ( elemType == groupDS->GetType() ||
6292 elemType == SMDSAbs_Node ||
6293 elemType == SMDSAbs_All ))
6295 elemIt = groupDS->GetElements();
6296 typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
6299 else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
6301 if ( filter_i->GetElementType() == theType ||
6302 filter_i->GetElementType() == SMESH::ALL ||
6303 elemType == SMDSAbs_Node ||
6304 elemType == SMDSAbs_All)
6306 SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
6307 if ( pred_i && pred_i->GetPredicate() )
6309 SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
6310 SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
6311 SMDSAbs_ElementType iterType = elemType == SMDSAbs_Node ? filterType : elemType;
6312 elemIt = SMDS_ElemIteratorPtr
6313 ( new PredicateIterator( allElemIt, pred_i->GetPredicate(), iterType ));
6314 typeOK = ( elemType == SMDSAbs_Node ? filterType == SMDSAbs_Node : elemIt->more() );
6320 SMESH::array_of_ElementType_var types = theObject->GetTypes();
6321 const bool isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
6322 if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
6324 SMDSAbs_ElementType iterType = isNodes ? SMDSAbs_Node : elemType;
6325 if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
6328 if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
6329 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, iterType ));
6333 SMESH::long_array_var ids = theObject->GetIDs();
6334 elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), iterType ));
6336 typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
6339 if ( elemIt && elemIt->more() && !typeOK )
6341 if ( elemType == SMDSAbs_Node )
6343 elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
6347 elemIt = SMDS_ElemIteratorPtr();
6353 //=============================================================================
6354 namespace // Finding concurrent hypotheses
6355 //=============================================================================
6359 * \brief mapping of mesh dimension into shape type
6361 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
6363 TopAbs_ShapeEnum aType = TopAbs_SOLID;
6365 case 0: aType = TopAbs_VERTEX; break;
6366 case 1: aType = TopAbs_EDGE; break;
6367 case 2: aType = TopAbs_FACE; break;
6369 default:aType = TopAbs_SOLID; break;
6374 //-----------------------------------------------------------------------------
6376 * \brief Internal structure used to find concurrent submeshes
6378 * It represents a pair < submesh, concurrent dimension >, where
6379 * 'concurrent dimension' is dimension of shape where the submesh can concurrent
6380 * with another submesh. In other words, it is dimension of a hypothesis assigned
6387 int _dim; //!< a dimension the algo can build (concurrent dimension)
6388 int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
6389 TopTools_MapOfShape _shapeMap; //!< [sub-]shapes of dimension == _dim
6390 const SMESH_subMesh* _subMesh;
6391 list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
6393 //-----------------------------------------------------------------------------
6394 // Return the algorithm
6395 const SMESH_Algo* GetAlgo() const
6396 { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
6398 //-----------------------------------------------------------------------------
6400 SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
6402 const TopoDS_Shape& theShape)
6404 _subMesh = theSubMesh;
6405 SetShape( theDim, theShape );
6408 //-----------------------------------------------------------------------------
6410 void SetShape(const int theDim,
6411 const TopoDS_Shape& theShape)
6414 _ownDim = SMESH_Gen::GetShapeDim(theShape);
6415 if (_dim >= _ownDim)
6416 _shapeMap.Add( theShape );
6418 TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
6419 for( ; anExp.More(); anExp.Next() )
6420 _shapeMap.Add( anExp.Current() );
6424 //-----------------------------------------------------------------------------
6425 //! Check sharing of sub-shapes
6426 static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
6427 const TopTools_MapOfShape& theToFind,
6428 const TopAbs_ShapeEnum theType)
6430 bool isShared = false;
6431 TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
6432 for (; !isShared && anItr.More(); anItr.Next() )
6434 const TopoDS_Shape& aSubSh = anItr.Key();
6435 // check for case when concurrent dimensions are same
6436 isShared = theToFind.Contains( aSubSh );
6437 // check for sub-shape with concurrent dimension
6438 TopExp_Explorer anExp( aSubSh, theType );
6439 for ( ; !isShared && anExp.More(); anExp.Next() )
6440 isShared = theToFind.Contains( anExp.Current() );
6445 //-----------------------------------------------------------------------------
6446 //! check algorithms
6447 static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
6448 const SMESHDS_Hypothesis* theA2)
6450 if ( !theA1 || !theA2 ||
6451 theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
6452 theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
6453 return false; // one of the hypothesis is not algorithm
6454 // check algorithm names (should be equal)
6455 return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
6459 //-----------------------------------------------------------------------------
6460 //! Check if sub-shape hypotheses are concurrent
6461 bool IsConcurrent(const SMESH_DimHyp* theOther) const
6463 if ( _subMesh == theOther->_subMesh )
6464 return false; // same sub-shape - should not be
6466 // if ( <own dim of either of submeshes> == <concurrent dim> &&
6467 // any of the two submeshes is not on COMPOUND shape )
6468 // -> no concurrency
6469 bool meIsCompound = (_subMesh->GetSubMeshDS() &&
6470 _subMesh->GetSubMeshDS()->IsComplexSubmesh());
6471 bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
6472 theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
6473 if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
6476 bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
6477 if ( !checkSubShape )
6480 // check algorithms to be same
6481 const SMESH_Algo* a1 = this->GetAlgo();
6482 const SMESH_Algo* a2 = theOther->GetAlgo();
6483 bool isSame = checkAlgo( a1, a2 );
6487 // commented off for IPAL54678
6488 // if ( !a1 || !a2 )
6489 // return false; // pb?
6490 // return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency !
6493 // check hypothesises for concurrence (skip first as algorithm)
6495 // pointers should be same, because it is referened from mesh hypothesis partition
6496 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
6497 list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
6498 for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
6499 if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
6501 // the submeshes are concurrent if their algorithms has different parameters
6502 return nbSame != theOther->_hypotheses.size() - 1;
6505 // Return true if algorithm of this SMESH_DimHyp is used if no
6506 // sub-mesh order is imposed by the user
6507 bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
6509 // NeedDiscreteBoundary() algo has a higher priority
6510 if ( this ->GetAlgo()->NeedDiscreteBoundary() !=
6511 theOther->GetAlgo()->NeedDiscreteBoundary() )
6512 return !this->GetAlgo()->NeedDiscreteBoundary();
6514 return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
6517 }; // end of SMESH_DimHyp
6518 //-----------------------------------------------------------------------------
6520 typedef list<const SMESH_DimHyp*> TDimHypList;
6522 //-----------------------------------------------------------------------------
6524 void addDimHypInstance(const int theDim,
6525 const TopoDS_Shape& theShape,
6526 const SMESH_Algo* theAlgo,
6527 const SMESH_subMesh* theSubMesh,
6528 const list <const SMESHDS_Hypothesis*>& theHypList,
6529 TDimHypList* theDimHypListArr )
6531 if ( !theAlgo->NeedDiscreteBoundary() &&
6532 theAlgo->NeedLowerHyps( theDim )) // IPAL54678
6534 TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
6535 if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh )
6537 SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
6538 dimHyp->_hypotheses.push_front(theAlgo);
6539 listOfdimHyp.push_back( dimHyp );
6542 SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
6543 dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
6544 theHypList.begin(), theHypList.end() );
6547 //-----------------------------------------------------------------------------
6548 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
6549 TDimHypList& theListOfConcurr)
6551 if ( theListOfConcurr.empty() )
6553 theListOfConcurr.push_back( theDimHyp );
6557 TDimHypList::iterator hypIt = theListOfConcurr.begin();
6558 while ( hypIt != theListOfConcurr.end() &&
6559 !theDimHyp->IsHigherPriorityThan( *hypIt ))
6561 theListOfConcurr.insert( hypIt, theDimHyp );
6565 //-----------------------------------------------------------------------------
6566 void findConcurrents(const SMESH_DimHyp* theDimHyp,
6567 const TDimHypList& theListOfDimHyp,
6568 TDimHypList& theListOfConcurrHyp,
6569 set<int>& theSetOfConcurrId )
6571 TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
6572 for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
6574 const SMESH_DimHyp* curDimHyp = *rIt;
6575 if ( curDimHyp == theDimHyp )
6576 break; // meet own dimHyp pointer in same dimension
6578 if ( theDimHyp->IsConcurrent( curDimHyp ) &&
6579 theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
6581 addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
6586 //-----------------------------------------------------------------------------
6587 bool unionLists(TListOfInt& theListOfId,
6588 TListOfListOfInt& theListOfListOfId,
6591 bool changed = false;
6592 if ( theListOfId.empty() )
6594 TListOfListOfInt::iterator it = theListOfListOfId.begin();
6595 for ( int i = 0; it != theListOfListOfId.end(); it++, i++ )
6598 continue; //skip already treated lists
6599 // check if other list has any same submesh object
6600 TListOfInt& otherListOfId = *it;
6601 if ( find_first_of( theListOfId.begin(), theListOfId.end(),
6602 otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
6605 // union two lists (from source into target)
6606 TListOfInt::iterator it2 = otherListOfId.begin();
6607 for ( ; it2 != otherListOfId.end(); it2++ ) {
6608 if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
6610 theListOfId.push_back(*it2);
6614 // clear source list
6615 otherListOfId.clear();
6619 //-----------------------------------------------------------------------------
6621 //! free memory allocated for dimension-hypothesis objects
6622 void removeDimHyps( TDimHypList* theArrOfList )
6624 for (int i = 0; i < 4; i++ ) {
6625 TDimHypList& listOfdimHyp = theArrOfList[i];
6626 TDimHypList::const_iterator it = listOfdimHyp.begin();
6627 for ( ; it != listOfdimHyp.end(); it++ )
6632 //-----------------------------------------------------------------------------
6634 * \brief find common submeshes with given submesh
6635 * \param theSubMeshList list of already collected submesh to check
6636 * \param theSubMesh given submesh to intersect with other
6637 * \param theCommonSubMeshes collected common submeshes
6639 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
6640 const SMESH_subMesh* theSubMesh,
6641 set<const SMESH_subMesh*>& theCommon )
6645 list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
6646 for ( ; it != theSubMeshList.end(); it++ )
6647 theSubMesh->FindIntersection( *it, theCommon );
6648 theSubMeshList.push_back( theSubMesh );
6649 //theCommon.insert( theSubMesh );
6652 //-----------------------------------------------------------------------------
6653 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
6655 TListOfListOfInt::const_iterator listsIt = smLists.begin();
6656 for ( ; listsIt != smLists.end(); ++listsIt )
6658 const TListOfInt& smIDs = *listsIt;
6659 if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
6667 //=============================================================================
6669 * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
6671 //=============================================================================
6673 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
6675 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6676 if ( isSubMeshInList( submeshID, anOrder ))
6679 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6680 return isSubMeshInList( submeshID, allConurrent );
6683 //=============================================================================
6685 * \brief Return sub-mesh objects list in meshing order
6687 //=============================================================================
6689 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
6691 SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
6693 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6695 return aResult._retn();
6697 TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6698 TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6699 anOrder.splice( anOrder.end(), allConurrent );
6704 TListOfListOfInt::iterator listIt = anOrder.begin();
6705 for ( int listIndx = 1; listIt != anOrder.end(); listIt++, listIndx++ )
6706 if ( unionLists( *listIt, anOrder, listIndx ))
6711 // convert submesh ids into interface instances
6712 // and dump command into python
6713 convertMeshOrder( anOrder, aResult, false );
6715 return aResult._retn();
6718 //=============================================================================
6720 * \brief Finds concurrent sub-meshes
6722 //=============================================================================
6724 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
6726 TListOfListOfInt anOrder;
6727 ::SMESH_Mesh& mesh = GetImpl();
6729 // collect submeshes and detect concurrent algorithms and hypothesises
6730 TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
6732 map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
6733 for ( ; i_sm != _mapSubMesh.end(); i_sm++ )
6735 ::SMESH_subMesh* sm = (*i_sm).second;
6737 const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
6739 // list of assigned hypothesises
6740 const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
6741 // Find out dimensions where the submesh can be concurrent.
6742 // We define the dimensions by algo of each of hypotheses in hypList
6743 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
6744 for( ; hypIt != hypList.end(); hypIt++ )
6746 SMESH_Algo* anAlgo = 0;
6747 const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
6748 if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
6749 // hyp it-self is algo
6750 anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
6752 // try to find algorithm with help of sub-shapes
6753 TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
6754 for ( ; !anAlgo && anExp.More(); anExp.Next() )
6755 anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
6758 continue; // no algorithm assigned to a current submesh
6760 int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
6761 // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary()
6762 // and !anAlgo->NeedLowerHyps( dim ))
6764 // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
6765 for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
6766 addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
6768 } // end iterations on submesh
6770 // iterate on created dimension-hypotheses and check for concurrents
6771 for ( int i = 0; i < 4; i++ )
6773 const TDimHypList& listOfDimHyp = dimHypListArr[i];
6774 // check for concurrents in own and other dimensions (step-by-step)
6775 TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
6776 for ( ; dhIt != listOfDimHyp.end(); dhIt++ )
6778 const SMESH_DimHyp* dimHyp = *dhIt;
6779 TDimHypList listOfConcurr;
6780 set<int> setOfConcurrIds;
6781 // looking for concurrents and collect into own list
6782 for ( int j = i; j < 4; j++ )
6783 findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
6784 // check if any concurrents found
6785 if ( listOfConcurr.size() > 0 )
6787 // add own submesh to list of concurrent
6788 addInOrderOfPriority( dimHyp, listOfConcurr );
6789 list<int> listOfConcurrIds;
6790 TDimHypList::iterator hypIt = listOfConcurr.begin();
6791 for ( ; hypIt != listOfConcurr.end(); ++hypIt )
6792 listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
6793 anOrder.push_back( listOfConcurrIds );
6798 removeDimHyps(dimHypListArr);
6800 // now, minimize the number of concurrent groups
6801 // Here we assume that lists of submeshes can have same submesh
6802 // in case of multi-dimension algorithms, as result
6803 // list with common submesh has to be united into one list
6805 TListOfListOfInt::iterator listIt = anOrder.begin();
6806 for(; listIt != anOrder.end(); listIt++, listIndx++ )
6807 unionLists( *listIt, anOrder, listIndx + 1 );
6812 //=============================================================================
6814 * \brief Set submesh object order
6815 * \param theSubMeshArray submesh array order
6817 //=============================================================================
6819 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
6822 _preMeshInfo->ForgetOrLoad();
6825 ::SMESH_Mesh& mesh = GetImpl();
6827 TPythonDump aPythonDump; // prevent dump of called methods
6828 aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
6830 TListOfListOfInt subMeshOrder;
6831 for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
6833 const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
6834 TListOfInt subMeshIds;
6836 aPythonDump << ", ";
6837 aPythonDump << "[ ";
6838 // Collect subMeshes which should be clear
6839 // do it list-by-list, because modification of submesh order
6840 // take effect between concurrent submeshes only
6841 set<const SMESH_subMesh*> subMeshToClear;
6842 list<const SMESH_subMesh*> subMeshList;
6843 for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
6845 const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
6847 aPythonDump << ", ";
6848 aPythonDump << subMesh;
6849 subMeshIds.push_back( subMesh->GetId() );
6850 // detect common parts of submeshes
6851 if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
6852 findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
6854 aPythonDump << " ]";
6855 subMeshOrder.push_back( subMeshIds );
6857 // clear collected sub-meshes
6858 set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
6859 for ( ; clrIt != subMeshToClear.end(); clrIt++ )
6860 if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
6862 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
6863 if ( SMESH_Algo* algo = sm->GetAlgo() ) // #16748
6864 sm->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, algo ); // to clear a cached algo
6867 aPythonDump << " ])";
6869 mesh.SetMeshOrder( subMeshOrder );
6872 SMESH::SMESH_Mesh_var me = _this();
6873 _gen_i->UpdateIcons( me );
6878 //=============================================================================
6880 * \brief Convert submesh ids into submesh interfaces
6882 //=============================================================================
6884 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt& theIdsOrder,
6885 SMESH::submesh_array_array& theResOrder,
6886 const bool theIsDump)
6888 int nbSet = theIdsOrder.size();
6889 TPythonDump aPythonDump; // prevent dump of called methods
6891 aPythonDump << "[ ";
6892 theResOrder.length(nbSet);
6893 TListOfListOfInt::const_iterator it = theIdsOrder.begin();
6895 for( ; it != theIdsOrder.end(); it++ )
6897 // translate submesh identificators into submesh objects
6898 // takeing into account real number of concurrent lists
6899 const TListOfInt& aSubOrder = (*it);
6900 if (!aSubOrder.size())
6903 aPythonDump << "[ ";
6904 // convert shape indices into interfaces
6905 SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
6906 aResSubSet->length(aSubOrder.size());
6907 TListOfInt::const_iterator subIt = aSubOrder.begin();
6909 for( j = 0; subIt != aSubOrder.end(); subIt++ )
6911 if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
6913 SMESH::SMESH_subMesh_var subMesh =
6914 SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
6917 aPythonDump << ", ";
6918 aPythonDump << subMesh;
6920 aResSubSet[ j++ ] = subMesh;
6923 aPythonDump << " ]";
6925 theResOrder[ listIndx++ ] = aResSubSet;
6927 // correct number of lists
6928 theResOrder.length( listIndx );
6931 // finilise python dump
6932 aPythonDump << " ]";
6933 aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
6937 namespace // utils used by SMESH_MeshPartDS
6940 * \brief Class used to access to protected data of SMDS_MeshInfo
6942 struct TMeshInfo : public SMDS_MeshInfo
6944 void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
6947 * \brief Element holing its ID only
6949 struct TElemID : public SMDS_LinearEdge
6951 TElemID(int ID) : SMDS_LinearEdge(0,0) { setID( ID ); }
6955 //================================================================================
6957 // Implementation of SMESH_MeshPartDS
6959 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
6960 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
6962 SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
6963 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
6966 _meshDS = mesh_i->GetImpl().GetMeshDS();
6968 SetPersistentId( _meshDS->GetPersistentId() );
6970 if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
6972 // <meshPart> is the whole mesh
6973 myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
6975 set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
6976 myGroupSet = _meshDS->GetGroups();
6981 SMESH::long_array_var anIDs = meshPart->GetIDs();
6982 SMESH::array_of_ElementType_var types = meshPart->GetTypes();
6983 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
6985 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
6986 if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
6987 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6992 for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
6993 if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
6994 if ( _elements[ e->GetType() ].insert( e ).second )
6997 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
6998 while ( nIt->more() )
7000 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7001 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7008 ShapeToMesh( _meshDS->ShapeToMesh() );
7010 _meshDS = 0; // to enforce iteration on _elements and _nodes
7013 // -------------------------------------------------------------------------------------
7014 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
7015 SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
7018 list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
7019 for ( ; partIt != meshPart.end(); ++partIt )
7020 if ( const SMDS_MeshElement * e = *partIt )
7021 if ( _elements[ e->GetType() ].insert( e ).second )
7024 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
7025 while ( nIt->more() )
7027 const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
7028 if ( _elements[ SMDSAbs_Node ].insert( n ).second )
7034 // -------------------------------------------------------------------------------------
7035 const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const
7037 if ( _meshDS ) return _meshDS->FindElement( IDelem );
7039 TElemID elem( IDelem );
7040 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7041 if ( !_elements[ iType ].empty() )
7043 TIDSortedElemSet::const_iterator it = _elements[ iType ].find( &elem );
7044 if ( it != _elements[ iType ].end() )
7049 // -------------------------------------------------------------------------------------
7050 bool SMESH_MeshPartDS::HasNumerationHoles()
7052 if ( _meshDS ) return _meshDS->HasNumerationHoles();
7054 return ( MinNodeID() != 1 ||
7055 MaxNodeID() != NbNodes() ||
7056 MinElementID() != 1 ||
7057 MaxElementID() != NbElements() );
7059 // -------------------------------------------------------------------------------------
7060 int SMESH_MeshPartDS::MaxNodeID() const
7062 if ( _meshDS ) return _meshDS->MaxNodeID();
7063 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].rbegin())->GetID();
7065 // -------------------------------------------------------------------------------------
7066 int SMESH_MeshPartDS::MinNodeID() const
7068 if ( _meshDS ) return _meshDS->MinNodeID();
7069 return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].begin())->GetID();
7071 // -------------------------------------------------------------------------------------
7072 int SMESH_MeshPartDS::MaxElementID() const
7074 if ( _meshDS ) return _meshDS->MaxElementID();
7076 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7077 if ( !_elements[ iType ].empty() )
7078 maxID = Max( maxID, (*_elements[ iType ].rbegin())->GetID() );
7081 // -------------------------------------------------------------------------------------
7082 int SMESH_MeshPartDS::MinElementID() const
7084 if ( _meshDS ) return _meshDS->MinElementID();
7086 for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
7087 if ( !_elements[ iType ].empty() )
7088 minID = Min( minID, (*_elements[ iType ].begin())->GetID() );
7091 // -------------------------------------------------------------------------------------
7092 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
7094 if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
7096 typedef SMDS_SetIterator
7097 <const SMDS_MeshElement*,
7098 TIDSortedElemSet::const_iterator,
7099 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7100 SMDS_MeshElement::GeomFilter
7103 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( geomType );
7105 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7106 _elements[type].end(),
7107 SMDS_MeshElement::GeomFilter( geomType )));
7109 // -------------------------------------------------------------------------------------
7110 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
7112 if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
7114 typedef SMDS_SetIterator
7115 <const SMDS_MeshElement*,
7116 TIDSortedElemSet::const_iterator,
7117 SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
7118 SMDS_MeshElement::EntityFilter
7121 SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( entity );
7123 return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
7124 _elements[type].end(),
7125 SMDS_MeshElement::EntityFilter( entity )));
7127 // -------------------------------------------------------------------------------------
7128 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
7130 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
7131 if ( type == SMDSAbs_All && !_meshDS )
7133 typedef vector< SMDS_ElemIteratorPtr > TIterVec;
7135 for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
7136 if ( !_elements[i].empty() && i != SMDSAbs_Node )
7138 ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
7140 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
7141 return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
7143 return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
7144 ( new TIter( _elements[type].begin(), _elements[type].end() ));
7146 // -------------------------------------------------------------------------------------
7147 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType) \
7148 iterType SMESH_MeshPartDS::methName() const \
7150 typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
7151 return _meshDS ? _meshDS->methName() : iterType \
7152 ( new TIter( _elements[elemType].begin(), _elements[elemType].end() )); \
7154 // -------------------------------------------------------------------------------------
7155 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
7156 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
7157 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
7158 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
7159 #undef _GET_ITER_DEFINE
7161 // END Implementation of SMESH_MeshPartDS
7163 //================================================================================