Salome HOME
23636: EDF 18217 - Problem when suppressing CAD
authoreap <eap@opencascade.com>
Mon, 4 Feb 2019 11:32:58 +0000 (14:32 +0300)
committereap <eap@opencascade.com>
Mon, 4 Feb 2019 11:32:58 +0000 (14:32 +0300)
+
1) optimize standalone group filling
2) fix regressions caused by adding FT_Length3D

src/SMDS/SMDS_MeshGroup.cxx
src/SMESHDS/SMESHDS_Group.cxx
src/SMESHDS/SMESHDS_GroupBase.cxx
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_MeshInfo.cxx
src/SMESHGUI/SMESHGUI_MeshInfosBox.cxx
src/SMESH_I/SMESH_2smeshpy.cxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_SWIG/smeshBuilder.py

index e2f5fbc..c41409c 100644 (file)
@@ -77,10 +77,11 @@ bool SMDS_MeshGroup::Add(const SMDS_MeshElement * theElem)
     return false;
   }
 
-  myElements.insert( theElem );
+  bool added = myElements.insert( theElem ).second;
+
   ++myTic;
 
-  return true;
+  return added;
 }
 
 //=======================================================================
index e6df602..ebcf125 100644 (file)
@@ -105,15 +105,14 @@ bool SMESHDS_Group::Add (const int theID)
 
 bool SMESHDS_Group::Add (const SMDS_MeshElement* aElem )
 {
-  if (!aElem || myGroup.Contains(aElem))
-    return false;
-
-  if (myGroup.IsEmpty())
-    SetType( aElem->GetType() );
-
-  myGroup.Add (aElem);
-  resetIterator();
-  return true;
+  bool added = false;
+  if ( aElem )
+  {
+    added = myGroup.Add (aElem);
+    if ( added )
+      resetIterator();
+  }
+  return added;
 }
 
 //=============================================================================
@@ -124,12 +123,14 @@ bool SMESHDS_Group::Add (const SMDS_MeshElement* aElem )
 
 bool SMESHDS_Group::Remove (const int theID)
 {
-  const SMDS_MeshElement* aElem = findInMesh (theID);
-  if (!aElem || !myGroup.Contains(aElem))
-    return false;
-  myGroup.Remove (aElem);
-  resetIterator();
-  return true;
+  bool removed = false;
+  if ( const SMDS_MeshElement* aElem = findInMesh( theID ))
+  {
+    removed = myGroup.Remove (aElem);
+    if ( removed )
+      resetIterator();
+  }
+  return removed;
 }
 
 
index 95a91cd..0aad7f8 100644 (file)
@@ -126,7 +126,7 @@ bool SMESHDS_GroupBase::IsEmpty()
 {
   if ( myMesh->GetMeshInfo().NbElements( myType ) == 0 )
     // avoid long iteration over sub-meshes of a complex sub-mesh of a group on geometry
-    return false;
+    return true;
   SMDS_ElemIteratorPtr it = GetElements();
   return ( !it || !it->more() );
 }
index 7c386d3..c697a08 100644 (file)
@@ -4992,9 +4992,9 @@ void SMESHGUI::contextMenuPopup( const QString& client, QMenu* menu, QString& ti
     _PTR(Study) study = appStudy->studyDS();
     _PTR(SObject) obj = study->FindObjectID( io->getEntry() );
     if ( obj ) {
-      QString aName = QString( SMESH::fromUtf8(obj->GetName()) );
-      while ( aName.at( aName.length() - 1 ) == ' ' ) // Remove extraspaces in Name of Popup
-          aName.remove( (aName.length() - 1), 1 );
+      QString aName = SMESH::fromUtf8( obj->GetName());
+      while ( !aName.isEmpty() && aName.at( aName.length() - 1 ) == ' ' ) // Remove extraspaces in Name of Popup
+        aName.remove(( aName.length() - 1 ), 1 );
       title = aName;
     }
   }
index bcbd1b8..07239f4 100644 (file)
@@ -974,6 +974,8 @@ void SMESHGUI_BaseInfo::clear()
         widget( i, j )->setProperty( "value", 0 );
     }
   }
