1 // Copyright (C) 2007-2010 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.
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 // SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
23 // File : SMESH_Mesh_i.cxx
24 // Author : Paul RASCLE, EDF
27 #include "SMESH_Mesh_i.hxx"
29 #include "SMESH_Filter_i.hxx"
30 #include "SMESH_Gen_i.hxx"
31 #include "SMESH_Group_i.hxx"
32 #include "SMESH_MEDMesh_i.hxx"
33 #include "SMESH_MeshEditor_i.hxx"
34 #include "SMESH_PythonDump.hxx"
35 #include "SMESH_subMesh_i.hxx"
37 #include "DriverMED_R_SMESHDS_Mesh.h"
38 #include "DriverMED_W_SMESHDS_Mesh.h"
39 #include "SMDS_VolumeTool.hxx"
40 #include "SMDS_ElemIterator.hxx"
41 #include "SMESHDS_Command.hxx"
42 #include "SMESHDS_CommandType.hxx"
43 #include "SMESHDS_GroupOnGeom.hxx"
44 #include "SMESH_Group.hxx"
45 #include "SMESH_MeshEditor.hxx"
46 #include "SMESH_MesherHelper.hxx"
47 #include "SMDS_EdgePosition.hxx"
48 #include "SMDS_FacePosition.hxx"
51 #include "SALOME_NamingService.hxx"
52 #include "Utils_CorbaException.hxx"
53 #include "Utils_ExceptHandlers.hxx"
54 #include "Utils_SINGLETON.hxx"
55 #include "utilities.h"
56 #include "GEOMImpl_Types.hxx"
59 #include <BRep_Builder.hxx>
60 #include <OSD_Directory.hxx>
61 #include <OSD_File.hxx>
62 #include <OSD_Path.hxx>
63 #include <OSD_Protection.hxx>
64 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
65 #include <TColStd_MapOfInteger.hxx>
66 #include <TColStd_SequenceOfInteger.hxx>
67 #include <TCollection_AsciiString.hxx>
69 #include <TopExp_Explorer.hxx>
70 #include <TopoDS_Compound.hxx>
71 #include <TopTools_MapOfShape.hxx>
72 #include <TopTools_MapIteratorOfMapOfShape.hxx>
82 static int MYDEBUG = 0;
84 static int MYDEBUG = 0;
88 using SMESH::TPythonDump;
90 int SMESH_Mesh_i::myIdGenerator = 0;
92 //To disable automatic genericobj management, the following line should be commented.
93 //Otherwise, it should be uncommented. Refer to KERNEL_SRC/src/SALOMEDSImpl/SALOMEDSImpl_AttributeIOR.cxx
94 #define WITHGENERICOBJ
96 //=============================================================================
100 //=============================================================================
102 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
104 CORBA::Long studyId )
105 : SALOME::GenericObj_i( thePOA )
107 MESSAGE("SMESH_Mesh_i");
110 _id = myIdGenerator++;
114 //=============================================================================
118 //=============================================================================
120 SMESH_Mesh_i::~SMESH_Mesh_i()
122 MESSAGE("~SMESH_Mesh_i");
124 #ifdef WITHGENERICOBJ
126 map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
127 for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++) {
128 if ( CORBA::is_nil( itGr->second ))
130 SMESH_GroupBase_i* aGroup = dynamic_cast<SMESH_GroupBase_i*>(SMESH_Gen_i::GetServant(itGr->second).in());
132 // this method is called from destructor of group (PAL6331)
133 //_impl->RemoveGroup( aGroup->GetLocalID() );
134 aGroup->myMeshServant = 0;
135 aGroup->UnRegister();
141 map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
142 for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ ) {
143 if ( CORBA::is_nil( itSM->second ))
145 SMESH_subMesh_i* aSubMesh = dynamic_cast<SMESH_subMesh_i*>(SMESH_Gen_i::GetServant(itSM->second).in());
147 aSubMesh->UnRegister();
150 _mapSubMeshIor.clear();
152 // destroy hypotheses
153 map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
154 for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
155 if ( CORBA::is_nil( itH->second ))
157 SMESH_Hypothesis_i* aHypo = dynamic_cast<SMESH_Hypothesis_i*>(SMESH_Gen_i::GetServant(itH->second).in());
168 //=============================================================================
172 * Associates <this> mesh with <theShape> and puts a reference
173 * to <theShape> into the current study;
174 * the previous shape is substituted by the new one.
176 //=============================================================================
178 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
179 throw (SALOME::SALOME_Exception)
181 Unexpect aCatch(SALOME_SalomeException);
183 _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
185 catch(SALOME_Exception & S_ex) {
186 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
188 // to track changes of GEOM groups
189 addGeomGroupData( theShapeObject, _this() );
192 //================================================================================
194 * \brief return true if mesh has a shape to build a shape on
196 //================================================================================
198 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
199 throw (SALOME::SALOME_Exception)
201 Unexpect aCatch(SALOME_SalomeException);
204 res = _impl->HasShapeToMesh();
206 catch(SALOME_Exception & S_ex) {
207 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
212 //=======================================================================
213 //function : GetShapeToMesh
215 //=======================================================================
217 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
218 throw (SALOME::SALOME_Exception)
220 Unexpect aCatch(SALOME_SalomeException);
221 GEOM::GEOM_Object_var aShapeObj;
223 TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
225 aShapeObj = _gen_i->ShapeToGeomObject( S );
227 catch(SALOME_Exception & S_ex) {
228 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
230 return aShapeObj._retn();
233 //================================================================================
235 * \brief Remove all nodes and elements
237 //================================================================================
239 void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
241 Unexpect aCatch(SALOME_SalomeException);
244 CheckGeomGroupModif(); // issue 20145
246 catch(SALOME_Exception & S_ex) {
247 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
249 TPythonDump() << _this() << ".Clear()";
252 //================================================================================
254 * \brief Remove all nodes and elements for indicated shape
256 //================================================================================
258 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
259 throw (SALOME::SALOME_Exception)
261 Unexpect aCatch(SALOME_SalomeException);
263 _impl->ClearSubMesh( ShapeID );
265 catch(SALOME_Exception & S_ex) {
266 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
270 //=============================================================================
274 //=============================================================================
276 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
278 SMESH::DriverMED_ReadStatus res;
281 case DriverMED_R_SMESHDS_Mesh::DRS_OK:
282 res = SMESH::DRS_OK; break;
283 case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
284 res = SMESH::DRS_EMPTY; break;
285 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
286 res = SMESH::DRS_WARN_RENUMBER; break;
287 case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
288 res = SMESH::DRS_WARN_SKIP_ELEM; break;
289 case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
291 res = SMESH::DRS_FAIL; break;
296 //=============================================================================
300 * Imports mesh data from MED file
302 //=============================================================================
304 SMESH::DriverMED_ReadStatus
305 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
306 throw ( SALOME::SALOME_Exception )
308 Unexpect aCatch(SALOME_SalomeException);
311 status = _impl->MEDToMesh( theFileName, theMeshName );
313 catch( SALOME_Exception& S_ex ) {
314 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
317 THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
320 CreateGroupServants();
322 int major, minor, release;
323 if( !MED::getMEDVersion( theFileName, major, minor, release ) )
324 major = minor = release = -1;
325 myFileInfo = new SALOME_MED::MedFileInfo();
326 myFileInfo->fileName = theFileName;
327 myFileInfo->fileSize = 0;
330 if ( ::_stati64( theFileName, &d ) != -1 )
333 if ( ::stat64( theFileName, &d ) != -1 )
335 myFileInfo->fileSize = d.st_size;
336 myFileInfo->major = major;
337 myFileInfo->minor = minor;
338 myFileInfo->release = release;
340 return ConvertDriverMEDReadStatus(status);
343 //================================================================================
345 * \brief Return string representation of a MED file version comprising nbDigits
347 //================================================================================
349 char* SMESH_Mesh_i::GetVersionString(SMESH::MED_VERSION version, CORBA::Short nbDigits)
351 string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(MED::EVersion(version),
353 return CORBA::string_dup( ver.c_str() );
356 //=============================================================================
360 * Imports mesh data from MED file
362 //=============================================================================
364 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
365 throw ( SALOME::SALOME_Exception )
367 // Read mesh with name = <theMeshName> into SMESH_Mesh
368 _impl->UNVToMesh( theFileName );
370 CreateGroupServants();
375 //=============================================================================
379 * Imports mesh data from STL file
381 //=============================================================================
382 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
383 throw ( SALOME::SALOME_Exception )
385 // Read mesh with name = <theMeshName> into SMESH_Mesh
386 _impl->STLToMesh( theFileName );
391 //=============================================================================
395 * Imports mesh data from MED file
397 //=============================================================================
399 // int SMESH_Mesh_i::importMEDFile( const char* theFileName, const char* theMeshName )
401 // // Read mesh with name = <theMeshName> and all its groups into SMESH_Mesh
402 // int status = _impl->MEDToMesh( theFileName, theMeshName );
403 // CreateGroupServants();
408 //=============================================================================
412 //=============================================================================
414 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
416 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
417 (SMESH_Hypothesis::Hypothesis_Status theStatus)
420 RETURNCASE( HYP_OK );
421 RETURNCASE( HYP_MISSING );
422 RETURNCASE( HYP_CONCURENT );
423 RETURNCASE( HYP_BAD_PARAMETER );
424 RETURNCASE( HYP_HIDDEN_ALGO );
425 RETURNCASE( HYP_HIDING_ALGO );
426 RETURNCASE( HYP_UNKNOWN_FATAL );
427 RETURNCASE( HYP_INCOMPATIBLE );
428 RETURNCASE( HYP_NOTCONFORM );
429 RETURNCASE( HYP_ALREADY_EXIST );
430 RETURNCASE( HYP_BAD_DIM );
431 RETURNCASE( HYP_BAD_SUBSHAPE );
432 RETURNCASE( HYP_BAD_GEOMETRY );
433 RETURNCASE( HYP_NEED_SHAPE );
436 return SMESH::HYP_UNKNOWN_FATAL;
439 //=============================================================================
443 * calls internal addHypothesis() and then adds a reference to <anHyp> under
444 * the SObject actually having a reference to <aSubShape>.
445 * NB: For this method to work, it is necessary to add a reference to sub-shape first.
447 //=============================================================================
449 SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
450 SMESH::SMESH_Hypothesis_ptr anHyp)
451 throw(SALOME::SALOME_Exception)
453 Unexpect aCatch(SALOME_SalomeException);
454 SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp );
456 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
457 _gen_i->AddHypothesisToShape(_gen_i->GetCurrentStudy(), _this(),
458 aSubShapeObject, anHyp );
460 if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
462 // Update Python script
463 if(_impl->HasShapeToMesh()) {
464 TPythonDump() << "status = " << _this() << ".AddHypothesis( "
465 << aSubShapeObject << ", " << anHyp << " )";
468 TPythonDump() << "status = " << _this() << ".AddHypothesis( "<< anHyp << " )";
471 return ConvertHypothesisStatus(status);
474 //=============================================================================
478 //=============================================================================
480 SMESH_Hypothesis::Hypothesis_Status
481 SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
482 SMESH::SMESH_Hypothesis_ptr anHyp)
484 if(MYDEBUG) MESSAGE("addHypothesis");
486 if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
487 THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
490 SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
491 if (CORBA::is_nil(myHyp))
492 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
495 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
498 TopoDS_Shape myLocSubShape;
499 //use PseudoShape in case if mesh has no shape
501 myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
503 myLocSubShape = _impl->GetShapeToMesh();
505 int hypId = myHyp->GetId();
506 status = _impl->AddHypothesis(myLocSubShape, hypId);
507 if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
508 _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( myHyp );
509 #ifdef WITHGENERICOBJ
510 _mapHypo[hypId]->Register();
512 // assure there is a corresponding submesh
513 if ( !_impl->IsMainShape( myLocSubShape )) {
514 int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
515 if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
516 createSubMesh( aSubShapeObject );
520 catch(SALOME_Exception & S_ex)
522 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
527 //=============================================================================
531 //=============================================================================
533 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
534 SMESH::SMESH_Hypothesis_ptr anHyp)
535 throw(SALOME::SALOME_Exception)
537 Unexpect aCatch(SALOME_SalomeException);
538 SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp );
540 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
541 _gen_i->RemoveHypothesisFromShape(_gen_i->GetCurrentStudy(), _this(),
542 aSubShapeObject, anHyp );
544 // Update Python script
545 // Update Python script
546 if(_impl->HasShapeToMesh()) {
547 TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
548 << aSubShapeObject << ", " << anHyp << " )";
551 TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
555 return ConvertHypothesisStatus(status);
558 //=============================================================================
562 //=============================================================================
564 SMESH_Hypothesis::Hypothesis_Status
565 SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
566 SMESH::SMESH_Hypothesis_ptr anHyp)
568 if(MYDEBUG) MESSAGE("removeHypothesis()");
569 // **** proposer liste de subShape (selection multiple)
571 if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
572 THROW_SALOME_CORBA_EXCEPTION("bad subShape reference", SALOME::BAD_PARAM);
574 SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
575 if (CORBA::is_nil(myHyp))
576 THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
578 SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
581 TopoDS_Shape myLocSubShape;
582 //use PseudoShape in case if mesh has no shape
584 myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
586 myLocSubShape = _impl->GetShapeToMesh();
588 int hypId = myHyp->GetId();
589 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
590 // if ( !SMESH_Hypothesis::IsStatusFatal(status) ) EAP: hyp can be used on many subshapes
591 // _mapHypo.erase( hypId );
593 catch(SALOME_Exception & S_ex)
595 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
600 //=============================================================================
604 //=============================================================================
606 SMESH::ListOfHypothesis *
607 SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
608 throw(SALOME::SALOME_Exception)
610 Unexpect aCatch(SALOME_SalomeException);
611 if (MYDEBUG) MESSAGE("GetHypothesisList");
612 if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShapeObject))
613 THROW_SALOME_CORBA_EXCEPTION("bad subShape reference", SALOME::BAD_PARAM);
615 SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
618 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
619 if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
620 myLocSubShape = _impl->GetShapeToMesh();
621 const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
622 int i = 0, n = aLocalList.size();
625 for ( list<const SMESHDS_Hypothesis*>::const_iterator anIt = aLocalList.begin(); i < n && anIt != aLocalList.end(); anIt++ ) {
626 SMESHDS_Hypothesis* aHyp = (SMESHDS_Hypothesis*)(*anIt);
627 if ( _mapHypo.find( aHyp->GetID() ) != _mapHypo.end() )
628 aList[i++] = SMESH::SMESH_Hypothesis::_narrow( _mapHypo[aHyp->GetID()] );
633 catch(SALOME_Exception & S_ex) {
634 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
637 return aList._retn();
640 //=============================================================================
644 //=============================================================================
645 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject,
646 const char* theName )
647 throw(SALOME::SALOME_Exception)
649 Unexpect aCatch(SALOME_SalomeException);
650 MESSAGE("SMESH_Mesh_i::GetSubMesh");
651 if (CORBA::is_nil(aSubShapeObject))
652 THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
655 SMESH::SMESH_subMesh_var subMesh;
656 SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow(_this());
658 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
660 //Get or Create the SMESH_subMesh object implementation
662 int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
664 if ( !subMeshId && ! _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape ))
666 TopoDS_Iterator it( myLocSubShape );
668 THROW_SALOME_CORBA_EXCEPTION("not sub-shape of the main shape", SALOME::BAD_PARAM);
670 subMesh = getSubMesh( subMeshId );
672 // create a new subMesh object servant if there is none for the shape
673 if ( subMesh->_is_nil() )
674 subMesh = createSubMesh( aSubShapeObject );
675 if ( _gen_i->CanPublishInStudy( subMesh )) {
676 SALOMEDS::SObject_var aSO =
677 _gen_i->PublishSubMesh(_gen_i->GetCurrentStudy(), aMesh,
678 subMesh, aSubShapeObject, theName );
679 if ( !aSO->_is_nil()) {
680 // Update Python script
681 TPythonDump() << aSO << " = " << _this() << ".GetSubMesh( "
682 << aSubShapeObject << ", '" << theName << "' )";
686 catch(SALOME_Exception & S_ex) {
687 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
689 return subMesh._retn();
692 //=============================================================================
696 //=============================================================================
698 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
699 throw (SALOME::SALOME_Exception)
701 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::RemoveSubMesh");
702 if ( theSubMesh->_is_nil() )
705 GEOM::GEOM_Object_var aSubShapeObject;
706 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
707 if ( !aStudy->_is_nil() ) {
708 // Remove submesh's SObject
709 SALOMEDS::SObject_var anSO = _gen_i->ObjectToSObject( aStudy, theSubMesh );
710 if ( !anSO->_is_nil() ) {
711 long aTag = SMESH_Gen_i::GetRefOnShapeTag();
712 SALOMEDS::SObject_var anObj, aRef;
713 if ( anSO->FindSubObject( aTag, anObj ) && anObj->ReferencedObject( aRef ) )
714 aSubShapeObject = GEOM::GEOM_Object::_narrow( aRef->GetObject() );
716 // if ( aSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
717 // aSubShapeObject = theSubMesh->GetSubShape();
719 aStudy->NewBuilder()->RemoveObjectWithChildren( anSO );
721 // Update Python script
722 TPythonDump() << _this() << ".RemoveSubMesh( " << anSO << " )";
726 removeSubMesh( theSubMesh, aSubShapeObject.in() );
729 //=============================================================================
733 //=============================================================================
734 #define CASE2STRING(enum) case SMESH::enum: return "SMESH."#enum;
735 inline TCollection_AsciiString ElementTypeString (SMESH::ElementType theElemType)
737 switch (theElemType) {
742 CASE2STRING( VOLUME );
743 CASE2STRING( ELEM0D );
749 //=============================================================================
753 //=============================================================================
755 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
756 const char* theName )
757 throw(SALOME::SALOME_Exception)
759 Unexpect aCatch(SALOME_SalomeException);
760 SMESH::SMESH_Group_var aNewGroup =
761 SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
763 if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
764 SALOMEDS::SObject_var aSO =
765 _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
766 aNewGroup, GEOM::GEOM_Object::_nil(), theName);
767 if ( !aSO->_is_nil()) {
768 // Update Python script
769 TPythonDump() << aSO << " = " << _this() << ".CreateGroup( "
770 << ElementTypeString(theElemType) << ", '" << theName << "' )";
773 return aNewGroup._retn();
777 //=============================================================================
781 //=============================================================================
782 SMESH::SMESH_GroupOnGeom_ptr SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType theElemType,
784 GEOM::GEOM_Object_ptr theGeomObj)
785 throw(SALOME::SALOME_Exception)
787 Unexpect aCatch(SALOME_SalomeException);
788 SMESH::SMESH_GroupOnGeom_var aNewGroup;
790 TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
791 if ( !aShape.IsNull() )
793 aNewGroup = SMESH::SMESH_GroupOnGeom::_narrow
794 ( createGroup( theElemType, theName, aShape ));
796 if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
797 SALOMEDS::SObject_var aSO =
798 _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
799 aNewGroup, theGeomObj, theName);
800 if ( !aSO->_is_nil()) {
801 // Update Python script
802 TPythonDump() << aSO << " = " << _this() << ".CreateGroupFromGEOM("
803 << ElementTypeString(theElemType) << ", '" << theName << "', "
804 << theGeomObj << " )";
809 return aNewGroup._retn();
812 //=============================================================================
816 //=============================================================================
818 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
819 throw (SALOME::SALOME_Exception)
821 if ( theGroup->_is_nil() )
824 SMESH_GroupBase_i* aGroup =
825 dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
829 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
830 if ( !aStudy->_is_nil() ) {
831 SALOMEDS::SObject_var aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
833 if ( !aGroupSO->_is_nil() ) {
834 // Update Python script
835 TPythonDump() << _this() << ".RemoveGroup( " << aGroupSO << " )";
837 // Remove group's SObject
838 aStudy->NewBuilder()->RemoveObjectWithChildren( aGroupSO );
842 // Remove the group from SMESH data structures
843 removeGroup( aGroup->GetLocalID() );
846 //=============================================================================
847 /*! RemoveGroupWithContents
848 * Remove group with its contents
850 //=============================================================================
851 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
852 throw (SALOME::SALOME_Exception)
854 if ( theGroup->_is_nil() )
857 SMESH_GroupBase_i* aGroup =
858 dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
862 SMESH::long_array_var anIds = aGroup->GetListOfID();
863 SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
865 TPythonDump pyDump; // Supress dump from RemoveNodes/Elements() and RemoveGroup()
868 if ( aGroup->GetType() == SMESH::NODE )
869 aMeshEditor->RemoveNodes( anIds );
871 aMeshEditor->RemoveElements( anIds );
874 RemoveGroup( theGroup );
876 // Update Python script
877 pyDump << _this() << ".RemoveGroupWithContents( " << theGroup << " )";
880 //================================================================================
882 * \brief Get the list of groups existing in the mesh
883 * \retval SMESH::ListOfGroups * - list of groups
885 //================================================================================
887 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
889 Unexpect aCatch(SALOME_SalomeException);
890 if (MYDEBUG) MESSAGE("GetGroups");
892 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
895 TPythonDump aPythonDump;
896 if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
900 aList->length( _mapGroups.size() );
902 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
903 for ( ; it != _mapGroups.end(); it++ ) {
904 if ( CORBA::is_nil( it->second )) continue;
905 aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
907 if (i > 1) aPythonDump << ", ";
908 aPythonDump << it->second;
912 catch(SALOME_Exception & S_ex) {
913 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
916 // Update Python script
917 if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
918 aPythonDump << " ] = " << _this() << ".GetGroups()";
920 return aList._retn();
923 //=============================================================================
925 * Get number of groups existing in the mesh
927 //=============================================================================
929 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
931 Unexpect aCatch(SALOME_SalomeException);
932 return _mapGroups.size();
935 //=============================================================================
937 * New group is created. All mesh elements that are
938 * present in initial groups are added to the new one
940 //=============================================================================
941 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
942 SMESH::SMESH_GroupBase_ptr theGroup2,
943 const char* theName )
944 throw (SALOME::SALOME_Exception)
948 if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
949 theGroup1->GetType() != theGroup2->GetType() )
950 return SMESH::SMESH_Group::_nil();
953 SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
954 if ( aResGrp->_is_nil() )
955 return SMESH::SMESH_Group::_nil();
957 SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
958 SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
960 TColStd_MapOfInteger aResMap;
962 for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
963 aResMap.Add( anIds1[ i1 ] );
965 for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
966 aResMap.Add( anIds2[ i2 ] );
968 SMESH::long_array_var aResIds = new SMESH::long_array;
969 aResIds->length( aResMap.Extent() );
972 TColStd_MapIteratorOfMapOfInteger anIter( aResMap );
973 for( ; anIter.More(); anIter.Next() )
974 aResIds[ resI++ ] = anIter.Key();
976 aResGrp->Add( aResIds );
978 // Clear python lines, created by CreateGroup() and Add()
979 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
980 _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
981 _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
983 // Update Python script
984 TPythonDump() << aResGrp << " = " << _this() << ".UnionGroups( "
985 << theGroup1 << ", " << theGroup2 << ", '"
988 return aResGrp._retn();
992 return SMESH::SMESH_Group::_nil();
996 //=============================================================================
998 \brief Union list of groups. New group is created. All mesh elements that are
999 present in initial groups are added to the new one.
1000 \param theGroups list of groups
1001 \param theName name of group to be created
1002 \return pointer on the group
1004 //=============================================================================
1005 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
1006 const char* theName )
1007 throw (SALOME::SALOME_Exception)
1010 return SMESH::SMESH_Group::_nil();
1014 vector< int > anIds;
1015 SMESH::ElementType aType = SMESH::ALL;
1016 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1018 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1019 if ( CORBA::is_nil( aGrp ) )
1023 SMESH::ElementType aCurrType = aGrp->GetType();
1024 if ( aType == SMESH::ALL )
1028 if ( aType != aCurrType )
1029 return SMESH::SMESH_Group::_nil();
1033 SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1034 for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1036 int aCurrId = aCurrIds[ i ];
1037 anIds.push_back( aCurrId );
1042 SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1043 if ( aResGrp->_is_nil() )
1044 return SMESH::SMESH_Group::_nil();
1046 // Create array of identifiers
1047 SMESH::long_array_var aResIds = new SMESH::long_array;
1048 aResIds->length( anIds.size() );
1050 //NCollection_Map< int >::Iterator anIter( anIds );
1051 for ( int i = 0; i<anIds.size(); i++ )
1053 aResIds[ i ] = anIds[i];
1055 aResGrp->Add( aResIds );
1057 // Clear python lines, created by CreateGroup() and Add()
1058 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1059 _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1060 _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1062 // Update Python script
1064 TPythonDump() << aResGrp << " = " << _this() << ".UnionListOfGroups( "
1065 << &theGroups << ", '" << theName << "' )";
1067 return aResGrp._retn();
1071 return SMESH::SMESH_Group::_nil();
1075 //=============================================================================
1077 * New group is created. All mesh elements that are
1078 * present in both initial groups are added to the new one.
1080 //=============================================================================
1081 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1082 SMESH::SMESH_GroupBase_ptr theGroup2,
1083 const char* theName )
1084 throw (SALOME::SALOME_Exception)
1086 if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
1087 theGroup1->GetType() != theGroup2->GetType() )
1088 return SMESH::SMESH_Group::_nil();
1090 // Create Intersection
1091 SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
1092 if ( aResGrp->_is_nil() )
1095 SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
1096 SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
1098 TColStd_MapOfInteger aMap1;
1100 for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
1101 aMap1.Add( anIds1[ i1 ] );
1103 TColStd_SequenceOfInteger aSeq;
1105 for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
1106 if ( aMap1.Contains( anIds2[ i2 ] ) )
1107 aSeq.Append( anIds2[ i2 ] );
1109 SMESH::long_array_var aResIds = new SMESH::long_array;
1110 aResIds->length( aSeq.Length() );
1112 for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
1113 aResIds[ resI ] = aSeq( resI + 1 );
1115 aResGrp->Add( aResIds );
1117 // Clear python lines, created by CreateGroup() and Add()
1118 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1119 _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1120 _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1122 // Update Python script
1123 TPythonDump() << aResGrp << " = " << _this() << ".IntersectGroups( "
1124 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1126 return aResGrp._retn();
1129 //=============================================================================
1131 \brief Intersect list of groups. New group is created. All mesh elements that
1132 are present in all initial groups simultaneously are added to the new one.
1133 \param theGroups list of groups
1134 \param theName name of group to be created
1135 \return pointer on the group
1137 //=============================================================================
1138 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectListOfGroups(
1139 const SMESH::ListOfGroups& theGroups, const char* theName )
1140 throw (SALOME::SALOME_Exception)
1143 return SMESH::SMESH_Group::_nil();
1147 NCollection_DataMap< int, int > anIdToCount;
1148 SMESH::ElementType aType = SMESH::ALL;
1149 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1151 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1152 if ( CORBA::is_nil( aGrp ) )
1156 SMESH::ElementType aCurrType = aGrp->GetType();
1157 if ( aType == SMESH::ALL )
1161 if ( aType != aCurrType )
1162 return SMESH::SMESH_Group::_nil();
1165 // calculates number of occurance ids in groups
1166 SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1167 for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1169 int aCurrId = aCurrIds[ i ];
1170 if ( !anIdToCount.IsBound( aCurrId ) )
1171 anIdToCount.Bind( aCurrId, 1 );
1173 anIdToCount( aCurrId ) = anIdToCount( aCurrId ) + 1;
1177 // create map of ids
1178 int nbGrp = theGroups.length();
1179 vector< int > anIds;
1180 NCollection_DataMap< int, int >::Iterator anIter( anIdToCount );
1181 for ( ; anIter.More(); anIter.Next() )
1183 int aCurrId = anIter.Key();
1184 int aCurrNb = anIter.Value();
1185 if ( aCurrNb == nbGrp )
1186 anIds.push_back( aCurrId );
1190 SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1191 if ( aResGrp->_is_nil() )
1192 return SMESH::SMESH_Group::_nil();
1194 // Create array of identifiers
1195 SMESH::long_array_var aResIds = new SMESH::long_array;
1196 aResIds->length( anIds.size() );
1198 //NCollection_Map< int >::Iterator aListIter( anIds );
1199 for ( int i = 0; i<anIds.size(); i++ )
1201 aResIds[ i ] = anIds[i];
1203 aResGrp->Add( aResIds );
1205 // Clear python lines, created by CreateGroup() and Add()
1206 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1207 _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1208 _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1210 // Update Python script
1212 TPythonDump() << aResGrp << " = " << _this() << ".IntersectListOfGroups( "
1213 << &theGroups << ", '" << theName << "' )";
1215 return aResGrp._retn();
1219 return SMESH::SMESH_Group::_nil();
1223 //=============================================================================
1225 * New group is created. All mesh elements that are present in
1226 * main group but do not present in tool group are added to the new one
1228 //=============================================================================
1229 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1230 SMESH::SMESH_GroupBase_ptr theGroup2,
1231 const char* theName )
1232 throw (SALOME::SALOME_Exception)
1234 if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
1235 theGroup1->GetType() != theGroup2->GetType() )
1236 return SMESH::SMESH_Group::_nil();
1239 SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
1240 if ( aResGrp->_is_nil() )
1243 SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
1244 SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
1246 TColStd_MapOfInteger aMap2;
1248 for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
1249 aMap2.Add( anIds2[ i2 ] );
1251 TColStd_SequenceOfInteger aSeq;
1252 for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
1253 if ( !aMap2.Contains( anIds1[ i1 ] ) )
1254 aSeq.Append( anIds1[ i1 ] );
1256 SMESH::long_array_var aResIds = new SMESH::long_array;
1257 aResIds->length( aSeq.Length() );
1259 for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
1260 aResIds[ resI ] = aSeq( resI + 1 );
1262 aResGrp->Add( aResIds );
1264 // Clear python lines, created by CreateGroup() and Add()
1265 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1266 _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1267 _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1269 // Update Python script
1270 TPythonDump() << aResGrp << " = " << _this() << ".CutGroups( "
1271 << theGroup1 << ", " << theGroup2 << ", '"
1272 << theName << "' )";
1274 return aResGrp._retn();
1277 //=============================================================================
1279 \brief Cut lists of groups. New group is created. All mesh elements that are
1280 present in main groups but do not present in tool groups are added to the new one
1281 \param theMainGroups list of main groups
1282 \param theToolGroups list of tool groups
1283 \param theName name of group to be created
1284 \return pointer on the group
1286 //=============================================================================
1287 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutListOfGroups(
1288 const SMESH::ListOfGroups& theMainGroups,
1289 const SMESH::ListOfGroups& theToolGroups,
1290 const char* theName )
1291 throw (SALOME::SALOME_Exception)
1294 return SMESH::SMESH_Group::_nil();
1298 set< int > aToolIds;
1299 SMESH::ElementType aType = SMESH::ALL;
1301 // iterate through tool groups
1302 for ( g = 0, n = theToolGroups.length(); g < n; g++ )
1304 SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1305 if ( CORBA::is_nil( aGrp ) )
1309 SMESH::ElementType aCurrType = aGrp->GetType();
1310 if ( aType == SMESH::ALL )
1314 if ( aType != aCurrType )
1315 return SMESH::SMESH_Group::_nil();
1319 SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1320 for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1322 int aCurrId = aCurrIds[ i ];
1323 aToolIds.insert( aCurrId );
1327 vector< int > anIds; // result
1329 // Iterate through main group
1330 for ( g = 0, n = theMainGroups.length(); g < n; g++ )
1332 SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1333 if ( CORBA::is_nil( aGrp ) )
1337 SMESH::ElementType aCurrType = aGrp->GetType();
1338 if ( aType == SMESH::ALL )
1342 if ( aType != aCurrType )
1343 return SMESH::SMESH_Group::_nil();
1347 SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1348 for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1350 int aCurrId = aCurrIds[ i ];
1351 if ( !aToolIds.count( aCurrId ) )
1352 anIds.push_back( aCurrId );
1357 SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1358 if ( aResGrp->_is_nil() )
1359 return SMESH::SMESH_Group::_nil();
1361 // Create array of identifiers
1362 SMESH::long_array_var aResIds = new SMESH::long_array;
1363 aResIds->length( anIds.size() );
1365 for (int i=0; i<anIds.size(); i++ )
1367 aResIds[ i ] = anIds[i];
1369 aResGrp->Add( aResIds );
1371 // Clear python lines, created by CreateGroup() and Add()
1372 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1373 _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1374 _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1376 // Update Python script
1378 TPythonDump() << aResGrp << " = " << _this() << ".CutListOfGroups( "
1379 << &theMainGroups << ", " << &theToolGroups << ", '"
1380 << theName << "' )";
1382 return aResGrp._retn();
1386 return SMESH::SMESH_Group::_nil();
1390 //=============================================================================
1392 \brief Create groups of entities from existing groups of superior dimensions
1394 1) extract all nodes from each group,
1395 2) combine all elements of specified dimension laying on these nodes.
1396 \param theGroups list of source groups
1397 \param theElemType dimension of elements
1398 \param theName name of new group
1399 \return pointer on new group
1401 //=============================================================================
1402 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateDimGroup(
1403 const SMESH::ListOfGroups& theGroups,
1404 SMESH::ElementType theElemType,
1405 const char* theName )
1406 throw (SALOME::SALOME_Exception)
1408 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1410 if ( !theName || !aMeshDS )
1411 return SMESH::SMESH_Group::_nil();
1413 SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1417 // Create map of nodes from all groups
1419 set< int > aNodeMap;
1421 for ( int g = 0, n = theGroups.length(); g < n; g++ )
1423 SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1424 if ( CORBA::is_nil( aGrp ) )
1427 SMESH::ElementType aType = aGrp->GetType();
1428 if ( aType == SMESH::ALL )
1430 else if ( aType == SMESH::NODE )
1432 SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1433 for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1435 int aCurrId = aCurrIds[ i ];
1436 const SMDS_MeshNode* aNode = aMeshDS->FindNode( aCurrId );
1438 aNodeMap.insert( aNode->GetID() );
1443 SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1444 for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1446 int aCurrId = aCurrIds[ i ];
1447 const SMDS_MeshElement* anElem = aMeshDS->FindElement( aCurrId );
1450 SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
1451 while( aNodeIter->more() )
1453 const SMDS_MeshNode* aNode =
1454 dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
1456 aNodeMap.insert( aNode->GetID() );
1462 // Get result identifiers
1464 vector< int > aResultIds;
1465 if ( theElemType == SMESH::NODE )
1467 //NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
1468 set<int>::iterator iter = aNodeMap.begin();
1469 for ( ; iter != aNodeMap.end(); iter++ )
1470 aResultIds.push_back( *iter);
1474 // Create list of elements of given dimension constructed on the nodes
1475 vector< int > anElemList;
1476 //NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
1477 //for ( ; aNodeIter.More(); aNodeIter.Next() )
1478 set<int>::iterator iter = aNodeMap.begin();
1479 for ( ; iter != aNodeMap.end(); iter++ )
1481 const SMDS_MeshElement* aNode =
1482 dynamic_cast<const SMDS_MeshElement*>( aMeshDS->FindNode( *iter ) );
1486 SMDS_ElemIteratorPtr anElemIter = aNode->elementsIterator( anElemType );
1487 while( anElemIter->more() )
1489 const SMDS_MeshElement* anElem =
1490 dynamic_cast<const SMDS_MeshElement*>( anElemIter->next() );
1491 if ( anElem && anElem->GetType() == anElemType )
1492 anElemList.push_back( anElem->GetID() );
1496 // check whether all nodes of elements are present in nodes map
1497 //NCollection_Map< int >::Iterator anIter( anElemList );
1498 //for ( ; anIter.More(); anIter.Next() )
1499 for (int i=0; i< anElemList.size(); i++)
1501 const SMDS_MeshElement* anElem = aMeshDS->FindElement( anElemList[i] );
1506 SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
1507 while( aNodeIter->more() )
1509 const SMDS_MeshNode* aNode =
1510 dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
1511 if ( !aNode || !aNodeMap.count( aNode->GetID() ) )
1518 aResultIds.push_back( anElem->GetID() );
1524 SMESH::SMESH_Group_var aResGrp = CreateGroup( theElemType, theName );
1525 if ( aResGrp->_is_nil() )
1526 return SMESH::SMESH_Group::_nil();
1528 // Create array of identifiers
1529 SMESH::long_array_var aResIds = new SMESH::long_array;
1530 aResIds->length( aResultIds.size() );
1532 //NCollection_Map< int >::Iterator aResIter( aResultIds );
1533 //for ( int i = 0; aResIter.More(); aResIter.Next(), i++ )
1534 for (int i=0; i< aResultIds.size(); i++)
1535 aResIds[ i ] = aResultIds[i];
1536 aResGrp->Add( aResIds );
1538 // Remove strings corresponding to group creation
1539 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1540 _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1541 _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1543 // Update Python script
1545 TPythonDump() << aResGrp << " = " << _this() << ".CreateDimGroup( "
1546 << &theGroups << ", " << theElemType << ", '" << theName << "' )";
1548 return aResGrp._retn();
1552 return SMESH::SMESH_Group::_nil();
1556 //================================================================================
1558 * \brief Remember GEOM group data
1560 //================================================================================
1562 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1563 CORBA::Object_ptr theSmeshObj)
1565 if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1568 SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1569 SALOMEDS::SObject_var groupSO = _gen_i->ObjectToSObject( study, theGeomObj );
1570 if ( groupSO->_is_nil() )
1573 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1574 GEOM::GEOM_IGroupOperations_var groupOp =
1575 geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1576 GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
1579 _geomGroupData.push_back( TGeomGroupData() );
1580 TGeomGroupData & groupData = _geomGroupData.back();
1582 CORBA::String_var entry = groupSO->GetID();
1583 groupData._groupEntry = entry.in();
1585 for ( int i = 0; i < ids->length(); ++i )
1586 groupData._indices.insert( ids[i] );
1588 groupData._smeshObject = theSmeshObj;
1591 //================================================================================
1593 * Remove GEOM group data relating to removed smesh object
1595 //================================================================================
1597 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
1599 list<TGeomGroupData>::iterator
1600 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1601 for ( ; data != dataEnd; ++data ) {
1602 if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
1603 _geomGroupData.erase( data );
1609 //================================================================================
1611 * \brief Return new group contents if it has been changed and update group data
1613 //================================================================================
1615 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
1617 TopoDS_Shape newShape;
1620 SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1621 if ( study->_is_nil() ) return newShape; // means "not changed"
1622 SALOMEDS::SObject_var groupSO = study->FindObjectID( groupData._groupEntry.c_str() );
1623 if ( !groupSO->_is_nil() )
1625 CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
1626 if ( CORBA::is_nil( groupObj )) return newShape;
1627 GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
1629 // get indices of group items
1630 set<int> curIndices;
1631 GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1632 GEOM::GEOM_IGroupOperations_var groupOp =
1633 geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1634 GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
1635 for ( int i = 0; i < ids->length(); ++i )
1636 curIndices.insert( ids[i] );
1638 if ( groupData._indices == curIndices )
1639 return newShape; // group not changed
1642 groupData._indices = curIndices;
1644 GEOM_Client* geomClient = _gen_i->GetShapeReader();
1645 if ( !geomClient ) return newShape;
1646 TCollection_AsciiString groupIOR = geomGen->GetStringFromIOR( geomGroup );
1647 geomClient->RemoveShapeFromBuffer( groupIOR );
1648 newShape = _gen_i->GeomObjectToShape( geomGroup );
1651 if ( newShape.IsNull() ) {
1652 // geom group becomes empty - return empty compound
1653 TopoDS_Compound compound;
1654 BRep_Builder().MakeCompound(compound);
1655 newShape = compound;
1661 //=============================================================================
1663 * \brief Storage of shape and index used in CheckGeomGroupModif()
1665 //=============================================================================
1666 struct TIndexedShape {
1668 TopoDS_Shape _shape;
1669 TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
1672 //=============================================================================
1674 * \brief Update objects depending on changed geom groups
1676 * NPAL16168: geometrical group edition from a submesh don't modifiy mesh computation
1677 * issue 0020210: Update of a smesh group after modification of the associated geom group
1679 //=============================================================================
1681 void SMESH_Mesh_i::CheckGeomGroupModif()
1683 if ( !_impl->HasShapeToMesh() ) return;
1685 SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1686 if ( study->_is_nil() ) return;
1688 CORBA::Long nbEntities = NbNodes() + NbElements();
1690 // Check if group contents changed
1692 typedef map< string, TopoDS_Shape > TEntry2Geom;
1693 TEntry2Geom newGroupContents;
1695 list<TGeomGroupData>::iterator
1696 data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1697 for ( ; data != dataEnd; ++data )
1699 pair< TEntry2Geom::iterator, bool > it_new =
1700 newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
1701 bool processedGroup = !it_new.second;
1702 TopoDS_Shape& newShape = it_new.first->second;
1703 if ( !processedGroup )
1704 newShape = newGroupShape( *data );
1705 if ( newShape.IsNull() )
1706 continue; // no changes
1708 if ( processedGroup ) { // update group indices
1709 list<TGeomGroupData>::iterator data2 = data;
1710 for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
1711 data->_indices = data2->_indices;
1714 // Update SMESH objects according to new GEOM group contents
1716 SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
1717 if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
1719 int oldID = submesh->GetId();
1720 if ( _mapSubMeshIor.find( oldID ) == _mapSubMeshIor.end() )
1722 TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
1724 // update hypotheses
1725 list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
1726 list <const SMESHDS_Hypothesis * >::iterator hypIt;
1727 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1729 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
1730 _impl->AddHypothesis ( newShape, (*hypIt)->GetID());
1732 // care of submeshes
1733 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
1734 int newID = newSubmesh->GetId();
1735 if ( newID != oldID ) {
1736 _mapSubMesh [ newID ] = newSubmesh;
1737 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1738 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1739 _mapSubMesh. erase(oldID);
1740 _mapSubMesh_i. erase(oldID);
1741 _mapSubMeshIor.erase(oldID);
1742 _mapSubMesh_i [ newID ]->changeLocalId( newID );
1747 SMESH::SMESH_GroupOnGeom_var smeshGroup =
1748 SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
1749 if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
1751 SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
1753 ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
1754 SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
1755 ds->SetShape( newShape );
1760 SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
1761 if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
1763 // Remove groups and submeshes basing on removed sub-shapes
1765 TopTools_MapOfShape newShapeMap;
1766 TopoDS_Iterator shapeIt( newShape );
1767 for ( ; shapeIt.More(); shapeIt.Next() )
1768 newShapeMap.Add( shapeIt.Value() );
1770 SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1771 for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
1773 if ( newShapeMap.Contains( shapeIt.Value() ))
1775 TopTools_IndexedMapOfShape oldShapeMap;
1776 TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
1777 for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
1779 const TopoDS_Shape& oldShape = oldShapeMap(i);
1780 int oldInd = meshDS->ShapeToIndex( oldShape );
1782 map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
1783 if ( i_smIor != _mapSubMeshIor.end() ) {
1784 RemoveSubMesh( i_smIor->second ); // one submesh per shape index
1787 map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
1788 for ( ; i_grp != _mapGroups.end(); ++i_grp )
1790 // check if a group bases on oldInd shape
1791 SMESHDS_GroupOnGeom* grpOnGeom = 0;
1792 if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
1793 grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
1794 if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
1796 RemoveGroup( i_grp->second ); // several groups can base on same shape
1797 i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
1802 // Reassign hypotheses and update groups after setting the new shape to mesh
1804 // collect anassigned hypotheses
1805 typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
1806 list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
1807 TShapeHypList assignedHyps;
1808 for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
1810 const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
1811 list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
1812 if ( !hyps.empty() ) {
1813 assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
1814 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1815 _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
1818 // collect shapes supporting groups
1819 typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
1820 TShapeTypeList groupData;
1821 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
1822 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
1823 for ( ; grIt != groups.end(); ++grIt )
1825 if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
1827 ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
1829 // set new shape to mesh -> DS of submeshes and geom groups is deleted
1830 _impl->ShapeToMesh( newShape );
1832 // reassign hypotheses
1833 TShapeHypList::iterator indS_hyps = assignedHyps.begin();
1834 for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
1836 TIndexedShape& geom = indS_hyps->first;
1837 list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
1838 int oldID = geom._index;
1839 int newID = meshDS->ShapeToIndex( geom._shape );
1842 if ( oldID == 1 ) { // main shape
1844 geom._shape = newShape;
1846 for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1847 _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
1848 // care of submeshes
1849 SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
1850 if ( newID != oldID ) {
1851 _mapSubMesh [ newID ] = newSubmesh;
1852 _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1853 _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1854 _mapSubMesh. erase(oldID);
1855 _mapSubMesh_i. erase(oldID);
1856 _mapSubMeshIor.erase(oldID);
1857 _mapSubMesh_i [ newID ]->changeLocalId( newID );
1861 TShapeTypeList::iterator geomType = groupData.begin();
1862 for ( ; geomType != groupData.end(); ++geomType )
1864 const TIndexedShape& geom = geomType->first;
1865 int oldID = geom._index;
1866 if ( _mapGroups.find( oldID ) == _mapGroups.end() )
1869 SALOMEDS::SObject_var groupSO = _gen_i->ObjectToSObject( study,_mapGroups[oldID] );
1870 CORBA::String_var name = groupSO->GetName();
1872 SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID] );
1874 if ( group_i && _impl->AddGroup( geomType->second, name.in(), newID, geom._shape ))
1875 group_i->changeLocalId( newID );
1878 break; // everything has been updated
1881 } // loop on group data
1885 CORBA::Long newNbEntities = NbNodes() + NbElements();
1886 list< SALOMEDS::SObject_var > soToUpdateIcons;
1887 if ( newNbEntities != nbEntities )
1889 // Add all SObjects with icons
1890 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, _this() )); // mesh
1892 for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
1893 i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
1894 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_sm->second ));
1896 for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
1897 i_gr != _mapGroups.end(); ++i_gr ) // groups
1898 soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_gr->second ));
1901 list< SALOMEDS::SObject_var >::iterator so = soToUpdateIcons.begin();
1902 for ( ; so != soToUpdateIcons.end(); ++so )
1903 _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
1906 //=============================================================================
1908 * \brief Create standalone group instead if group on geometry
1910 //=============================================================================
1912 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupOnGeom_ptr theGroup )
1914 SMESH::SMESH_Group_var aGroup;
1915 if ( theGroup->_is_nil() )
1916 return aGroup._retn();
1918 Unexpect aCatch(SALOME_SalomeException);
1920 SMESH_GroupBase_i* aGroupToRem =
1921 dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
1923 return aGroup._retn();
1925 int anId = aGroupToRem->GetLocalID();
1926 if ( !_impl->ConvertToStandalone( anId ) )
1927 return aGroup._retn();
1928 removeGeomGroupData( theGroup );
1930 SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1932 // remove old instance of group from own map
1933 _mapGroups.erase( anId );
1935 SALOMEDS::StudyBuilder_var builder;
1936 SALOMEDS::SObject_var aGroupSO;
1937 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1938 if ( !aStudy->_is_nil() ) {
1939 builder = aStudy->NewBuilder();
1940 aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
1941 if ( !aGroupSO->_is_nil() ) {
1943 // remove reference to geometry
1944 SALOMEDS::ChildIterator_var chItr = aStudy->NewChildIterator(aGroupSO);
1945 for ( ; chItr->More(); chItr->Next() )
1946 // Remove group's child SObject
1947 builder->RemoveObject( chItr->Value() );
1949 // Update Python script
1950 TPythonDump() << aGroupSO << " = " << _this() << ".ConvertToStandalone( "
1951 << aGroupSO << " )";
1955 // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1956 SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
1957 aGroupImpl->Register();
1958 // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1960 // remember new group in own map
1961 aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
1962 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
1964 // register CORBA object for persistence
1965 /*int nextId =*/ _gen_i->RegisterObject( aGroup );
1967 builder->SetIOR( aGroupSO, _gen_i->GetORB()->object_to_string( aGroup ) );
1969 return aGroup._retn();
1972 //=============================================================================
1976 //=============================================================================
1978 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
1980 if(MYDEBUG) MESSAGE( "createSubMesh" );
1981 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
1983 ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
1984 int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
1985 SMESH_subMesh_i *subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
1986 SMESH::SMESH_subMesh_var subMesh
1987 = SMESH::SMESH_subMesh::_narrow(subMeshServant->_this());
1989 _mapSubMesh[subMeshId] = mySubMesh;
1990 _mapSubMesh_i[subMeshId] = subMeshServant;
1991 _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate(subMesh);
1993 // register CORBA object for persistence
1994 int nextId = _gen_i->RegisterObject( subMesh );
1995 if(MYDEBUG) MESSAGE( "Add submesh to map with id = "<< nextId);
1997 // to track changes of GEOM groups
1998 addGeomGroupData( theSubShapeObject, subMesh );
2000 return subMesh._retn();
2003 //=======================================================================
2004 //function : getSubMesh
2006 //=======================================================================
2008 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
2010 map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
2011 if ( it == _mapSubMeshIor.end() )
2012 return SMESH::SMESH_subMesh::_nil();
2014 return SMESH::SMESH_subMesh::_duplicate( (*it).second );
2018 //=============================================================================
2022 //=============================================================================
2024 void SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
2025 GEOM::GEOM_Object_ptr theSubShapeObject )
2027 MESSAGE("SMESH_Mesh_i::removeSubMesh()");
2028 if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
2031 if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
2033 CORBA::Long shapeId = theSubMesh->GetId();
2034 if ( _mapSubMesh.find( shapeId ) != _mapSubMesh.end())
2036 TopoDS_Shape S = _mapSubMesh[ shapeId ]->GetSubShape();
2039 list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
2040 list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
2041 for ( ; hyp != hyps.end(); ++hyp )
2042 _impl->RemoveHypothesis(S, (*hyp)->GetID());
2049 SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
2050 for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
2051 removeHypothesis( theSubShapeObject, aHypList[i] );
2054 catch( const SALOME::SALOME_Exception& ) {
2055 INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
2057 removeGeomGroupData( theSubShapeObject );
2059 int subMeshId = theSubMesh->GetId();
2061 _mapSubMesh.erase(subMeshId);
2062 _mapSubMesh_i.erase(subMeshId);
2063 _mapSubMeshIor.erase(subMeshId);
2064 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeSubMesh() completed");
2067 //=============================================================================
2071 //=============================================================================
2073 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
2074 const char* theName,
2075 const TopoDS_Shape& theShape )
2077 std::string newName;
2078 if ( !theName || strlen( theName ) == 0 )
2080 std::set< std::string > presentNames;
2081 std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
2082 for ( ; i_gr != _mapGroups.end(); ++i_gr )
2083 presentNames.insert( i_gr->second->GetName() );
2085 newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
2086 } while ( !presentNames.insert( newName ).second );
2087 theName = newName.c_str();
2090 SMESH::SMESH_GroupBase_var aGroup;
2091 if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape )) {
2092 SMESH_GroupBase_i* aGroupImpl;
2093 if ( !theShape.IsNull() )
2094 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2096 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2098 // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
2099 SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
2100 aGroupImpl->Register();
2101 // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
2103 aGroup = SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
2104 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2106 // register CORBA object for persistence
2107 int nextId = _gen_i->RegisterObject( aGroup );
2108 if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
2110 // to track changes of GEOM groups
2111 if ( !theShape.IsNull() ) {
2112 GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
2113 addGeomGroupData( geom, aGroup );
2116 return aGroup._retn();
2119 //=============================================================================
2121 * SMESH_Mesh_i::removeGroup
2123 * Should be called by ~SMESH_Group_i()
2125 //=============================================================================
2127 void SMESH_Mesh_i::removeGroup( const int theId )
2129 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
2130 if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
2131 SMESH::SMESH_GroupBase_ptr group = _mapGroups[theId];
2132 _mapGroups.erase( theId );
2133 removeGeomGroupData( group );
2134 if (! _impl->RemoveGroup( theId ))
2136 // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
2137 RemoveGroup( group );
2142 //=============================================================================
2146 //=============================================================================
2148 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
2149 throw(SALOME::SALOME_Exception)
2151 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetLog");
2153 SMESH::log_array_var aLog;
2155 list < SMESHDS_Command * >logDS = _impl->GetLog();
2156 aLog = new SMESH::log_array;
2158 int lg = logDS.size();
2161 list < SMESHDS_Command * >::iterator its = logDS.begin();
2162 while(its != logDS.end()){
2163 SMESHDS_Command *com = *its;
2164 int comType = com->GetType();
2166 int lgcom = com->GetNumber();
2168 const list < int >&intList = com->GetIndexes();
2169 int inum = intList.size();
2171 list < int >::const_iterator ii = intList.begin();
2172 const list < double >&coordList = com->GetCoords();
2173 int rnum = coordList.size();
2175 list < double >::const_iterator ir = coordList.begin();
2176 aLog[indexLog].commandType = comType;
2177 aLog[indexLog].number = lgcom;
2178 aLog[indexLog].coords.length(rnum);
2179 aLog[indexLog].indexes.length(inum);
2180 for(int i = 0; i < rnum; i++){
2181 aLog[indexLog].coords[i] = *ir;
2182 //MESSAGE(" "<<i<<" "<<ir.Value());
2185 for(int i = 0; i < inum; i++){
2186 aLog[indexLog].indexes[i] = *ii;
2187 //MESSAGE(" "<<i<<" "<<ii.Value());
2196 catch(SALOME_Exception & S_ex){
2197 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
2199 return aLog._retn();
2203 //=============================================================================
2207 //=============================================================================
2209 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
2211 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::ClearLog");
2215 //=============================================================================
2219 //=============================================================================
2221 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
2223 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetId");
2227 //=============================================================================
2231 //=============================================================================
2233 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
2238 //=============================================================================
2241 //!< implementation of struct used to call SMESH_Mesh_i::removeGroup() from
2242 // SMESH_Mesh::RemoveGroup() (issue 0020918)
2243 struct TRmGroupCallUp_i : public SMESH_Mesh::TRmGroupCallUp
2245 SMESH_Mesh_i* _mesh;
2246 TRmGroupCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
2247 virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
2251 //=============================================================================
2255 //=============================================================================
2257 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
2259 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
2262 _impl->SetRemoveGroupCallUp( new TRmGroupCallUp_i(this));
2265 //=============================================================================
2269 //=============================================================================
2271 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
2273 if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
2277 //=============================================================================
2279 * Return mesh editor
2281 //=============================================================================
2283 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
2285 // Create MeshEditor
2286 SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, false );
2287 SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
2289 // Update Python script
2290 TPythonDump() << aMeshEditor << " = " << _this() << ".GetMeshEditor()";
2292 return aMesh._retn();
2295 //=============================================================================
2297 * Return mesh edition previewer
2299 //=============================================================================
2301 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
2303 SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, true );
2304 SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
2305 return aMesh._retn();
2308 //================================================================================
2310 * \brief Return true if the mesh has been edited since a last total re-compute
2311 * and those modifications may prevent successful partial re-compute
2313 //================================================================================
2315 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
2317 Unexpect aCatch(SALOME_SalomeException);
2318 return _impl->HasModificationsToDiscard();
2321 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
2323 const int MAX_ATTEMPTS = 100;
2325 double tolerance = 0.5;
2326 SALOMEDS::Color col;
2330 // generate random color
2331 double red = (double)rand() / RAND_MAX;
2332 double green = (double)rand() / RAND_MAX;
2333 double blue = (double)rand() / RAND_MAX;
2334 // check existence in the list of the existing colors
2335 bool matched = false;
2336 std::list<SALOMEDS::Color>::const_iterator it;
2337 for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
2338 SALOMEDS::Color color = *it;
2339 double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B - blue );
2340 matched = tol < tolerance;
2342 if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
2343 ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
2351 //=============================================================================
2355 //=============================================================================
2356 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
2358 Unexpect aCatch(SALOME_SalomeException);
2359 _impl->SetAutoColor(theAutoColor);
2361 TPythonDump pyDump; // not to dump group->SetColor() from below code
2362 pyDump<<_this()<<".SetAutoColor( "<<theAutoColor<<" )";
2364 std::list<SALOMEDS::Color> aReservedColors;
2365 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
2366 for ( ; it != _mapGroups.end(); it++ ) {
2367 if ( CORBA::is_nil( it->second )) continue;
2368 SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
2369 it->second->SetColor( aColor );
2370 aReservedColors.push_back( aColor );
2374 //=============================================================================
2378 //=============================================================================
2379 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
2381 Unexpect aCatch(SALOME_SalomeException);
2382 return _impl->GetAutoColor();
2386 //=============================================================================
2388 * Export in different formats
2390 //=============================================================================
2392 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
2394 return _impl->HasDuplicatedGroupNamesMED();
2397 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
2399 TCollection_AsciiString aFullName ((char*)file);
2400 OSD_Path aPath (aFullName);
2401 OSD_File aFile (aPath);
2402 if (aFile.Exists()) {
2403 // existing filesystem node
2404 if (aFile.KindOfFile() == OSD_FILE) {
2405 if (aFile.IsWriteable()) {
2410 if (aFile.Failed()) {
2411 TCollection_AsciiString msg ("File ");
2412 msg += aFullName + " cannot be replaced.";
2413 THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2416 TCollection_AsciiString msg ("File ");
2417 msg += aFullName + " cannot be overwritten.";
2418 THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2421 TCollection_AsciiString msg ("Location ");
2422 msg += aFullName + " is not a file.";
2423 THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2426 // nonexisting file; check if it can be created
2428 aFile.Build(OSD_WriteOnly, OSD_Protection());
2429 if (aFile.Failed()) {
2430 TCollection_AsciiString msg ("You cannot create the file ");
2431 msg += aFullName + ". Check the directory existance and access rights.";
2432 THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2440 void SMESH_Mesh_i::ExportToMEDX (const char* file,
2441 CORBA::Boolean auto_groups,
2442 SMESH::MED_VERSION theVersion,
2443 CORBA::Boolean overwrite)
2444 throw(SALOME::SALOME_Exception)
2446 Unexpect aCatch(SALOME_SalomeException);
2449 PrepareForWriting(file, overwrite);
2450 const char* aMeshName = "Mesh";
2451 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2452 if ( !aStudy->_is_nil() ) {
2453 SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2454 if ( !aMeshSO->_is_nil() ) {
2455 aMeshName = aMeshSO->GetName();
2456 // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2457 if ( !aStudy->GetProperties()->IsLocked() )
2459 SALOMEDS::GenericAttribute_var anAttr;
2460 SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2461 SALOMEDS::AttributeExternalFileDef_var aFileName;
2462 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2463 aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
2464 ASSERT(!aFileName->_is_nil());
2465 aFileName->SetValue(file);
2466 SALOMEDS::AttributeFileType_var aFileType;
2467 anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2468 aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
2469 ASSERT(!aFileType->_is_nil());
2470 aFileType->SetValue("FICHIERMED");
2474 // Update Python script
2475 // set name of mesh before export
2476 TPythonDump() << _gen_i << ".SetName(" << _this() << ", '" << aMeshName << "')";
2478 // check names of groups
2481 TPythonDump() << _this() << ".ExportToMEDX( r'"
2482 << file << "', " << auto_groups << ", " << theVersion << ", " << overwrite << " )";
2484 _impl->ExportMED( file, aMeshName, auto_groups, theVersion );
2487 void SMESH_Mesh_i::ExportToMED (const char* file,
2488 CORBA::Boolean auto_groups,
2489 SMESH::MED_VERSION theVersion)
2490 throw(SALOME::SALOME_Exception)
2492 ExportToMEDX(file,auto_groups,theVersion,true);
2495 void SMESH_Mesh_i::ExportMED (const char* file,
2496 CORBA::Boolean auto_groups)
2497 throw(SALOME::SALOME_Exception)
2499 ExportToMEDX(file,auto_groups,SMESH::MED_V2_2,true);
2502 void SMESH_Mesh_i::ExportDAT (const char *file)
2503 throw(SALOME::SALOME_Exception)
2505 Unexpect aCatch(SALOME_SalomeException);
2507 // Update Python script
2508 // check names of groups
2510 TPythonDump() << _this() << ".ExportDAT( r'" << file << "' )";
2513 PrepareForWriting(file);
2514 _impl->ExportDAT(file);
2517 void SMESH_Mesh_i::ExportUNV (const char *file)
2518 throw(SALOME::SALOME_Exception)
2520 Unexpect aCatch(SALOME_SalomeException);
2522 // Update Python script
2523 // check names of groups
2525 TPythonDump() << _this() << ".ExportUNV( r'" << file << "' )";
2528 PrepareForWriting(file);
2529 _impl->ExportUNV(file);
2532 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2533 throw(SALOME::SALOME_Exception)
2535 Unexpect aCatch(SALOME_SalomeException);
2537 // Update Python script
2538 // check names of groups
2540 TPythonDump() << _this() << ".ExportSTL( r'" << file << "', " << isascii << " )";
2543 PrepareForWriting(file);
2544 _impl->ExportSTL(file, isascii);
2547 //=============================================================================
2551 //=============================================================================
2553 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
2555 Unexpect aCatch(SALOME_SalomeException);
2556 SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
2557 SALOME_MED::MESH_var aMesh = aMedMesh->_this();
2558 return aMesh._retn();
2561 //=============================================================================
2565 //=============================================================================
2566 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
2568 Unexpect aCatch(SALOME_SalomeException);
2569 return _impl->NbNodes();
2572 //=============================================================================
2576 //=============================================================================
2577 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
2579 Unexpect aCatch(SALOME_SalomeException);
2580 return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes();
2583 //=============================================================================
2587 //=============================================================================
2588 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
2590 Unexpect aCatch(SALOME_SalomeException);
2591 return _impl->Nb0DElements();
2594 //=============================================================================
2598 //=============================================================================
2599 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
2601 Unexpect aCatch(SALOME_SalomeException);
2602 return _impl->NbEdges();
2605 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
2606 throw(SALOME::SALOME_Exception)
2608 Unexpect aCatch(SALOME_SalomeException);
2609 return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
2612 //=============================================================================
2616 //=============================================================================
2617 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
2619 Unexpect aCatch(SALOME_SalomeException);
2620 return _impl->NbFaces();
2623 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
2625 Unexpect aCatch(SALOME_SalomeException);
2626 return _impl->NbTriangles();
2629 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
2631 Unexpect aCatch(SALOME_SalomeException);
2632 return _impl->NbQuadrangles();
2635 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
2637 Unexpect aCatch(SALOME_SalomeException);
2638 return _impl->NbPolygons();
2641 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
2642 throw(SALOME::SALOME_Exception)
2644 Unexpect aCatch(SALOME_SalomeException);
2645 return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
2648 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
2649 throw(SALOME::SALOME_Exception)
2651 Unexpect aCatch(SALOME_SalomeException);
2652 return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
2655 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
2656 throw(SALOME::SALOME_Exception)
2658 Unexpect aCatch(SALOME_SalomeException);
2659 return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
2662 //=============================================================================
2666 //=============================================================================
2667 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
2669 Unexpect aCatch(SALOME_SalomeException);
2670 return _impl->NbVolumes();
2673 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
2675 Unexpect aCatch(SALOME_SalomeException);
2676 return _impl->NbTetras();
2679 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
2681 Unexpect aCatch(SALOME_SalomeException);
2682 return _impl->NbHexas();
2685 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
2687 Unexpect aCatch(SALOME_SalomeException);
2688 return _impl->NbPyramids();
2691 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
2693 Unexpect aCatch(SALOME_SalomeException);
2694 return _impl->NbPrisms();
2697 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
2699 Unexpect aCatch(SALOME_SalomeException);
2700 return _impl->NbPolyhedrons();
2703 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
2704 throw(SALOME::SALOME_Exception)
2706 Unexpect aCatch(SALOME_SalomeException);
2707 return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
2710 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
2711 throw(SALOME::SALOME_Exception)
2713 Unexpect aCatch(SALOME_SalomeException);
2714 return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
2717 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
2718 throw(SALOME::SALOME_Exception)
2720 Unexpect aCatch(SALOME_SalomeException);
2721 return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
2724 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
2725 throw(SALOME::SALOME_Exception)
2727 Unexpect aCatch(SALOME_SalomeException);
2728 return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
2731 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
2732 throw(SALOME::SALOME_Exception)
2734 Unexpect aCatch(SALOME_SalomeException);
2735 return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
2738 //=============================================================================
2742 //=============================================================================
2743 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
2745 Unexpect aCatch(SALOME_SalomeException);
2746 return _mapSubMesh_i.size();
2749 //=============================================================================
2753 //=============================================================================
2754 char* SMESH_Mesh_i::Dump()
2758 return CORBA::string_dup( os.str().c_str() );
2761 //=============================================================================
2765 //=============================================================================
2766 SMESH::long_array* SMESH_Mesh_i::GetIDs()
2768 // SMESH::long_array_var aResult = new SMESH::long_array();
2769 // SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2770 // int aMinId = aSMESHDS_Mesh->MinElementID();
2771 // int aMaxId = aSMESHDS_Mesh->MaxElementID();
2773 // aResult->length(aMaxId - aMinId + 1);
2775 // for (int i = 0, id = aMinId; id <= aMaxId; id++ )
2776 // aResult[i++] = id;
2778 // return aResult._retn();
2780 return GetElementsId();
2783 //=============================================================================
2787 //=============================================================================
2789 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
2790 throw (SALOME::SALOME_Exception)
2792 Unexpect aCatch(SALOME_SalomeException);
2793 MESSAGE("SMESH_Mesh_i::GetElementsId");
2794 SMESH::long_array_var aResult = new SMESH::long_array();
2795 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2797 if ( aSMESHDS_Mesh == NULL )
2798 return aResult._retn();
2800 long nbElements = NbElements();
2801 aResult->length( nbElements );
2802 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2803 for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
2804 aResult[i] = anIt->next()->GetID();
2806 return aResult._retn();
2810 //=============================================================================
2814 //=============================================================================
2816 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
2817 throw (SALOME::SALOME_Exception)
2819 Unexpect aCatch(SALOME_SalomeException);
2820 MESSAGE("SMESH_subMesh_i::GetElementsByType");
2821 SMESH::long_array_var aResult = new SMESH::long_array();
2822 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2824 if ( aSMESHDS_Mesh == NULL )
2825 return aResult._retn();
2827 long nbElements = NbElements();
2829 // No sense in returning ids of elements along with ids of nodes:
2830 // when theElemType == SMESH::ALL, return node ids only if
2831 // there are no elements
2832 if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
2833 return GetNodesId();
2835 aResult->length( nbElements );
2839 SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2840 while ( i < nbElements && anIt->more() ) {
2841 const SMDS_MeshElement* anElem = anIt->next();
2842 if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
2843 aResult[i++] = anElem->GetID();
2846 aResult->length( i );
2848 return aResult._retn();
2851 //=============================================================================
2855 //=============================================================================
2857 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
2858 throw (SALOME::SALOME_Exception)
2860 Unexpect aCatch(SALOME_SalomeException);
2861 MESSAGE("SMESH_subMesh_i::GetNodesId");
2862 SMESH::long_array_var aResult = new SMESH::long_array();
2863 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2865 if ( aSMESHDS_Mesh == NULL )
2866 return aResult._retn();
2868 long nbNodes = NbNodes();
2869 aResult->length( nbNodes );
2870 SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true);
2871 for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
2872 aResult[i] = anIt->next()->GetID();
2874 return aResult._retn();
2877 //=============================================================================
2881 //=============================================================================
2883 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
2884 throw (SALOME::SALOME_Exception)
2886 return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
2889 //=============================================================================
2893 //=============================================================================
2895 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
2896 throw (SALOME::SALOME_Exception)
2898 const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
2900 THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
2902 return ( SMESH::EntityType ) e->GetEntityType();
2905 //=============================================================================
2907 * Returns ID of elements for given submesh
2909 //=============================================================================
2910 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
2911 throw (SALOME::SALOME_Exception)
2913 SMESH::long_array_var aResult = new SMESH::long_array();
2915 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2916 if(!SM) return aResult._retn();
2918 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2919 if(!SDSM) return aResult._retn();
2921 aResult->length(SDSM->NbElements());
2923 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2925 while ( eIt->more() ) {
2926 aResult[i++] = eIt->next()->GetID();
2929 return aResult._retn();
2933 //=============================================================================
2935 * Returns ID of nodes for given submesh
2936 * If param all==true - returns all nodes, else -
2937 * returns only nodes on shapes.
2939 //=============================================================================
2940 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
2941 throw (SALOME::SALOME_Exception)
2943 SMESH::long_array_var aResult = new SMESH::long_array();
2945 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2946 if(!SM) return aResult._retn();
2948 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2949 if(!SDSM) return aResult._retn();
2952 if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
2953 SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
2954 while ( nIt->more() ) {
2955 const SMDS_MeshNode* elem = nIt->next();
2956 theElems.insert( elem->GetID() );
2959 else { // all nodes of submesh elements
2960 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2961 while ( eIt->more() ) {
2962 const SMDS_MeshElement* anElem = eIt->next();
2963 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
2964 while ( nIt->more() ) {
2965 const SMDS_MeshElement* elem = nIt->next();
2966 theElems.insert( elem->GetID() );
2971 aResult->length(theElems.size());
2972 set<int>::iterator itElem;
2974 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
2975 aResult[i++] = *itElem;
2977 return aResult._retn();
2981 //=============================================================================
2983 * Returns type of elements for given submesh
2985 //=============================================================================
2986 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
2987 throw (SALOME::SALOME_Exception)
2989 SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2990 if(!SM) return SMESH::ALL;
2992 SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2993 if(!SDSM) return SMESH::ALL;
2995 if(SDSM->NbElements()==0)
2996 return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
2998 SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2999 const SMDS_MeshElement* anElem = eIt->next();
3000 return ( SMESH::ElementType ) anElem->GetType();
3004 //=============================================================================
3008 //=============================================================================
3010 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
3012 CORBA::LongLong pointeur = CORBA::LongLong(_impl);
3014 MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
3019 //=============================================================================
3021 * Get XYZ coordinates of node as list of double
3022 * If there is not node for given ID - returns empty list
3024 //=============================================================================
3026 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
3028 SMESH::double_array_var aResult = new SMESH::double_array();
3029 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3030 if ( aSMESHDS_Mesh == NULL )
3031 return aResult._retn();
3034 const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3036 return aResult._retn();
3040 aResult[0] = aNode->X();
3041 aResult[1] = aNode->Y();
3042 aResult[2] = aNode->Z();
3043 return aResult._retn();
3047 //=============================================================================
3049 * For given node returns list of IDs of inverse elements
3050 * If there is not node for given ID - returns empty list
3052 //=============================================================================
3054 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
3056 SMESH::long_array_var aResult = new SMESH::long_array();
3057 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3058 if ( aSMESHDS_Mesh == NULL )
3059 return aResult._retn();
3062 const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3064 return aResult._retn();
3066 // find inverse elements
3067 SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
3068 TColStd_SequenceOfInteger IDs;
3069 while(eIt->more()) {
3070 const SMDS_MeshElement* elem = eIt->next();
3071 IDs.Append(elem->GetID());
3073 if(IDs.Length()>0) {
3074 aResult->length(IDs.Length());
3076 for(; i<=IDs.Length(); i++) {
3077 aResult[i-1] = IDs.Value(i);
3080 return aResult._retn();
3083 //=============================================================================
3085 * \brief Return position of a node on shape
3087 //=============================================================================
3089 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
3091 SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
3092 aNodePosition->shapeID = 0;
3093 aNodePosition->shapeType = GEOM::SHAPE;
3095 SMESHDS_Mesh* mesh = _impl->GetMeshDS();
3096 if ( !mesh ) return aNodePosition;
3098 if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
3100 if ( SMDS_PositionPtr pos = aNode->GetPosition() )
3102 aNodePosition->shapeID = aNode->getshapeId();
3103 switch ( pos->GetTypeOfPosition() ) {
3105 aNodePosition->shapeType = GEOM::EDGE;
3106 aNodePosition->params.length(1);
3107 aNodePosition->params[0] =
3108 static_cast<SMDS_EdgePosition*>( pos )->GetUParameter();
3111 aNodePosition->shapeType = GEOM::FACE;
3112 aNodePosition->params.length(2);
3113 aNodePosition->params[0] =
3114 static_cast<SMDS_FacePosition*>( pos )->GetUParameter();
3115 aNodePosition->params[1] =
3116 static_cast<SMDS_FacePosition*>( pos )->GetVParameter();
3118 case SMDS_TOP_VERTEX:
3119 aNodePosition->shapeType = GEOM::VERTEX;
3121 case SMDS_TOP_3DSPACE:
3122 if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
3123 aNodePosition->shapeType = GEOM::SOLID;
3124 else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
3125 aNodePosition->shapeType = GEOM::SHELL;
3131 return aNodePosition;
3134 //=============================================================================
3136 * If given element is node returns IDs of shape from position
3137 * If there is not node for given ID - returns -1
3139 //=============================================================================
3141 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
3143 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3144 if ( aSMESHDS_Mesh == NULL )
3148 const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3150 return aNode->getshapeId();
3157 //=============================================================================
3159 * For given element returns ID of result shape after
3160 * ::FindShape() from SMESH_MeshEditor
3161 * If there is not element for given ID - returns -1
3163 //=============================================================================
3165 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
3167 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3168 if ( aSMESHDS_Mesh == NULL )
3171 // try to find element
3172 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3176 //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
3177 ::SMESH_MeshEditor aMeshEditor(_impl);
3178 int index = aMeshEditor.FindShape( elem );
3186 //=============================================================================
3188 * Returns number of nodes for given element
3189 * If there is not element for given ID - returns -1
3191 //=============================================================================
3193 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
3195 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3196 if ( aSMESHDS_Mesh == NULL ) return -1;
3197 // try to find element
3198 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3199 if(!elem) return -1;
3200 return elem->NbNodes();
3204 //=============================================================================
3206 * Returns ID of node by given index for given element
3207 * If there is not element for given ID - returns -1
3208 * If there is not node for given index - returns -2
3210 //=============================================================================
3212 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
3214 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3215 if ( aSMESHDS_Mesh == NULL ) return -1;
3216 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3217 if(!elem) return -1;
3218 if( index>=elem->NbNodes() || index<0 ) return -1;
3219 return elem->GetNode(index)->GetID();
3222 //=============================================================================
3224 * Returns IDs of nodes of given element
3226 //=============================================================================
3228 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
3230 SMESH::long_array_var aResult = new SMESH::long_array();
3231 if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3233 if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
3235 aResult->length( elem->NbNodes() );
3236 for ( int i = 0; i < elem->NbNodes(); ++i )
3237 aResult[ i ] = elem->GetNode( i )->GetID();
3240 return aResult._retn();
3243 //=============================================================================
3245 * Returns true if given node is medium node
3246 * in given quadratic element
3248 //=============================================================================
3250 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
3252 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3253 if ( aSMESHDS_Mesh == NULL ) return false;
3255 const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3256 if(!aNode) return false;
3257 // try to find element
3258 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
3259 if(!elem) return false;
3261 return elem->IsMediumNode(aNode);
3265 //=============================================================================
3267 * Returns true if given node is medium node
3268 * in one of quadratic elements
3270 //=============================================================================
3272 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
3273 SMESH::ElementType theElemType)
3275 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3276 if ( aSMESHDS_Mesh == NULL ) return false;
3279 const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3280 if(!aNode) return false;
3282 SMESH_MesherHelper aHelper( *(_impl) );
3284 SMDSAbs_ElementType aType;
3285 if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
3286 else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
3287 else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
3288 else aType = SMDSAbs_All;
3290 return aHelper.IsMedium(aNode,aType);
3294 //=============================================================================
3296 * Returns number of edges for given element
3298 //=============================================================================
3300 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
3302 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3303 if ( aSMESHDS_Mesh == NULL ) return -1;
3304 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3305 if(!elem) return -1;
3306 return elem->NbEdges();
3310 //=============================================================================
3312 * Returns number of faces for given element
3314 //=============================================================================
3316 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
3318 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3319 if ( aSMESHDS_Mesh == NULL ) return -1;
3320 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3321 if(!elem) return -1;
3322 return elem->NbFaces();
3325 //=======================================================================
3326 //function : GetElemFaceNodes
3327 //purpose : Returns nodes of given face (counted from zero) for given element.
3328 //=======================================================================
3330 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long elemId,
3331 CORBA::Short faceIndex)
3333 SMESH::long_array_var aResult = new SMESH::long_array();
3334 if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3336 if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) )
3338 SMDS_VolumeTool vtool( elem );
3339 if ( faceIndex < vtool.NbFaces() )
3341 aResult->length( vtool.NbFaceNodes( faceIndex ));
3342 const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
3343 for ( int i = 0; i < aResult->length(); ++i )
3344 aResult[ i ] = nn[ i ]->GetID();
3348 return aResult._retn();
3351 //=======================================================================
3352 //function : FindElementByNodes
3353 //purpose : Returns an element based on all given nodes.
3354 //=======================================================================
3356 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
3358 CORBA::Long elemID(0);
3359 if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
3361 vector< const SMDS_MeshNode * > nn( nodes.length() );
3362 for ( int i = 0; i < nodes.length(); ++i )
3363 if ( !( nn[i] = mesh->FindNode( nodes[i] )))
3366 const SMDS_MeshElement* elem = mesh->FindElement( nn );
3367 if ( !elem && ( _impl->NbEdges( ORDER_QUADRATIC ) ||
3368 _impl->NbFaces( ORDER_QUADRATIC ) ||
3369 _impl->NbVolumes( ORDER_QUADRATIC )))
3370 elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
3372 if ( elem ) elemID = CORBA::Long( elem->GetID() );
3377 //=============================================================================
3379 * Returns true if given element is polygon
3381 //=============================================================================
3383 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
3385 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3386 if ( aSMESHDS_Mesh == NULL ) return false;
3387 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3388 if(!elem) return false;
3389 return elem->IsPoly();
3393 //=============================================================================
3395 * Returns true if given element is quadratic
3397 //=============================================================================
3399 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
3401 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3402 if ( aSMESHDS_Mesh == NULL ) return false;
3403 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3404 if(!elem) return false;
3405 return elem->IsQuadratic();
3409 //=============================================================================
3411 * Returns bary center for given element
3413 //=============================================================================
3415 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
3417 SMESH::double_array_var aResult = new SMESH::double_array();
3418 SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3419 if ( aSMESHDS_Mesh == NULL )
3420 return aResult._retn();
3422 const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3424 return aResult._retn();
3426 if(elem->GetType()==SMDSAbs_Volume) {
3427 SMDS_VolumeTool aTool;
3428 if(aTool.Set(elem)) {
3430 if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
3435 SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
3437 double x=0., y=0., z=0.;
3438 for(; anIt->more(); ) {
3440 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
3454 return aResult._retn();
3458 //=============================================================================
3460 * Create and publish group servants if any groups were imported or created anyhow
3462 //=============================================================================
3464 void SMESH_Mesh_i::CreateGroupServants()
3466 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3469 ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
3470 while ( groupIt->more() )
3472 ::SMESH_Group* group = groupIt->next();
3473 int anId = group->GetGroupDS()->GetID();
3475 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
3476 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3478 addedIDs.insert( anId );
3480 SMESH_GroupBase_i* aGroupImpl;
3482 if ( SMESHDS_GroupOnGeom* groupOnGeom =
3483 dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
3485 aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3486 shape = groupOnGeom->GetShape();
3489 aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3492 // To ensure correct mapping of servant and correct reference counting in GenericObj_i
3493 SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
3494 aGroupImpl->Register();
3496 SMESH::SMESH_GroupBase_var groupVar =
3497 SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
3498 _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
3500 // register CORBA object for persistence
3501 int nextId = _gen_i->RegisterObject( groupVar );
3502 if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
3504 // publishing the groups in the study
3505 if ( !aStudy->_is_nil() ) {
3506 GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
3507 _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
3510 if ( !addedIDs.empty() )
3513 set<int>::iterator id = addedIDs.begin();
3514 for ( ; id != addedIDs.end(); ++id )
3516 map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
3517 int i = std::distance( _mapGroups.begin(), it );
3518 TPythonDump() << it->second << " = " << _this() << ".GetGroups()[ "<< i << " ]";
3523 //=============================================================================
3525 * \brief Return groups cantained in _mapGroups by their IDs
3527 //=============================================================================
3529 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
3531 int nbGroups = groupIDs.size();
3532 SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
3533 aList->length( nbGroups );
3535 list<int>::const_iterator ids = groupIDs.begin();
3536 for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
3538 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
3539 if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3540 aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
3542 aList->length( nbGroups );
3543 return aList._retn();
3546 //=============================================================================
3548 * \brief Return information about imported file
3550 //=============================================================================
3552 SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
3554 SALOME_MED::MedFileInfo_var res( myFileInfo );
3555 if ( !res.operator->() ) {
3556 res = new SALOME_MED::MedFileInfo;
3558 res->fileSize = res->major = res->minor = res->release = -1;
3563 //=============================================================================
3565 * \brief Check and correct names of mesh groups
3567 //=============================================================================
3569 void SMESH_Mesh_i::checkGroupNames()
3571 int nbGrp = NbGroups();
3575 SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3576 if ( aStudy->_is_nil() )
3577 return; // nothing to do
3579 SMESH::ListOfGroups* grpList = 0;
3580 // avoid dump of "GetGroups"
3582 // store python dump into a local variable inside local scope
3583 SMESH::TPythonDump pDump; // do not delete this line of code
3584 grpList = GetGroups();
3587 for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
3588 SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
3591 SALOMEDS::SObject_var aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
3592 if ( aGrpSO->_is_nil() )
3594 // correct name of the mesh group if necessary
3595 const char* guiName = aGrpSO->GetName();
3596 if ( strcmp(guiName, aGrp->GetName()) )
3597 aGrp->SetName( guiName );
3601 //=============================================================================
3603 * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
3605 //=============================================================================
3606 void SMESH_Mesh_i::SetParameters(const char* theParameters)
3608 SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Mesh::_narrow(_this()),
3609 CORBA::string_dup(theParameters));
3612 //=============================================================================
3614 * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
3616 //=============================================================================
3617 char* SMESH_Mesh_i::GetParameters()
3619 SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3620 return CORBA::string_dup(gen->GetParameters(SMESH::SMESH_Mesh::_narrow(_this())));
3623 //=============================================================================
3625 * \brief Returns list of notebook variables used for last Mesh operation
3627 //=============================================================================
3628 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
3630 SMESH::string_array_var aResult = new SMESH::string_array();
3631 SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3633 char *aParameters = GetParameters();
3634 SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy();
3635 if(!aStudy->_is_nil()) {
3636 SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters);
3637 if(aSections->length() > 0) {
3638 SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
3639 aResult->length(aVars.length());
3640 for(int i = 0;i < aVars.length();i++)
3641 aResult[i] = CORBA::string_dup( aVars[i]);
3645 return aResult._retn();
3648 //=======================================================================
3649 //function : GetTypes
3650 //purpose : Returns types of elements it contains
3651 //=======================================================================
3653 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
3655 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
3659 if (_impl->NbEdges())
3660 types[nbTypes++] = SMESH::EDGE;
3661 if (_impl->NbFaces())
3662 types[nbTypes++] = SMESH::FACE;
3663 if (_impl->NbVolumes())
3664 types[nbTypes++] = SMESH::VOLUME;
3665 if (_impl->Nb0DElements())
3666 types[nbTypes++] = SMESH::ELEM0D;
3667 types->length( nbTypes );
3669 return types._retn();
3672 //=======================================================================
3673 //function : GetMesh
3674 //purpose : Returns self
3675 //=======================================================================
3677 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
3679 return SMESH::SMESH_Mesh::_duplicate( _this() );
3682 //=============================================================================
3684 * \brief Returns statistic of mesh elements
3686 //=============================================================================
3687 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
3689 SMESH::long_array_var aRes = new SMESH::long_array();
3690 aRes->length(SMESH::Entity_Last);
3691 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
3693 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
3695 return aRes._retn();
3696 const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
3697 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
3698 aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
3699 return aRes._retn();
3702 //=============================================================================
3704 * \brief Collect statistic of mesh elements given by iterator
3706 //=============================================================================
3707 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
3708 SMESH::long_array& theInfo)
3710 if (!theItr) return;
3711 while (theItr->more())
3712 theInfo[ theItr->next()->GetEntityType() ]++;
3715 //=============================================================================
3717 * \brief mapping of mesh dimension into shape type
3719 //=============================================================================
3720 static TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
3722 TopAbs_ShapeEnum aType = TopAbs_SOLID;
3724 case 0: aType = TopAbs_VERTEX; break;
3725 case 1: aType = TopAbs_EDGE; break;
3726 case 2: aType = TopAbs_FACE; break;
3728 default:aType = TopAbs_SOLID; break;
3733 //=============================================================================
3735 * \brief Internal structure used to find concurent submeshes
3737 * It represents a pair < submesh, concurent dimension >, where
3738 * 'concurrent dimension' is dimension of shape where the submesh can concurent
3739 * with another submesh. In other words, it is dimension of a hypothesis assigned
3742 //=============================================================================
3748 int _dim; //!< a dimension the algo can build (concurrent dimension)
3749 int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
3750 TopTools_MapOfShape _shapeMap;
3751 SMESH_subMesh* _subMesh;
3752 list<const SMESHDS_Hypothesis*> _hypothesises; //!< algo is first, then its parameters
3755 SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
3757 const TopoDS_Shape& theShape)
3759 _subMesh = (SMESH_subMesh*)theSubMesh;
3760 SetShape( theDim, theShape );
3764 void SetShape(const int theDim,
3765 const TopoDS_Shape& theShape)
3768 _ownDim = (int)SMESH_Gen::GetShapeDim(theShape);
3769 if (_dim >= _ownDim)
3770 _shapeMap.Add( theShape );
3772 TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
3773 for( ; anExp.More(); anExp.Next() )
3774 _shapeMap.Add( anExp.Current() );
3778 //! Check sharing of sub shapes
3779 static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
3780 const TopTools_MapOfShape& theToFind,
3781 const TopAbs_ShapeEnum theType)
3783 bool isShared = false;
3784 TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
3785 for (; !isShared && anItr.More(); anItr.Next() ) {
3786 const TopoDS_Shape aSubSh = anItr.Key();
3787 // check for case when concurrent dimensions are same
3788 isShared = theToFind.Contains( aSubSh );
3789 // check for subshape with concurrent dimension
3790 TopExp_Explorer anExp( aSubSh, theType );
3791 for ( ; !isShared && anExp.More(); anExp.Next() )
3792 isShared = theToFind.Contains( anExp.Current() );
3797 //! check algorithms
3798 static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
3799 const SMESHDS_Hypothesis* theA2)
3801 if ( theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
3802 theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
3803 return false; // one of the hypothesis is not algorithm
3804 // check algorithm names (should be equal)
3805 return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
3809 //! Check if subshape hypotheses are concurrent
3810 bool IsConcurrent(const SMESH_DimHyp* theOther) const
3812 if ( _subMesh == theOther->_subMesh )
3813 return false; // same subshape - should not be
3815 // if ( <own dim of either of submeshes> == <concurrent dim> &&
3816 // any of the two submeshes is not on COMPOUND shape )
3817 // -> no concurrency
3818 bool meIsCompound = (_subMesh->GetSubMeshDS() && _subMesh->GetSubMeshDS()->IsComplexSubmesh());
3819 bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() && theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
3820 if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
3823 // bool checkSubShape = ( _dim >= theOther->_dim )
3824 // ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
3825 // : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
3826 bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
3827 if ( !checkSubShape )
3830 // check algorithms to be same
3831 if (!checkAlgo( _hypothesises.front(), theOther->_hypothesises.front() ))
3832 return true; // different algorithms
3834 // check hypothesises for concurrence (skip first as algorithm)
3836 // pointers should be same, becase it is referenes from mesh hypothesis partition
3837 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypothesises.begin();
3838 list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypothesises.end();
3839 for ( hypIt++ /*skip first as algo*/; hypIt != _hypothesises.end(); hypIt++ )
3840 if ( find( theOther->_hypothesises.begin(), otheEndIt, *hypIt ) != otheEndIt )
3842 // the submeshes are concurrent if their algorithms has different parameters
3843 return nbSame != theOther->_hypothesises.size() - 1;
3846 }; // end of SMESH_DimHyp
3848 typedef list<SMESH_DimHyp*> TDimHypList;
3850 static void addDimHypInstance(const int theDim,
3851 const TopoDS_Shape& theShape,
3852 const SMESH_Algo* theAlgo,
3853 const SMESH_subMesh* theSubMesh,
3854 const list <const SMESHDS_Hypothesis*>& theHypList,
3855 TDimHypList* theDimHypListArr )
3857 TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
3858 if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
3859 SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
3860 listOfdimHyp.push_back( dimHyp );
3863 SMESH_DimHyp* dimHyp = listOfdimHyp.back();
3864 dimHyp->_hypothesises.push_front(theAlgo);
3865 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = theHypList.begin();
3866 for( ; hypIt != theHypList.end(); hypIt++ )
3867 dimHyp->_hypothesises.push_back( *hypIt );
3870 static void findConcurrents(const SMESH_DimHyp* theDimHyp,
3871 const TDimHypList& theListOfDimHyp,
3872 TListOfInt& theListOfConcurr )
3874 TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
3875 for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) {
3876 const SMESH_DimHyp* curDimHyp = *rIt;
3877 if ( curDimHyp == theDimHyp )
3878 break; // meet own dimHyp pointer in same dimension
3879 else if ( theDimHyp->IsConcurrent( curDimHyp ) )
3880 if ( find( theListOfConcurr.begin(),
3881 theListOfConcurr.end(),
3882 curDimHyp->_subMesh->GetId() ) == theListOfConcurr.end() )
3883 theListOfConcurr.push_back( curDimHyp->_subMesh->GetId() );
3887 static void unionLists(TListOfInt& theListOfId,
3888 TListOfListOfInt& theListOfListOfId,
3891 TListOfListOfInt::iterator it = theListOfListOfId.begin();
3892 for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
3894 continue; //skip already treated lists
3895 // check if other list has any same submesh object
3896 TListOfInt& otherListOfId = *it;
3897 if ( find_first_of( theListOfId.begin(), theListOfId.end(),
3898 otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
3901 // union two lists (from source into target)
3902 TListOfInt::iterator it2 = otherListOfId.begin();
3903 for ( ; it2 != otherListOfId.end(); it2++ ) {
3904 if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
3905 theListOfId.push_back(*it2);
3907 // clear source list
3908 otherListOfId.clear();
3912 //! free memory allocated for dimension-hypothesis objects
3913 static void removeDimHyps( TDimHypList* theArrOfList )
3915 for (int i = 0; i < 4; i++ ) {
3916 TDimHypList& listOfdimHyp = theArrOfList[i];
3917 TDimHypList::const_iterator it = listOfdimHyp.begin();
3918 for ( ; it != listOfdimHyp.end(); it++ )
3923 //=============================================================================
3925 * \brief Return submesh objects list in meshing order
3927 //=============================================================================
3929 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
3931 SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
3933 SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
3935 return aResult._retn();
3937 ::SMESH_Mesh& mesh = GetImpl();
3938 TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order?
3939 if ( !anOrder.size() ) {
3941 // collect submeshes detecting concurrent algorithms and hypothesises
3942 TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
3944 map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
3945 for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
3946 ::SMESH_subMesh* sm = (*i_sm).second;
3948 const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
3950 // list of assigned hypothesises
3951 const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
3952 // Find out dimensions where the submesh can be concurrent.
3953 // We define the dimensions by algo of each of hypotheses in hypList
3954 list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
3955 for( ; hypIt != hypList.end(); hypIt++ ) {
3956 SMESH_Algo* anAlgo = 0;
3957 const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
3958 if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
3959 // hyp it-self is algo
3960 anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
3962 // try to find algorithm with help of subshapes
3963 TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
3964 for ( ; !anAlgo && anExp.More(); anExp.Next() )
3965 anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
3968 continue; // no assigned algorithm to current submesh
3970 int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
3971 // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDescretBoundary())
3973 // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
3974 for ( int j = anAlgo->NeedDescretBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
3975 addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
3977 } // end iterations on submesh
3979 // iterate on created dimension-hypotheses and check for concurrents
3980 for ( int i = 0; i < 4; i++ ) {
3981 const list<SMESH_DimHyp*>& listOfDimHyp = dimHypListArr[i];
3982 // check for concurrents in own and other dimensions (step-by-step)
3983 TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
3984 for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
3985 const SMESH_DimHyp* dimHyp = *dhIt;
3986 TListOfInt listOfConcurr;
3987 // looking for concurrents and collect into own list
3988 for ( int j = i; j < 4; j++ )
3989 findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr );
3990 // check if any concurrents found
3991 if ( listOfConcurr.size() > 0 ) {
3992 // add own submesh to list of concurrent
3993 listOfConcurr.push_front( dimHyp->_subMesh->GetId() );
3994 anOrder.push_back( listOfConcurr );
3999 removeDimHyps(dimHypListArr);
4001 // now, minimise the number of concurrent groups
4002 // Here we assume that lists of submhes can has same submesh
4003 // in case of multi-dimension algorithms, as result
4004 // list with common submesh have to be union into one list
4006 TListOfListOfInt::iterator listIt = anOrder.begin();
4007 for(; listIt != anOrder.end(); listIt++, listIndx++ )
4008 unionLists( *listIt, anOrder, listIndx + 1 );
4010 // convert submesh ids into interface instances
4011 // and dump command into python
4012 convertMeshOrder( anOrder, aResult, true );
4014 return aResult._retn();
4017 //=============================================================================
4019 * \brief find common submeshes with given submesh
4020 * \param theSubMeshList list of already collected submesh to check
4021 * \param theSubMesh given submesh to intersect with other
4022 * \param theCommonSubMeshes collected common submeshes
4024 //=============================================================================
4026 static void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
4027 const SMESH_subMesh* theSubMesh,
4028 set<const SMESH_subMesh*>& theCommon )
4032 list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
4033 for ( ; it != theSubMeshList.end(); it++ )
4034 theSubMesh->FindIntersection( *it, theCommon );
4035 theSubMeshList.push_back( theSubMesh );
4036 //theCommon.insert( theSubMesh );
4039 //=============================================================================
4041 * \brief Set submesh object order
4042 * \param theSubMeshArray submesh array order
4044 //=============================================================================
4046 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
4049 ::SMESH_Mesh& mesh = GetImpl();
4051 TPythonDump aPythonDump; // prevent dump of called methods
4052 aPythonDump << "isDone = " << _this() << ".SetMeshOrder( [ ";
4054 TListOfListOfInt subMeshOrder;
4055 for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
4057 const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
4058 TListOfInt subMeshIds;
4059 aPythonDump << "[ ";
4060 // Collect subMeshes which should be clear
4061 // do it list-by-list, because modification of submesh order
4062 // take effect between concurrent submeshes only
4063 set<const SMESH_subMesh*> subMeshToClear;
4064 list<const SMESH_subMesh*> subMeshList;
4065 for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
4067 const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
4069 aPythonDump << ", ";
4070 aPythonDump << subMesh;
4071 subMeshIds.push_back( subMesh->GetId() );
4072 // detect common parts of submeshes
4073 if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
4074 findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
4076 aPythonDump << " ]";
4077 subMeshOrder.push_back( subMeshIds );
4079 // clear collected submeshes
4080 set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
4081 for ( ; clrIt != subMeshToClear.end(); clrIt++ ) {
4082 SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt;
4084 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
4085 // ClearSubMesh( *clrIt );
4088 aPythonDump << " ])";
4090 mesh.SetMeshOrder( subMeshOrder );
4096 //=============================================================================
4098 * \brief Convert submesh ids into submesh interfaces
4100 //=============================================================================
4102 void SMESH_Mesh_i::convertMeshOrder
4103 (const TListOfListOfInt& theIdsOrder,
4104 SMESH::submesh_array_array& theResOrder,
4105 const bool theIsDump)
4107 int nbSet = theIdsOrder.size();
4108 TPythonDump aPythonDump; // prevent dump of called methods
4110 aPythonDump << "[ ";
4111 theResOrder.length(nbSet);
4112 TListOfListOfInt::const_iterator it = theIdsOrder.begin();
4114 for( ; it != theIdsOrder.end(); it++ ) {
4115 // translate submesh identificators into submesh objects
4116 // takeing into account real number of concurrent lists
4117 const TListOfInt& aSubOrder = (*it);
4118 if (!aSubOrder.size())
4121 aPythonDump << "[ ";
4122 // convert shape indeces into interfaces
4123 SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
4124 aResSubSet->length(aSubOrder.size());
4125 TListOfInt::const_iterator subIt = aSubOrder.begin();
4126 for( int j = 0; subIt != aSubOrder.end(); subIt++ ) {
4127 if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
4129 SMESH::SMESH_subMesh_var subMesh =
4130 SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
4133 aPythonDump << ", ";
4134 aPythonDump << subMesh;
4136 aResSubSet[ j++ ] = subMesh;
4139 aPythonDump << " ]";
4140 theResOrder[ listIndx++ ] = aResSubSet;
4142 // correct number of lists
4143 theResOrder.length( listIndx );
4146 // finilise python dump
4147 aPythonDump << " ]";
4148 aPythonDump << " = " << _this() << ".GetMeshOrder()";