+//================================================================================
+/*!
+* \brief Replace a shape in the mesh upon Break Link
+*/
+//================================================================================
+
+void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom)
+{
+ // check if geometry changed
+ bool geomChanged = true;
+ GEOM::GEOM_Object_var oldGeom = GetShapeToMesh();
+ if ( !theNewGeom->_is_nil() && !oldGeom->_is_nil() )
+ geomChanged = ( oldGeom->GetTick() != theNewGeom->GetTick() );
+
+ TopoDS_Shape S = _impl->GetShapeToMesh();
+ GEOM_Client* geomClient = _gen_i->GetShapeReader();
+ TCollection_AsciiString aIOR;
+ if ( geomClient->Find( S, aIOR ))
+ geomClient->RemoveShapeFromBuffer( aIOR );
+
+ // clear buffer also for sub-groups
+ SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
+ const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
+ std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
+ for (; g != groups.end(); ++g)
+ if (const SMESHDS_GroupOnGeom* group = dynamic_cast<SMESHDS_GroupOnGeom*>(*g))
+ {
+ const TopoDS_Shape& s = group->GetShape();
+ if ( geomClient->Find( s, aIOR ))
+ geomClient->RemoveShapeFromBuffer( aIOR );
+ }
+
+ // clear buffer also for sub-meshes
+ std::map<int, SMESH_subMesh_i*>::const_iterator aSubMeshIter = _mapSubMesh_i.cbegin();
+ for(; aSubMeshIter != _mapSubMesh_i.cend(); aSubMeshIter++) {
+ int aShapeID = aSubMeshIter->first;
+ const TopoDS_Shape& aSubShape = meshDS->IndexToShape(aShapeID);
+ TCollection_AsciiString aShapeIOR;
+ if ( geomClient->Find( aSubShape, aShapeIOR ))
+ geomClient->RemoveShapeFromBuffer( aShapeIOR );
+ }
+
+ typedef struct {
+ int shapeID; smIdType fromID, toID; // indices of elements of a sub-mesh
+ } TRange;
+ std::vector< TRange > elemRanges, nodeRanges; // elements of sub-meshes
+ std::vector< SMDS_PositionPtr > positions; // node positions
+ if ( !geomChanged )
+ {
+ // store positions of elements on geometry
+ Load();
+ if ( meshDS->MaxNodeID() > meshDS->NbNodes() ||
+ meshDS->MaxElementID() > meshDS->NbElements() )
+ {
+ meshDS->Modified();
+ meshDS->CompactMesh();
+ }
+ positions.resize( meshDS->NbNodes() + 1 );
+ for ( SMDS_NodeIteratorPtr nodeIt = meshDS->nodesIterator(); nodeIt->more(); )
+ {
+ const SMDS_MeshNode* n = nodeIt->next();
+ positions[ n->GetID() ] = n->GetPosition();
+ }
+
+ // remove elements from sub-meshes to avoid their removal at hypotheses addition
+ for ( int isNode = 0; isNode < 2; ++isNode )
+ {
+ std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
+ ranges.reserve( meshDS->MaxShapeIndex() + 10 );
+ ranges.push_back( TRange{ 0,0,0 });
+ SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
+ while ( elemIt->more() )
+ {
+ const SMDS_MeshElement* e = elemIt->next();
+ const smIdType elemID = e->GetID();
+ const int shapeID = e->GetShapeID();
+ TRange & lastRange = ranges.back();
+ if ( lastRange.shapeID != shapeID ||
+ lastRange.toID != elemID )
+ ranges.push_back( TRange{ shapeID, elemID, elemID + 1 });
+ else
+ lastRange.toID = elemID + 1;
+
+ if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( shapeID ))
+ {
+ if ( isNode ) sm->RemoveNode( static_cast< const SMDS_MeshNode *>( e ));
+ else sm->RemoveElement( e );
+ }
+ }
+ }
+ }
+
+
+ // update the reference to theNewGeom (needed for correct execution of a dumped python script)
+ SMESH::SMESH_Mesh_var me = _this();
+ SALOMEDS::SObject_wrap aSO = _gen_i->ObjectToSObject( me );
+ CORBA::String_var entry = theNewGeom->GetStudyEntry();
+ if ( !aSO->_is_nil() )
+ {
+ SALOMEDS::SObject_wrap aShapeRefSO;
+ if ( aSO->FindSubObject( _gen_i->GetRefOnShapeTag(), aShapeRefSO.inout() ))
+ {
+ SALOMEDS::SObject_wrap aShapeSO = _gen_i->getStudyServant()->FindObjectID( entry );
+ SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
+ builder->Addreference( aShapeRefSO, aShapeSO );
+ }
+ }
+
+ // re-assign global hypotheses to the new shape
+ _mainShapeTick = geomChanged ? -1 : theNewGeom->GetTick();
+ CheckGeomModif( true );
+
+ if ( !geomChanged )
+ {
+ // restore positions of elements on geometry
+ for ( int isNode = 0; isNode < 2; ++isNode )
+ {
+ std::vector< TRange > & ranges = isNode ? nodeRanges : elemRanges;
+ for ( size_t i = 1; i < ranges.size(); ++i )
+ {
+ int elemID = ranges[ i ].fromID;
+ int toID = ranges[ i ].toID;
+ SMESHDS_SubMesh * smDS = meshDS->NewSubMesh( ranges[ i ].shapeID );
+ if ( isNode )
+ for ( ; elemID < toID; ++elemID )
+ smDS->AddNode( meshDS->FindNode( elemID ));
+ else
+ for ( ; elemID < toID; ++elemID )
+ smDS->AddElement( meshDS->FindElement( elemID ));
+
+ if ( SMESH_subMesh* sm = _impl->GetSubMeshContaining( ranges[ i ].shapeID ))
+ sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+ }
+ }
+ for ( unsigned int nodeID = 1; nodeID < positions.size(); ++nodeID )
+ if ( positions[ nodeID ])
+ if ( SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( meshDS->FindNode( nodeID )))
+ n->SetPosition( positions[ nodeID ], n->GetShapeID() );
+
+ // restore icons
+ _gen_i->UpdateIcons( SMESH::SMESH_Mesh_var( _this() ));
+ }
+
+ TPythonDump() << "SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject("
+ << me <<".GetMesh()), " << entry.in() << ")";
+
+ TPythonDump() << me << ".ReplaceShape( " << entry.in() << " )";
+
+}
+