+  // hide 'Load' button
+  widget( iEnd, iSingle )->setVisible( false );
 }
 
 /*!
index ff20b1f..91986a2 100644 (file)
@@ -520,7 +520,7 @@ void SMESHGUI_MeshInfosBox::SetMeshInfo(const SMESH::long_array& theInfo)
     // prisms
     myNbPrism    ->setText( QString("%1").arg( theInfo[SMDSEntity_Penta] +
                                                theInfo[SMDSEntity_Quad_Penta] +
-                                                                                          theInfo[SMDSEntity_BiQuad_Penta] ));
+                                               theInfo[SMDSEntity_BiQuad_Penta] ));
     myNbLinPrism   ->setText( QString("%1").arg( theInfo[SMDSEntity_Penta] ));
     myNbQuadPrism  ->setText( QString("%1").arg( theInfo[SMDSEntity_Quad_Penta] ));
     myNbBiQuadPrism->setText( QString("%1").arg( theInfo[SMDSEntity_BiQuad_Penta] ));
index e76d1b3..69b3b0f 100644 (file)
@@ -296,6 +296,8 @@ namespace {
     //   - FT_NodeConnectivityNumber= 22
     // v 8.5.0: FT_Undefined == 49, new items:
     //   - FT_Deflection2D          = 22
+    // v 9.3.0: FT_Undefined == 50, new items:
+    //   - FT_Length3D              = 22
     //
     // It's necessary to continue recording this history and to fill
     // undef2newItems (see below) accordingly.
@@ -319,6 +321,7 @@ namespace {
       undef2newItems[ 47 ].push_back( 22 );
       undef2newItems[ 48 ].push_back( 22 );
       undef2newItems[ 49 ].push_back( 22 );
+      undef2newItems[ 50 ].push_back( 22 );
 
       ASSERT( undef2newItems.rbegin()->first == SMESH::FT_Undefined );
     }
index c61a7da..a926430 100644 (file)
@@ -240,7 +240,7 @@ GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
         for ( ; data != _geomGroupData.end(); ++data )
           if ( data->_smeshObject->_is_equivalent( _this() ))
           {
-            SALOMEDS::SObject_wrap so = SMESH_Gen_i::getStudyServant()->FindObjectID( data->_groupEntry.c_str() );
+            SALOMEDS::SObject_wrap so = _gen_i->getStudyServant()->FindObjectID( data->_groupEntry.c_str() );
             CORBA::Object_var     obj = _gen_i->SObjectToObject( so );
             aShapeObj = GEOM::GEOM_Object::_narrow( obj );
             break;
@@ -772,6 +772,9 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
   if (CORBA::is_nil( anHyp ))
     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
 
+  if ( _preMeshInfo )
+    _preMeshInfo->ForgetOrLoad();
+
   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
   try
   {
@@ -955,7 +958,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
     // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
     //   aSubShape = theSubMesh->GetSubShape();
 
-    SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::getStudyServant()->NewBuilder();
+    SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
     builder->RemoveObjectWithChildren( anSO );
 
     // Update Python script
@@ -2075,11 +2078,66 @@ namespace
   struct TGroupOnGeomData
   {
     int                 _oldID;
-    int                 _shapeID;
+    TopoDS_Shape        _shape;
     SMDSAbs_ElementType _type;
     std::string         _name;
     Quantity_Color      _color;
+
+    TGroupOnGeomData( const SMESHDS_GroupOnGeom* group )
+    {
+      _oldID = group->GetID();
+      _type  = group->GetType();
+      _name  = group->GetStoreName();
+      _color = group->GetColor();
+    }
   };
+
+  //-----------------------------------------------------------------------------
+  /*!
+   * \brief Check if a filter is still valid after geometry removal
+   */
+  bool isValidGeomFilter( SMESH::Filter_var theFilter )
+  {
+    if ( theFilter->_is_nil() )
+      return false;
+    SMESH::Filter::Criteria_var criteria;
+    theFilter->GetCriteria( criteria.out() );
+
+    for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
+    {
+      const char* thresholdID = criteria[ iCr ].ThresholdID.in();
+      std::string entry;
+      switch ( criteria[ iCr ].Type )
+      {
+      case SMESH::FT_BelongToGeom:
+      case SMESH::FT_BelongToPlane:
+      case SMESH::FT_BelongToCylinder:
+      case SMESH::FT_BelongToGenSurface:
+      case SMESH::FT_LyingOnGeom:
+        entry = thresholdID;
+        break;
+      case SMESH::FT_ConnectedElements:
+        if ( thresholdID )
+        {
+          entry = thresholdID;
+          break;
+        }
+      default:
+        continue;
+      }
+      SMESH_Gen_i*           gen = SMESH_Gen_i::GetSMESHGen();
+      SALOMEDS::SObject_wrap  so = gen->getStudyServant()->FindObjectID( entry.c_str() );
+      if ( so->_is_nil() )
+        return false;
+      CORBA::Object_var      obj = so->GetObject();
+      GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj );
+      if ( gen->GeomObjectToShape( geom ).IsNull() )
+        return false;
+
+    } // loop on criteria
+
+    return true;
+  }
 }
 
 //=============================================================================
@@ -2092,19 +2150,67 @@ namespace
 
 void SMESH_Mesh_i::CheckGeomModif()
 {
+  SMESH::SMESH_Mesh_var me = _this();
+  GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
+
+  //bool removedFromClient = false;
+
+  if ( mainGO->_is_nil() ) // GEOM_Client cleared or geometry removed? (IPAL52735, PAL23636)
+  {
+    //removedFromClient = _impl->HasShapeToMesh();
+
+    // try to find geometry by study reference
+    SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
+    SALOMEDS::SObject_wrap geomRefSO, geomSO;
+    if ( !meshSO->_is_nil() &&
+         meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
+         geomRefSO->ReferencedObject( geomSO.inout() ))
+    {
+      CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
+      mainGO = GEOM::GEOM_Object::_narrow( geomObj );
+    }
+
+    if ( mainGO->_is_nil() &&    // geometry removed ==>
+         !geomRefSO->_is_nil() ) // remove geom dependent data: sub-meshes etc.
+    {
+      // convert geom dependent groups into standalone ones
+      CheckGeomGroupModif();
+
+      _impl->ShapeToMesh( TopoDS_Shape() );
+
+      // remove sub-meshes
+      std::map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
+      while ( i_sm != _mapSubMeshIor.end() )
+      {
+        SMESH::SMESH_subMesh_ptr sm = i_sm->second;
+        ++i_sm;
+        RemoveSubMesh( sm );
+      }
+      // remove all children except groups in the study
+      SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
+      SALOMEDS::SObject_wrap so;
+      for ( CORBA::Long tag = SMESH::Tag_RefOnShape; tag <= SMESH::Tag_LastSubMesh; ++tag )
+        if ( meshSO->FindSubObject( tag, so.inout() ))
+          builder->RemoveObjectWithChildren( so );
+
+      _gen_i->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED" );
+
+      return;
+    }
+  }
+
   if ( !_impl->HasShapeToMesh() ) return;
 
-  GEOM::GEOM_Object_var mainGO = _gen_i->ShapeToGeomObject( _impl->GetShapeToMesh() );
-  //if ( mainGO->_is_nil() ) return;
 
   // Update after group modification
 
-  if ( mainGO->_is_nil() || /* shape was removed from GEOM_Client by newGroupShape()
-                               called by other mesh (IPAL52735) */
-       mainGO->GetType() == GEOM_GROUP ||
+  if ( mainGO->GetType() == GEOM_GROUP ||    // is group or not modified
        mainGO->GetTick() == _mainShapeTick )
   {
+    int nb = NbNodes() + NbElements();
     CheckGeomGroupModif();
+    if ( nb != NbNodes() + NbElements() ) // something removed due to hypotheses change
+      _gen_i->UpdateIcons( me );
     return;
   }
 
@@ -2131,23 +2237,35 @@ void SMESH_Mesh_i::CheckGeomModif()
   SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
 
   // store data of groups on geometry
-  vector< TGroupOnGeomData > groupsData;
-  const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
+  std::vector< TGroupOnGeomData > groupsData;
+  const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
   groupsData.reserve( groups.size() );
-  set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
+  std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
   for ( ; g != groups.end(); ++g )
+  {
     if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
     {
-      TGroupOnGeomData data;
-      data._oldID   = group->GetID();
-      data._shapeID = meshDS->ShapeToIndex( group->GetShape() );
-      data._type    = group->GetType();
-      data._name    = group->GetStoreName();
-      data._color   = group->GetColor();
-      groupsData.push_back( data );
+      groupsData.push_back( TGroupOnGeomData( group ));
+
+      // get a new shape
+      SMESH::SMESH_GroupOnGeom_var gog;
+      std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.find( group->GetID() );
+      if ( i_grp != _mapGroups.end() )
+        gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second );
+
+      GEOM::GEOM_Object_var geom;
+      if ( !gog->_is_nil() )
+        geom = gog->GetShape();
+      if ( !geom->_is_nil() )
+      {
+        CORBA::String_var ior = geomGen->GetStringFromIOR( geom );
+        geomClient->RemoveShapeFromBuffer( ior.in() );
+        groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
+      }
     }
+  }
   // store assigned hypotheses
-  vector< pair< int, THypList > > ids2Hyps;
+  std::vector< pair< int, THypList > > ids2Hyps;
   const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
   for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
   {
@@ -2162,7 +2280,7 @@ void SMESH_Mesh_i::CheckGeomModif()
   _impl->ShapeToMesh( newShape );
 
   // re-add shapes of geom groups
-  list<TGeomGroupData>::iterator data = _geomGroupData.begin();
+  std::list<TGeomGroupData>::iterator data = _geomGroupData.begin();
   for ( ; data != _geomGroupData.end(); ++data )
   {
     TopoDS_Shape newShape = newGroupShape( *data );
@@ -2192,36 +2310,28 @@ void SMESH_Mesh_i::CheckGeomModif()
       _impl->AddHypothesis( s, (*h)->GetID() );
   }
 
-  // restore groups
+  // restore groups on geometry
   for ( size_t i = 0; i < groupsData.size(); ++i )
   {
     const TGroupOnGeomData& data = groupsData[i];
+    if ( data._shape.IsNull() )
+      continue;
 
-    map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
+    std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
     if ( i2g == _mapGroups.end() ) continue;
 
     SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
     if ( !gr_i ) continue;
 
-    int id;
-    SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), id,
-                                      meshDS->IndexToShape( data._shapeID ));
+    SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape );
     if ( !g )
-    {
       _mapGroups.erase( i2g );
-    }
     else
-    {
       g->GetGroupDS()->SetColor( data._color );
-      gr_i->changeLocalId( id );
-      _mapGroups[ id ] = i2g->second;
-      if ( data._oldID != id )
-        _mapGroups.erase( i2g );
-    }
   }
 
   // update _mapSubMesh
-  map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
+  std::map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
   for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
     i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
 
@@ -2238,6 +2348,98 @@ void SMESH_Mesh_i::CheckGeomModif()
 
 void SMESH_Mesh_i::CheckGeomGroupModif()
 {
+  // remove sub-meshes referring a removed sub-shapes (if main shape still exists)
+  SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
+  GEOM::GEOM_Object_var  mainGO = GetShapeToMesh();
+  SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() ));
+  if ( !mainGO->_is_nil() && !meshSO->_is_nil() )
+  {
+    SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO;
+    for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag )
+      if ( meshSO->FindSubObject( tag, rootSO.inout() ))
+      {
+        int nbValid = 0, nbRemoved = 0;
+        SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO );
+        for ( ; chItr->More(); chItr->Next() )
+        {
+          SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO
+          if ( !smSO->_is_nil() &&
+               smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
+               geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference
+          {
+            CORBA::Object_var  geomObj = _gen_i->SObjectToObject( geomSO );
+            GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj );
+            if ( !geom->_non_existent() )
+            {
+              ++nbValid;
+              continue; // keep the sub-mesh
+            }
+          }
+          CORBA::Object_var     smObj = _gen_i->SObjectToObject( smSO );
+          SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj );
+          if ( !sm->_is_nil() && !sm->_non_existent() )
+          {
+            GEOM::GEOM_Object_var smGeom = sm->GetSubShape();
+            if ( smGeom->_is_nil() )
+            {
+              RemoveSubMesh( sm );
+              ++nbRemoved;
+            }
+          }
+          else
+          {
+            if ( _preMeshInfo )
+              _preMeshInfo->ForgetAllData(); // unknown hypothesis modified
+            builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH
+            ++nbRemoved;
+          }
+        }
+        if ( /*nbRemoved > 0 &&*/ nbValid == 0 )
+          builder->RemoveObjectWithChildren( rootSO );
+      }
+  }
+
+  // check for removed sub-shapes and convert geom dependent groups into standalone ones
+  std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
+  while ( i_gr != _mapGroups.end())
+  {
+    SMESH::SMESH_GroupBase_ptr group = i_gr->second;
+    ++i_gr;
+    SALOMEDS::SObject_wrap        groupSO = _gen_i->ObjectToSObject( group ), refSO;
+    SMESH::SMESH_GroupOnGeom_var   onGeom = SMESH::SMESH_GroupOnGeom::_narrow  ( group );
+    SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group );
+    bool isValidGeom = false;
+    if ( !onGeom->_is_nil() )
+    {
+      isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() );
+    }
+    else if ( !onFilt->_is_nil() )
+    {
+      isValidGeom = isValidGeomFilter( onFilt->GetFilter() );
+    }
+    else // standalone
+    {
+      isValidGeom = ( !groupSO->_is_nil() &&
+                      !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ));
+    }
+    if ( !isValidGeom )
+    {
+      if ( !IsLoaded() || group->IsEmpty() )
+      {
+        RemoveGroup( group );
+      }
+      else if ( !onGeom->_is_nil() || !onFilt->_is_nil() )
+      {
+        SMESH::SMESH_Group_var ( ConvertToStandalone( group ));
+      }
+      else // is it possible?
+      {
+        builder->RemoveObjectWithChildren( refSO );
+      }
+    }
+  }
+
+
   if ( !_impl->HasShapeToMesh() ) return;
 
   CORBA::Long nbEntities = NbNodes() + NbElements();
@@ -2384,7 +2586,7 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
           groupData.push_back
             ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
       }
-      // set new shape to mesh -> DS of sub-meshes and geom groups are deleted
+      // set new shape to mesh -> DS of sub-meshes and geom groups is deleted
       _impl->Clear();
       _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
       _impl->ShapeToMesh( newShape );
@@ -2510,9 +2712,11 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase
       // remove reference to geometry
       SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
       for ( ; chItr->More(); chItr->Next() )
+      {
         // Remove group's child SObject
-        builder->RemoveObject( chItr->Value() );
-
+        SALOMEDS::SObject_wrap so = chItr->Value();
+        builder->RemoveObject( so );
+      }
       // Update Python script
       TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
                     << ".ConvertToStandalone( " << aGroupSO << " )";
@@ -2520,9 +2724,9 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase
       // change icon of Group on Filter
       if ( isOnFilter )
       {
-        SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
-        const int isEmpty = ( elemTypes->length() == 0 );
-        if ( !isEmpty )
+        // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
+        // const int isEmpty = ( elemTypes->length() == 0 );
+        // if ( !isEmpty )
         {
           SALOMEDS::GenericAttribute_wrap anAttr =
             builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
@@ -2631,14 +2835,17 @@ bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
 
   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
   {
-    if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end() &&
-         _mapSubMesh[ subMeshId ])
+    SMESH_subMesh* sm;
+    if (( _mapSubMesh.count( subMeshId )) &&
+        ( sm = _impl->GetSubMeshContaining( subMeshId )))
     {
-      TopoDS_Shape S = _mapSubMesh[ subMeshId ]->GetSubShape();
+      TopoDS_Shape S = sm->GetSubShape();
       if ( !S.IsNull() )
       {
         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
         isHypChanged = !hyps.empty();
+        if ( isHypChanged && _preMeshInfo )
+          _preMeshInfo->ForgetOrLoad();
         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
         for ( ; hyp != hyps.end(); ++hyp )
           _impl->RemoveHypothesis(S, (*hyp)->GetID());
index f3e8362..ffeaa7c 100755 (executable)
@@ -745,10 +745,13 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
                 mergeTolerance: tolerance for merging nodes
                 allGroups: forces creation of groups corresponding to every input mesh
                 name: name of a new mesh
-                meshToAppendTo a mesh to append all given meshes
+                meshToAppendTo: a mesh to append all given meshes
 
         Returns:
                 an instance of class :class:`Mesh`
+
+        See also: 
+                :meth:`Mesh.Append`
         """
 
         if not meshes: return None
@@ -1190,6 +1193,8 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
             functor = aFilterMgr.CreateLength()
         elif theCriterion == FT_Length2D:
             functor = aFilterMgr.CreateLength2D()
+        elif theCriterion == FT_Length3D:
+            functor = aFilterMgr.CreateLength3D()
         elif theCriterion == FT_Deflection2D:
             functor = aFilterMgr.CreateDeflection2D()
         elif theCriterion == FT_NodeConnectivityNumber: