]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Debug of the selector filter by neighbors and make sketch results stored in the data...
authormpv <mpv@opencascade.com>
Wed, 17 Oct 2018 10:38:03 +0000 (13:38 +0300)
committermpv <mpv@opencascade.com>
Fri, 26 Oct 2018 17:06:01 +0000 (20:06 +0300)
19 files changed:
src/ConstructionPlugin/ConstructionPlugin_Point.cpp
src/GeomAPI/GeomAPI_PlanarEdges.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_BodyBuilder.cpp
src/Model/Model_BodyBuilder.h
src/Model/Model_Data.h
src/Model/Model_Objects.cpp
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultConstruction.cpp
src/Model/Model_ResultConstruction.h
src/ModelAPI/ModelAPI_BodyBuilder.h
src/ModelAPI/ModelAPI_ResultConstruction.h
src/Selector/CMakeLists.txt
src/Selector/Selector_NExplode.cpp [new file with mode: 0644]
src/Selector/Selector_NExplode.h [new file with mode: 0644]
src/Selector/Selector_Selector.cpp
src/Selector/Selector_Selector.h
src/SketchPlugin/SketchPlugin_Feature.h
src/SketchPlugin/SketchPlugin_Sketch.h

index bb59c3d550acee82307197fd38c07ec3a372ee5b..8f4f8fc62ed55fec8c2226081ff66f03ddedc6e4 100644 (file)
@@ -143,6 +143,7 @@ void ConstructionPlugin_Point::execute()
 
   removeResults(1); // for case the point type was switched from multi-results type
   std::shared_ptr<ModelAPI_ResultConstruction> aConstr = document()->createConstruction(data());
+  aConstr->setInfinite(true);
   aConstr->setShape(aShape);
   setResult(aConstr);
 }
index fa4686de7e8797971b1d0ffc20520d9fdad9c978..dbc6e498a943ce533a23e5010d39558a3fcd3a19 100644 (file)
@@ -122,6 +122,8 @@ bool GeomAPI_PlanarEdges::isEqual(const std::shared_ptr<GeomAPI_Shape> theShape)
     return false;
   TopoDS_Shape& aMyShape = const_cast<TopoDS_Shape&>(impl<TopoDS_Shape>());
   TopoDS_Shape aTheShape = theShape->impl<TopoDS_Shape>();
+  if (aMyShape.ShapeType() != aTheShape.ShapeType()) // to don't confuse by the face of same edges
+    return false;
   TopExp_Explorer aMyExp(aMyShape, TopAbs_EDGE);
   TopExp_Explorer aTheExp(aTheShape, TopAbs_EDGE);
   for (; aMyExp.More() && aTheExp.More(); aMyExp.Next(), aTheExp.Next()) {
index 3aa4ffeaac701776dc79cf80798c01ae276fa86a..b4739045fbe616388e4a1cfdbb6c2c70bd17d102 100644 (file)
@@ -158,34 +158,36 @@ bool Model_AttributeSelection::setValue(const ObjectPtr& theContext,
       owner()->data()->blockSendAttributeUpdated(false);
     return false;
   }
-  if (theContext->groupName() == ModelAPI_ResultBody::group()) {
-    ResultBodyPtr aContextBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theContext);
+  bool isSelectBody = theContext->groupName() == ModelAPI_ResultBody::group();
+  if (!isSelectBody) {
+    ResultConstructionPtr aContextConstruction =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theContext);
+    isSelectBody = aContextConstruction.get() && !aContextConstruction->isInfinite();
+  }
+  if (isSelectBody) {
+    ResultPtr aContextResult = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);
+    GeomShapePtr aContextShape = aContextResult->shape();
     // do not select the whole shape for body:it is already must be in the data framework
     // equal and null selected objects mean the same: object is equal to context,
-    if (aContextBody->shape().get() &&
-        (aContextBody->shape()->isEqual(theSubShape) || !theSubShape.get())) {
+    if (aContextShape.get() && (aContextShape->isEqual(theSubShape) || !theSubShape.get())) {
       aSelLab.ForgetAllAttributes(true);
       TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID);
     } else {
-      selectBody(aContextBody, theSubShape);
+      selectBody(aContextResult, theSubShape);
     }
   } else if (theContext->groupName() == ModelAPI_ResultConstruction::group()) {
-    ResultConstructionPtr aContextConstruction =
-      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theContext);
     aSelLab.ForgetAllAttributes(true); // to remove old selection data
     std::shared_ptr<Model_ResultConstruction> aConstruction =
       std::dynamic_pointer_cast<Model_ResultConstruction>(theContext);
     std::shared_ptr<GeomAPI_Shape> aSubShape;
-    if (theSubShape.get() && !aContextConstruction->shape()->isEqual(theSubShape))
+    if (theSubShape.get() && !aConstruction->shape()->isEqual(theSubShape))
       aSubShape = theSubShape; // the whole context
     if (aConstruction->isInfinite()) {
       // For correct naming selection, put the shape into the naming structure.
-      // It seems sub-shapes are not needed: only this shape is (and can be ) selected.
+      // It seems sub-shapes are not needed: only this shape is (and can be) selected.
       TNaming_Builder aBuilder(aSelLab);
-      aBuilder.Generated(aContextConstruction->shape()->impl<TopoDS_Shape>());
+      aBuilder.Generated(aConstruction->shape()->impl<TopoDS_Shape>());
     }
-    int anIndex = aConstruction->select(theSubShape, owner()->document());
-    TDataStd_Integer::Set(aSelLab, anIndex);
   } else if (theContext->groupName() == ModelAPI_ResultPart::group()) {
     aSelLab.ForgetAllAttributes(true);
     TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID);
@@ -422,12 +424,7 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::internalValue(CenterTyp
       aResult = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
       aResult->setImpl(new TopoDS_Shape(aSelShape));
     } else if (aConstr) { // simple construction element: just shape of this construction element
-      Handle(TDataStd_Integer) anIndex;
-      if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
-        if (anIndex->Get() == 0) // it is just reference to construction, nothing is in value
-          return aResult;
-        return aConstr->shape(anIndex->Get(), owner()->document());
-      }
+      aResult = aConstr->shape();
     }
   }
   return aResult;
@@ -455,11 +452,7 @@ bool Model_AttributeSelection::isInitialized()
         std::shared_ptr<Model_ResultConstruction> aConstr =
           std::dynamic_pointer_cast<Model_ResultConstruction>(context());
         if (aConstr.get()) {
-          Handle(TDataStd_Integer) anIndex;
-          if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
-            // for the whole shape it may return null, so, if index exists, returns true
             return true;
-          }
         }
         // for the whole feature, a feature object
         FeaturePtr aFeat = contextFeature();
@@ -725,22 +718,19 @@ bool Model_AttributeSelection::update()
   }
 
   if (aContext->groupName() == ModelAPI_ResultConstruction::group()) {
-    Handle(TDataStd_Integer) anIndex;
-    if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
-      std::shared_ptr<Model_ResultConstruction> aConstructionContext =
-        std::dynamic_pointer_cast<Model_ResultConstruction>(aContext);
-      bool aModified = true;
-      bool aValid = aConstructionContext->update(anIndex->Get(), owner()->document(), aModified);
-      setInvalidIfFalse(aSelLab, aValid);
-      if (aConstructionContext->isInfinite()) {
-        // Update the selected shape.
-        TNaming_Builder aBuilder(aSelLab);
-        aBuilder.Generated(aConstructionContext->shape()->impl<TopoDS_Shape>());
+    bool aResult = true;
+    std::shared_ptr<Model_ResultConstruction> aConstructionContext =
+      std::dynamic_pointer_cast<Model_ResultConstruction>(aContext);
+    if (!aConstructionContext->isInfinite()) {
+      Selector_Selector aSelector(aSelLab);
+      aResult = aSelector.restore();
+      if (aResult) {
+        TopoDS_Shape aContextShape = aContext->shape()->impl<TopoDS_Shape>();
+        aResult = aSelector.solve(aContextShape);
       }
-      if (aModified)
-        owner()->data()->sendAttributeUpdated(this);
-      return aValid;
+      aResult = setInvalidIfFalse(aSelLab, aResult);
     }
+    return aResult;
   }
   return setInvalidIfFalse(aSelLab, false); // unknown case
 }
@@ -751,7 +741,7 @@ void Model_AttributeSelection::selectBody(
   // perform the selection
   TopoDS_Shape aContext;
 
-  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theContext);//myRef.value()
+  ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);//myRef.value()
   if (aBody) {
     aContext = aBody->shape()->impl<TopoDS_Shape>();
   } else {
@@ -766,67 +756,8 @@ void Model_AttributeSelection::selectBody(
   }
 
   // with "recover" feature the selected context may be not up to date (issue 1710)
-  Handle(TNaming_NamedShape) aResult;
   TDF_Label aSelLab = selectionLabel();
-  TopoDS_Shape aNewContext = aContext;
-  bool isUpdated = true;
-  while(!aNewContext.IsNull() && isUpdated) {
-    // searching for the very last shape that was produced from this one
-    isUpdated = false;
-    if (!TNaming_Tool::HasLabel(aSelLab, aNewContext))
-      // to avoid crash of TNaming_SameShapeIterator if pure shape does not exists
-      break;
-    for(TNaming_SameShapeIterator anIter(aNewContext, aSelLab); anIter.More(); anIter.Next()) {
-      TDF_Label aNSLab = anIter.Label();
-      if (!scope().Contains(aNSLab))
-        continue;
-      Handle(TNaming_NamedShape) aNS;
-      if (aNSLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
-        for(TNaming_Iterator aShapesIter(aNS); aShapesIter.More(); aShapesIter.Next()) {
-          if (aShapesIter.Evolution() == TNaming_SELECTED)
-            continue; // don't use the selection evolution
-          if (!aShapesIter.OldShape().IsNull() && aShapesIter.OldShape().IsSame(aNewContext)) {
-             // found the original shape
-            aNewContext = aShapesIter.NewShape(); // go to the newer shape
-            isUpdated = true;
-            break;
-          }
-        }
-      }
-    }
-  }
-  if (aNewContext.IsNull()) { // a context is already deleted
-    setInvalidIfFalse(aSelLab, false);
-    Events_InfoMessage("Model_AttributeSelection", "Failed to select shape already deleted").send();
-    return;
-  }
-
   TopoDS_Shape aNewSub = theSubShape ? theSubShape->impl<TopoDS_Shape>() : aContext;
-  if (!aNewSub.IsEqual(aContext)) { // searching for subshape in the new context
-    bool isFound = false;
-    TopExp_Explorer anExp(aNewContext, aNewSub.ShapeType());
-    for(; anExp.More(); anExp.Next()) {
-      if (anExp.Current().IsSame(aNewSub)) {
-        isFound = true;
-        break;
-      }
-    }
-    if (!isFound) { // sub-shape is not found in the up-to-date instance of the context shape
-      // if context is sub-result of compound/compsolid, selection of sub-shape better propagate to
-      // the main result (which is may be modified); the case is in 1799
-      ResultBodyPtr aMain = ModelAPI_Tools::bodyOwner(theContext);
-      while(ModelAPI_Tools::bodyOwner(aMain).get())
-        aMain = ModelAPI_Tools::bodyOwner(theContext);
-      if (aMain.get()) {
-        selectBody(aMain, theSubShape);
-        return;
-      }
-      setInvalidIfFalse(aSelLab, false);
-      Events_InfoMessage("Model_AttributeSelection",
-        "Failed to select sub-shape already modified").send();
-      return;
-    }
-  }
 
   /// fix for issue 411: result modified shapes must not participate in this selection mechanism
   if (!aContext.IsNull()) {
@@ -842,10 +773,10 @@ void Model_AttributeSelection::selectBody(
     Selector_Selector aSel(aSelLab);
     try {
       //aSel.Select(aNewSub, aNewContext);
-      aSelectorOk = aSel.select(aNewContext, aNewSub);
+      aSelectorOk = aSel.select(aContext, aNewSub);
       if (aSelectorOk) {
         aSel.store();
-        aSelectorOk = aSel.solve(aNewContext);
+        aSelectorOk = aSel.solve(aContext);
       }
     } catch(...) {
       aSelectorOk = false;
@@ -865,7 +796,7 @@ void Model_AttributeSelection::selectBody(
     }
     if (!aSelectorOk) { // weak naming identifier instead
       GeomShapePtr aContextShape(new GeomAPI_Shape);
-      aContextShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewContext));
+      aContextShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aContext));
       GeomShapePtr aValueShape(new GeomAPI_Shape);
       aValueShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewSub));
 
@@ -964,13 +895,25 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa
   }
 
   TDF_Label aSelLab = selectionLabel();
+  if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // whole context, no value
+    return contextName(aCont);
+  }
+
   Handle(TDataStd_Integer) aWeakId;
   if (aSelLab.FindAttribute(kWEAK_NAMING, aWeakId)) { // a weak naming is used
     std::ostringstream aNameStream;
-    aNameStream<<aCont->data()->name()<<"/weak_name_"<<aWeakId->Get();
+    aNameStream<<contextName(aCont)<<"/weak_name_"<<aWeakId->Get();
     return aNameStream.str();
   }
 
+  // whole infinitive construction
+  if (aCont->groupName() == ModelAPI_ResultConstruction::group()) {
+    ResultConstructionPtr aConstr = std::dynamic_pointer_cast<Model_ResultConstruction>(aCont);
+    if (aConstr->isInfinite()) {
+      return contextName(aCont);
+    }
+  }
+
   Selector_Selector aSelector(aSelLab);
   std::string aResult;
   if (aSelector.restore())
@@ -1722,8 +1665,17 @@ std::string Model_AttributeSelection::contextName(const TDF_Label theSelectionLa
   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(aMyDoc);
   FeaturePtr aFeatureOwner = aDoc->featureByLab(theSelectionLab);
   if (aFeatureOwner.get()) {
+    // if it is sub-element of the sketch, the context name is the name of the sketch
     // searching also for result - real context
-    ResultPtr aResult = aDoc->resultByLab(theSelectionLab);
+    ResultPtr aResult;
+    FeaturePtr aComposite = ModelAPI_Tools::compositeOwner(aFeatureOwner);
+    if (aComposite.get() && aComposite->results().size() == 1 &&
+        aComposite->firstResult()->groupName() == ModelAPI_ResultConstruction::group()) {
+      aFeatureOwner = aComposite;
+      aResult = aFeatureOwner->firstResult();
+    } else {
+      aResult = aDoc->resultByLab(theSelectionLab);
+    }
     if (aResult.get()) {
       // this is to avoid duplicated names of results problem
       std::string aContextName = aResult->data()->name();
index c17c9b8d56c3ea2cf4870d67825bb84db2679001..370ce2ad15cc01cf8debdae11968600083897edb 100755 (executable)
@@ -133,75 +133,6 @@ Model_BodyBuilder::Model_BodyBuilder(ModelAPI_Object* theOwner)
 {
 }
 
-// Converts evolution of naming shape to selection evelution and back to avoid
-// naming support on the disabled results. Deeply in the labels tree, recursively.
-static void evolutionToSelectionRec(TDF_Label theLab, const bool theFlag) {
-  std::list<std::pair<TopoDS_Shape, TopoDS_Shape> > aShapePairs; // to store old and new shapes
-  Handle(TNaming_NamedShape) aName;
-  int anEvolution = -1;
-  if (theLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
-    TNaming_Evolution aNSEvol = aName->Evolution();
-    if ((aNSEvol == TNaming_SELECTED && theFlag) ||
-        (aNSEvol != TNaming_SELECTED && !theFlag)) { // nothing to do, it is already correct
-      return;
-    }
-    anEvolution = (int)(aNSEvol);
-    if (!theFlag) {
-      Handle(TDataStd_Integer) anAttrEvol;
-      if (theLab.FindAttribute(TDataStd_Integer::GetID(), anAttrEvol)) {
-        anEvolution = anAttrEvol->Get();
-      }
-    } else {
-      TDataStd_Integer::Set(theLab, anEvolution);
-    }
-
-    for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) {
-      // iterator goes in reversed order relatively to the Builder, to, make the list reversed
-      aShapePairs.push_front(std::pair<TopoDS_Shape, TopoDS_Shape>
-        (anIter.OldShape(), anIter.NewShape()));
-    }
-
-    // create new
-    TNaming_Builder aBuilder(theLab);
-    TNaming_Evolution anEvol = (TNaming_Evolution)(anEvolution);
-    std::list<std::pair<TopoDS_Shape, TopoDS_Shape> >::iterator aPairsIter = aShapePairs.begin();
-    for(; aPairsIter != aShapePairs.end(); aPairsIter++) {
-      if (theFlag) { // disabled => make selection
-        if (anEvolution == TNaming_DELETE) // issue 2274 : don't put too many same null shapes
-          aBuilder.Select(aPairsIter->first, aPairsIter->first);
-        else if (anEvolution == TNaming_PRIMITIVE)
-          aBuilder.Select(aPairsIter->second, aPairsIter->second);
-        else
-          aBuilder.Select(aPairsIter->second, aPairsIter->first);
-      } else if (anEvol == TNaming_GENERATED) {
-        aBuilder.Generated(aPairsIter->first, aPairsIter->second);
-      } else if (anEvol == TNaming_MODIFY) {
-        aBuilder.Modify(aPairsIter->first, aPairsIter->second);
-      } else if (anEvol == TNaming_DELETE) {
-        aBuilder.Delete(aPairsIter->first);
-      } else if (anEvol == TNaming_PRIMITIVE) {
-        aBuilder.Generated(aPairsIter->second);
-      } else if (anEvol == TNaming_SELECTED) {
-        aBuilder.Select(aPairsIter->second, aPairsIter->first);
-      }
-    }
-  }
-  // recursive call for all sub-labels
-  TDF_ChildIterator anIter(theLab, Standard_False);
-  for(; anIter.More(); anIter.Next()) {
-    evolutionToSelectionRec(anIter.Value(), theFlag);
-  }
-}
-
-void Model_BodyBuilder::evolutionToSelection(const bool theFlag)
-{
-  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-  if (!aData || !aData->isValid()) // unknown case
-    return;
-  TDF_Label& aShapeLab = aData->shapeLab();
-  evolutionToSelectionRec(aShapeLab, theFlag);
-}
-
 void Model_BodyBuilder::store(const GeomShapePtr& theShape,
                               const bool theIsStoreSameShapes)
 {
index 0217fb3a7cb52ee8d35a677358d28797c6c44ccd..ab82e48b224bf37a7896e9bfc54e13068286fc09 100755 (executable)
@@ -128,10 +128,6 @@ public:
   /// Removes the stored builders
   MODEL_EXPORT virtual ~Model_BodyBuilder();
 
-  /// Converts evolution of sub-shapes stored in naming structure to selection
-  /// (theFlag = true) and back (theFlag = false)
-  MODEL_EXPORT virtual void evolutionToSelection(const bool theFlag);
-
   /// Returns true if the latest modification of this body in the naming history
   // is equal to the given shape
   MODEL_EXPORT virtual bool isLatestEqual(const GeomShapePtr& theShape);
index 598193cb8903bc6eae4ed0b44601ca727bd94e46..e2a6a7994605b60b02ce8007ee44ac9b751760ac 100644 (file)
@@ -172,9 +172,9 @@ class Model_Data : public ModelAPI_Data
   MODEL_EXPORT virtual bool isValid();
 
   /// Returns the label where the shape must be stored (used in ResultBody)
-  TDF_Label& shapeLab()
+  TDF_Label shapeLab()
   {
-    return myLab;
+    return myLab.IsNull() ? myLab : myLab.Father().FindChild(2);
   }
 
   /// Initializes object by the attributes: must be called just after the object is created
index 6fc21e71e26da169c55bb0d31f06d3667d879b7c..dc1067ec6659ff1204d858de2affe05a34df3fc7 100644 (file)
@@ -1840,8 +1840,6 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
     }
   }
 
-  // for not persistent is will be done by parametric updater automatically
-  //if (!theFeature->isPersistentResult()) return;
   // check the existing results and remove them if there is nothing on the label
   std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
   while(aResIter != theFeature->results().cend()) {
@@ -1881,10 +1879,11 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
             // create the part result: it is better to restore the previous result if it is possible
             theFeature->execute();
         } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
-          theFeature->execute(); // construction shapes are needed for sketch solver
-          if (!theFeature->results().empty()) // to fix #2640 : update sketch, but not naming
-            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theFeature->firstResult())
-              ->facesNum(false);
+          ResultConstructionPtr aConstr = createConstruction(theFeature->data(), aResIndex);
+          if (!aConstr->updateShape())
+            theFeature->execute(); // not stored shape in the data structure, execute to have it
+          else
+            theFeature->setResult(aConstr, aResIndex); // result is ready without execution
         } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
           aNewBody = createGroup(theFeature->data(), aResIndex);
         } else if (aGroup->Get() == ModelAPI_ResultField::group().c_str()) {
index 746bbd7921d58e984fbd898d0d05f0b0e2477de9..7c7171ddd198e3cf9adcb0694f05ea77244ad967 100644 (file)
@@ -124,7 +124,6 @@ bool Model_ResultBody::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, con
 {
   bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag);
   if (aChanged) { // state is changed, so modifications are needed
-    myBuilder->evolutionToSelection(theFlag);
     updateSubs(shape(), false); // to set disabled/enabled
   }
   return aChanged;
index 1d0c715c7914bbd2db94fdb03782a8554dcc1d7f..07fa238251502f6308d940b1e95480870936a680 100644 (file)
 
 #include <Model_Data.h>
 #include <ModelAPI_CompositeFeature.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
 #include <Model_SelectionNaming.h>
 #include <ModelAPI_Events.h>
 #include <Config_PropManager.h>
 #include <GeomAPI_PlanarEdges.h>
 #include <GeomAPI_Shape.h>
-#include <GeomAlgoAPI_SketchBuilder.h>
 #include <Events_Loop.h>
 
 #include <TDF_Reference.hxx>
 #include <TDF_ChildIterator.hxx>
+#include <TDF_ChildIDIterator.hxx>
 #include <TNaming_NamedShape.hxx>
 #include <TNaming_Builder.hxx>
 #include <TDataStd_Integer.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Vertex.hxx>
+#include <TopoDS_ListOfShape.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TNaming_Tool.hxx>
 #include <Precision.hxx>
+#include <TopTools_MapOfShape.hxx>
 
-// identifier that it is full result selected, but in external document (for internal index is 0)
-Standard_GUID kFULL_RESULT_ID("ee87e529-da6f-46af-be25-5e0fefde52f7");
+// identifier of the infinite result
+Standard_GUID kIS_INFINITE("dea8cc5a-53f2-49c1-94e8-a947bed20a9f");
+// identifier of the result not in history
+Standard_GUID kIS_IN_HISTORY("a9aec01c-805e-44d1-b5d2-a63f06522f8a");
 
 
 void Model_ResultConstruction::colorConfigInfo(std::string& theSection, std::string& theName,
@@ -65,14 +70,10 @@ void Model_ResultConstruction::colorConfigInfo(std::string& theSection, std::str
 void Model_ResultConstruction::setShape(std::shared_ptr<GeomAPI_Shape> theShape)
 {
   if (myShape != theShape) {
-    if (!theShape.get() || !theShape->isEqual(myShape)) {
-        static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
-        ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), anEvent);
-        if (theShape.get()) {
-          myFacesUpToDate = false;
-          myFaces.clear();
-        }
-    }
+    if (!isInfinite())
+      storeShape(theShape);
+    static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+    ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), anEvent);
     myShape = theShape;
   }
 }
@@ -82,803 +83,305 @@ std::shared_ptr<GeomAPI_Shape> Model_ResultConstruction::shape()
   return myShape;
 }
 
-Model_ResultConstruction::Model_ResultConstruction()
-{
-  myIsInHistory = true;
-  myIsInfinite = false;
-  myFacesUpToDate = false;
-}
-
-void Model_ResultConstruction::setIsInHistory(const bool isInHistory)
-{
-  myIsInHistory = isInHistory;
-}
-
-int Model_ResultConstruction::facesNum(const bool theUpdateNaming)
+bool Model_ResultConstruction::updateShape()
 {
-  if (!myFacesUpToDate) {
-    std::shared_ptr<GeomAPI_PlanarEdges> aWirePtr =
-      std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(myShape);
-    if (aWirePtr.get()) {
-      std::list<std::shared_ptr<GeomAPI_Shape> > aFaces;
-      GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(),
-        aWirePtr->norm(), aWirePtr, aFaces);
-      std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aFIter = aFaces.begin();
-      for(; aFIter != aFaces.end(); aFIter++) {
-        std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(*aFIter));
-        if (aFace.get() && !aFace->isNull())
-          myFaces.push_back(aFace);
-      }
-    }
-    myFacesUpToDate = true;
-
-    // update all the faces and sub-elements in the naming structure
-    if (theUpdateNaming) {
-      DocumentPtr anEmptyExt;
-      bool aNotExt = false;
-      TDF_Label aDataLab = startLabel(anEmptyExt, aNotExt);
-      TDF_ChildIterator aSubsIter(aDataLab, Standard_False);
-      for(; aSubsIter.More(); aSubsIter.Next()) {
-        const TDF_Label aLab = aSubsIter.Value();
-        if (aLab.Tag() == 1) // skip the root shape label
-          continue;
-        Handle(TNaming_NamedShape) aNS;
-        if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
-          update(aLab.Tag() - 1, anEmptyExt, aNotExt);
-        }
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData && aData->isValid()) {
+    TDF_Label& aShapeLab = aData->shapeLab();
+    Handle(TNaming_NamedShape) aNS;
+    if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+      TopoDS_Shape aShape = aNS->Get();
+      if (!aShape.IsNull()) {
+        GeomShapePtr aGShape(new GeomAPI_Shape);
+        aGShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
+        myShape = aGShape; // restore the sketch sub-components
+        return true;
       }
     }
   }
-  return int(myFaces.size());
+  return false;
 }
 
-std::shared_ptr<GeomAPI_Face> Model_ResultConstruction::face(const int theIndex)
+Model_ResultConstruction::Model_ResultConstruction()
 {
-  return myFaces[theIndex];
 }
 
-bool Model_ResultConstruction::isInfinite()
-{
-  return myIsInfinite;
-}
 
-void Model_ResultConstruction::setInfinite(const bool theInfinite)
+bool Model_ResultConstruction::isInHistory()
 {
-  myIsInfinite = theInfinite;
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData.get() && aData->isValid()) {
+    return !aData->label().IsAttribute(kIS_IN_HISTORY); // by default no attribute, but in history
+  }
+  return true;  // unknown case
 }
 
-void Model_ResultConstruction::setIsConcealed(const bool theValue)
+void Model_ResultConstruction::setIsInHistory(const bool isInHistory)
 {
-  // do nothing: the construction element is never concealed
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData.get() && aData->isValid()) {
+    if (!isInHistory)
+      TDataStd_UAttribute::Set(aData->label(), kIS_IN_HISTORY);
+    else
+      aData->label().ForgetAttribute(kIS_IN_HISTORY);
+  }
 }
 
-static const int kSTART_VERTEX_DELTA = 1000000;
-
-static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, std::string theFullName,
-  const int theID, std::shared_ptr<Model_Document> theDoc,
-  bool theSelectionMode)
+bool Model_ResultConstruction::isInfinite()
 {
-  TDF_Label aLab = theID == 0 ? theMainLabel : theMainLabel.FindChild(theID);
-  TNaming_Builder aBuilder(aLab);
-  // wire never happens as sub, it must be generated to be found
-  // by SelectionNaming TNaming_Tool::NamedShape
-  if (theSelectionMode && theShape.ShapeType() != TopAbs_WIRE)
-    aBuilder.Select(theShape, theShape);
-  else
-    aBuilder.Generated(theShape);
-
-  theDoc->addNamingName(aLab, theFullName);
-  TDataStd_Name::Set(aLab, theFullName.c_str());
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData.get() && aData->isValid()) {
+    return aData->label().IsAttribute(kIS_INFINITE);
+  }
+  return false;  // unknown case
 }
 
-#include <TopTools_OrientedShapeMapHasher.hxx>
-
-// generates a full-name for sub-element of the composite feature (sketch)
-std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSubShape,
-  Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)())
+void Model_ResultConstruction::setInfinite(const bool theInfinite)
 {
-  TopAbs_ShapeEnum aShapeType = theSubShape.ShapeType();
-  gp_Pnt aVertexPos;
-  NCollection_Map<TopoDS_Edge> allExactEdges;
-  NCollection_DataMap<TopoDS_Edge, TopoDS_Edge, Model_EdgesHasher> allEdges;
-  NCollection_DataMap<Handle(Geom_Curve), TopoDS_Edge, Model_CurvesHasher> allCurves;
-  /// map from edges from theSubShape to the found corresponded indices of the sub-components
-  NCollection_DataMap<TopoDS_Edge, NCollection_List<int>, TopTools_OrientedShapeMapHasher>
-    anEdgesCorrespondence;
-  if (aShapeType == TopAbs_VERTEX) { // compare positions
-    aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(theSubShape));
-  } else {
-    for(TopExp_Explorer anEdgeExp(theSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) {
-      TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
-      allExactEdges.Add(anEdge);
-      allEdges.Bind(anEdge, anEdge);
-      Standard_Real aFirst, aLast;
-      Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-      allCurves.Bind(aCurve, anEdge);
-      anEdgesCorrespondence.Bind(anEdge, NCollection_List<int>());
-    }
-  }
-  std::map<int, int> anOrientations; //map from edges IDs to orientations of these edges in face
-  std::map<int, std::string> aSubNames; //map from edges IDs to names of edges
-  TColStd_PackedMapOfInteger aRefs; // indixes of sub-elements in composite
-
-
-  const int aSubNum = theComposite->numberOfSubs();
-  for(int a = 0; a < aSubNum; a++) {
-    FeaturePtr aSub = theComposite->subFeature(a);
-    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
-    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
-    // there may be many shapes (circle and center): register if at least one is in selection
-    for(; aRes != aResults.cend(); aRes++) {
-      ResultConstructionPtr aConstr =
-        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
-      if (!aConstr->shape()) {
-        continue;
-      }
-      if (aShapeType == TopAbs_VERTEX) {
-        if (aConstr->shape()->isVertex()) { // compare vertices positions
-          const TopoDS_Shape& aVertex = aConstr->shape()->impl<TopoDS_Shape>();
-          gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
-          if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
-            aRefs.Add(theComposite->subFeatureId(a));
-            aSubNames[theComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr);
-          }
-        } else { // get first or last vertex of the edge: last is stored with additional delta
-          const TopoDS_Shape& anEdge = aConstr->shape()->impl<TopoDS_Shape>();
-          int aDelta = kSTART_VERTEX_DELTA;
-          for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
-            gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current()));
-            if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
-              aRefs.Add(aDelta + theComposite->subFeatureId(a));
-              aSubNames[aDelta + theComposite->subFeatureId(a)] =
-                Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
-              break;
-            }
-            aDelta += kSTART_VERTEX_DELTA;
-          }
-        }
-      } else {
-        if (aConstr->shape()->isEdge()) {
-          const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
-          TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
-          if (anEdge.IsNull())
-            continue;
-          if (allEdges.IsBound(anEdge)) {
-            anEdgesCorrespondence.ChangeFind(allEdges.Find(anEdge)).Append(a);
-          } else {
-            Standard_Real aFirst, aLast;
-            Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-            if (allCurves.IsBound(aCurve)) {
-              anEdgesCorrespondence.ChangeFind(allCurves.Find(aCurve)).Append(a);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  if (aShapeType != TopAbs_VERTEX) { // get best candidates from the correspondances
-    NCollection_DataMap<TopoDS_Edge, NCollection_List<int>, TopTools_OrientedShapeMapHasher>
-      ::Iterator aCorIter(anEdgesCorrespondence);
-    for(; aCorIter.More(); aCorIter.Next()) {
-      TopoDS_Edge anOrig = aCorIter.Key();
-      NCollection_List<int>::Iterator aCandidate(aCorIter.Value());
-      int aBestScore = 0;
-      int aBestIndex = -1;
-      ResultConstructionPtr aBestConstr;
-      for(; aCandidate.More(); aCandidate.Next()) {
-        FeaturePtr aSub = theComposite->subFeature(aCandidate.Value());
-        const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
-        std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
-        // there may be many shapes (circle and center): register if at least one is in selection
-        for(; aRes != aResults.cend(); aRes++) {
-          ResultConstructionPtr aConstr =
-            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
-          if (!aConstr->shape() || !aConstr->shape()->isEdge())
-            continue;
-          const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
-          TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
-          if (anEdge.IsNull())
-            continue;
-          // detect score of the candidate
-          int aScore = 0;
-          if (anEdge.IsEqual(anOrig))
-            aScore = 10;
-          else if (anEdge.IsSame(anOrig))
-            aScore = 9;
-          else {
-            Standard_Real aFirst, aLast;
-            Handle(Geom_Curve) anOrigCurve = BRep_Tool::Curve(anOrig, aFirst, aLast);
-            Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-            if (anOrigCurve == aCurve) {
-              if (Model_EdgesHasher::IsEqual(anEdge, anOrig)) {
-                aScore = 8;
-              } else {
-                aScore = 6;
-              }
-            } else {
-              if (Model_EdgesHasher::IsEqual(anEdge, anOrig)) {
-                aScore = 7;
-              } else if (Model_CurvesHasher::IsEqual(aCurve, anOrigCurve)) {
-                aScore = 5;
-              }
-            }
-          }
-          if (aScore > aBestScore) {
-            aBestIndex = aCandidate.Value();
-            aBestScore = aScore;
-            aBestConstr = aConstr;
-          }
-        }
-      }
-      if (aBestIndex >= 0) {
-        int anID = theComposite->subFeatureId(aBestIndex);
-        aRefs.Add(anID);
-        aSubNames[anID] = Model_SelectionNaming::shortName(aBestConstr);
-        if (aShapeType != TopAbs_EDGE) { // face needs the sub-edges on sub-labels
-          // add edges to sub-label to support naming for edges selection
-          int anOrient = Model_SelectionNaming::edgeOrientation(theSubShape, anOrig);
-          anOrientations[anID] = anOrient;
-        }
-      }
-    }
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData.get() && aData->isValid()) {
+    if (theInfinite)
+      TDataStd_UAttribute::Set(aData->label(), kIS_INFINITE);
+    else
+      aData->label().ForgetAttribute(kIS_INFINITE);
   }
-  std::stringstream aName;
-  // #1839 : do not store name of the feature in the tree, since this name could be changed
-  if (theSubShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole construction result
-    if (theSubShape.ShapeType() == TopAbs_FACE) aName<<"Face";
-    else if (theSubShape.ShapeType() == TopAbs_WIRE) aName<<"Wire";
-    else if (theSubShape.ShapeType() == TopAbs_EDGE) aName<<"Edge";
-    else if (theSubShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex";
+}
 
-    // make a composite name from all sub-elements indexes: "1_2_3_4"
-    TColStd_MapIteratorOfPackedMapOfInteger aRef(aRefs);
-    for(; aRef.More(); aRef.Next()) {
-      aName<<"-"<<aSubNames[aRef.Key()];
-      if (anOrientations.find(aRef.Key()) != anOrientations.end()) {
-        if (anOrientations[aRef.Key()] == 1)
-          aName<<"f";
-        else if (anOrientations[aRef.Key()] == -1)
-          aName<<"r";
-      }
+int Model_ResultConstruction::facesNum(const bool theUpdateNaming)
+{
+  int aResult = 0;
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData.get() && aData->isValid()) {
+    TDF_Label& aShapeLab = aData->shapeLab();
+    TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID());
+    for (; anOldIter.More(); anOldIter.Next()) {
+      aResult++;
     }
   }
-  if (!theRefs.IsNull()) {
-    Handle(TColStd_HPackedMapOfInteger) aMap = new TColStd_HPackedMapOfInteger(aRefs);
-    theRefs->ChangeMap(aMap);
-  }
-  return aName.str();
+  return aResult;
 }
 
-// stores shape and name on sub-label of the main stored shape
-static void saveSubName(CompositeFeaturePtr theComposite,
-  TDF_Label& theLab, const bool isSelectionMode, TopoDS_Shape aSub,
-  std::shared_ptr<Model_Document> theDoc, std::string theFullName)
+std::shared_ptr<GeomAPI_Face> Model_ResultConstruction::face(const int theIndex)
 {
-  // trying to store the edge of composite result, not sketch sub as it is
-  if (aSub.ShapeType() == TopAbs_EDGE) {
-    ResultPtr aRes = theComposite->firstResult();
-    ResultConstructionPtr aConstr = std::dynamic_pointer_cast<Model_ResultConstruction>(aRes);
-    if (aConstr.get()) {
-      Standard_Real aSubFirst, aSubLast;
-      TopoDS_Edge aSubEdge = TopoDS::Edge(aSub);
-      Handle(Geom_Curve) aSubCurve = BRep_Tool::Curve(aSubEdge, aSubFirst, aSubLast);
-      for(int aFaceIndex = 0; aFaceIndex < aConstr->facesNum(); aFaceIndex++) {
-        GeomShapePtr aGFace = aConstr->face(aFaceIndex);
-        TopoDS_Shape aFace = aGFace->impl<TopoDS_Shape>();
-        for(TopExp_Explorer anExp(aFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
-          TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
-          Standard_Real aFirst, aLast;
-          Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-          if (Model_CurvesHasher::IsEqual(aCurve, aSubCurve) &&
-              ((fabs(aFirst - aSubFirst) < 1.e-9 &&  fabs(aLast - aSubLast) < 1.e-9)) ||
-              (fabs(aFirst - aSubLast) < 1.e-9 &&  fabs(aLast - aSubFirst) < 1.e-9)) {
-            aSub = anEdge;
-            break;
-          }
-        }
+  std::shared_ptr<GeomAPI_Face> aResult;
+  int anIndex = 0;
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData.get() && aData->isValid()) {
+    TDF_Label& aShapeLab = aData->shapeLab();
+    TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID());
+    for (; anOldIter.More(); anOldIter.Next()) {
+      if (anIndex == theIndex) {
+        Handle(TNaming_NamedShape) aNS;
+        anOldIter.Value()->Label().FindAttribute(TNaming_NamedShape::GetID(), aNS);
+        aResult.reset(new GeomAPI_Face);
+        aResult->setImpl(new TopoDS_Shape(aNS->Get()));
+        break;
       }
+      anIndex++;
     }
   }
-
-  TNaming_Builder aBuilder(theLab);
-  if (isSelectionMode)
-    aBuilder.Select(aSub, aSub);
-  else
-    aBuilder.Generated(aSub);
-  theDoc->addNamingName(theLab, theFullName.c_str());
-  TDataStd_Name::Set(theLab, theFullName.c_str());
+  return aResult;
 }
 
-
-TDF_Label Model_ResultConstruction::startLabel(
-  const std::shared_ptr<ModelAPI_Document> theExtDoc, bool& theExternal)
+void Model_ResultConstruction::setIsConcealed(const bool theValue)
 {
-  theExternal = theExtDoc.get() && theExtDoc != document();
-  if (theExternal) { // external document is used
-    std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(theExtDoc);
-    return aDoc->extConstructionsLabel();
-  }
-  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-  return aData->label();
+  // do nothing: the construction element is never concealed
 }
 
-int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSubShape,
-  const std::shared_ptr<ModelAPI_Document> theExtDoc, const int theIndex)
+void Model_ResultConstruction::storeShape(std::shared_ptr<GeomAPI_Shape> theShape)
 {
-  int anIndex; // resulting index of the sub-label
-  TopoDS_Shape aSubShape;
-  if (theSubShape.get()) {
-    aSubShape = theSubShape->impl<TopoDS_Shape>();
-  } else if (shape().get()) {
-    aSubShape = shape()->impl<TopoDS_Shape>();
-  }
-  // if external document requires this selection, put the naming structures to this doc
-  // to support the naming mechanism in this document correctly
-  bool anExternal;
-  TDF_Label aDataLab = startLabel(theExtDoc, anExternal);
-  if (theIndex == -1) {
-    anIndex = anExternal ? 2 : 1; // for the external doc don't mind about the main shape
-
-    if (theSubShape.get() || anExternal) { // searching for already selected sub (or whole for ext)
-      // iterate all the already presented shapes to see the same
-      TDF_ChildIterator aSubsIter(aDataLab, Standard_False);
-      for(; aSubsIter.More(); aSubsIter.Next()) {
-        const TDF_Label aLab = aSubsIter.Value();
-        if (aLab.Tag() == 1) // skip the root shape label
-          continue;
-        Handle(TNaming_NamedShape) aNS;
-        if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
-          if (aNS->Get().IsSame(aSubShape)) {
-            return aLab.Tag() - 1; // found exactly the needed shape, nothing else to do
-          }
-        }
-        anIndex = aLab.Tag(); // searching for the latest index
-      }
-      anIndex = (anIndex == 1) ? 2 : (anIndex + 1); // next after 1-root, or next after all
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData && aData->isValid()) {
+    TDF_Label& aShapeLab = aData->shapeLab();
+    if (!theShape.get() || theShape->isNull()) {
+      aShapeLab.ForgetAllAttributes();
+      return;
     }
-  } else {
-    anIndex = theIndex + 1;
-  }
-
-  // set the naming structure at index
-  TDF_Label aLab = aDataLab.FindChild(anIndex, Standard_True);
-
-  // if the subshape is part of a result face, select the whole face (#1997)
-  bool isSelectionMode = false; // and other don't set shapes - all the naming is in face label
-  if (!aSubShape.IsNull() && aSubShape.ShapeType() > TopAbs_FACE) {
-    // but before check that sub-vertex correctly detected as intersection of sketch edges (#2389)
-    int anEdgesNum = 2;
-    if (aSubShape.ShapeType() == TopAbs_VERTEX) {
-      anEdgesNum = 0;
+    std::shared_ptr<Model_Document> aMyDoc =
+      std::dynamic_pointer_cast<Model_Document>(document());
+    const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+    if (aShape.ShapeType() == TopAbs_VERTEX) {
+      aShapeLab.ForgetAllAttributes(); // clear all previously stored
+      TNaming_Builder aBuilder(aShapeLab);
+      aBuilder.Generated(aShape);
+      std::string aMyName = data()->name();
+      TDataStd_Name::Set(aShapeLab, aMyName.c_str());
+      aMyDoc->addNamingName(aShapeLab, aMyName);
+    } else if (aShape.ShapeType() == TopAbs_EDGE) { // store sub-vertices on sub-labels
+      aShapeLab.ForgetAllAttributes(); // clear all previously stored
+      TNaming_Builder aBuilder(aShapeLab);
+      aBuilder.Generated(aShape);
+
+      TopExp_Explorer anExp(aShape, TopAbs_VERTEX);
+      for(int anIndex = 1; anExp.More(); anExp.Next(), anIndex++) {
+        TDF_Label aSubLab = aShapeLab.FindChild(anIndex);;
+        TNaming_Builder aBuilder(aSubLab);
+        aBuilder.Generated(anExp.Current());
+        std::string aVertexName = anIndex == 1 ? "StartVertex" : "EndVertex";
+        TDataStd_Name::Set(aSubLab, aVertexName.c_str());
+        aMyDoc->addNamingName(aSubLab, aVertexName);
+      }
+      std::string aMyName = data()->name();
+      TDataStd_Name::Set(aShapeLab, aMyName.c_str());
+      aMyDoc->addNamingName(aShapeLab, aMyName);
+    } else { // this is probably sketch, so, work with it as with composite
+      std::shared_ptr<GeomAPI_PlanarEdges> aWirePtr =
+        std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theShape);
+      if (!aWirePtr.get())
+        return; // unknown case
       ResultPtr aThisPtr = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
-      FeaturePtr aThisFeature = document()->feature(aThisPtr);
+      FeaturePtr aThisFeature = aMyDoc->feature(aThisPtr);
       CompositeFeaturePtr aComposite =
         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aThisFeature);
-      if (aComposite.get()) {
-        const int aSubNum = aComposite->numberOfSubs();
-        for(int a = 0; a < aSubNum; a++) {
-          int aSubID = aComposite->subFeatureId(a);
-          FeaturePtr aSub = aComposite->subFeature(a);
-          const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
-          std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes;
-          for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) {
-            ResultConstructionPtr aConstr =
-              std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
-            if (aConstr->shape() && aConstr->shape()->isEdge()) {
-              TopoDS_Shape aResShape = aConstr->shape()->impl<TopoDS_Shape>();
-              for(TopExp_Explorer anExp(aResShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
-                if (aSubShape.IsSame(anExp.Current())) {
-                  anEdgesNum++;
-                  break;
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-    if (anEdgesNum > 1) {
-      for(int aFaceIndex = 0; aFaceIndex < facesNum(); aFaceIndex++) {
-        TopExp_Explorer anExp(face(aFaceIndex)->impl<TopoDS_Shape>(), aSubShape.ShapeType());
-        for(; anExp.More(); anExp.Next()) {
-          if (aSubShape.IsSame(anExp.Current())) { // this is the case: select the whole face
-            // here just store the face index (to update face if update of edge is needed)
-            TNaming_Builder aBuilder(aLab);
-            aBuilder.Select(aSubShape, aSubShape);
-            int aFaceSelID = select(face(aFaceIndex), theExtDoc, -1);
-            TDF_Reference::Set(aLab, aLab.Father().FindChild(aFaceSelID));
-            isSelectionMode = true;
-            break;
+      if (!aComposite || aComposite->numberOfSubs() == 0)
+        return; // unknown case
+      // collect indices of curves of current composite
+      NCollection_DataMap<Handle(Geom_Curve), int> aCurvesIndices;
+      NCollection_DataMap<int, TopoDS_Edge> anEdgeIndices;
+      std::map<int, std::string> aComponentsNames; // names of components that lay on index
+      const int aSubNum = aComposite->numberOfSubs();
+      for (int a = 0; a < aSubNum; a++) {
+        FeaturePtr aSub = aComposite->subFeature(a);
+        const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
+        std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
+        for (; aRes != aResults.cend(); aRes++) {
+          ResultConstructionPtr aConstr =
+            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
+          if (aConstr->shape() && aConstr->shape()->isEdge()) {
+            TopoDS_Edge anEdge = TopoDS::Edge(aConstr->shape()->impl<TopoDS_Shape>());
+            Standard_Real aFirst, aLast;
+            Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+            aCurvesIndices.Bind(aCurve, a);
+            anEdgeIndices.Bind(a, anEdge);
+            aComponentsNames[a] = Model_SelectionNaming::shortName(aConstr);
           }
         }
       }
-    }
-  }
-
-  // external full result is not identified by index == 0, so, add here the ID
-  if (!theSubShape.get()) {
-    TDataStd_UAttribute::Set(aLab, kFULL_RESULT_ID);
-    // empty NS
-    TNaming_Builder aBuilder(aLab);
-    // store all sub-faces naming since faces may be used for extrusion, where all edges are needed
-    Handle(TDataStd_IntPackedMap) anIndices = TDataStd_IntPackedMap::Set(aLab);
-    std::list<int> aFacesIndexes;
-    for(int a = 0; a < facesNum(); a++) {
-      anIndices->Add(select(face(a), theExtDoc, -1));
-    }
-    return anIndex - 1;
-  }
 
-  { // this to have erased Builder after the shape was generated (NS on this label may be changed)
-    TNaming_Builder aBuilder(aLab);
-    if (aSubShape.IsNull()) {
-      return anIndex - 1; // just keep empty named shape
-    }
-    // wire never happens as sub, it must be generated to be found
-    // by SelectionNaming TNaming_Tool::NamedShape
-    if (isSelectionMode && aSubShape.ShapeType() != TopAbs_WIRE) {
-      aBuilder.Select(aSubShape, aSubShape);
-    } else {
-      aBuilder.Generated(aSubShape);
-    }
-  }
-
-  if (anIndex == 1 && isInfinite()) { // infinitive results has no sub-selection
-    return anIndex - 1;
-  }
-  ResultPtr aThisPtr = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
-  FeaturePtr aThisFeature = document()->feature(aThisPtr);
-  CompositeFeaturePtr aComposite =
-    std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aThisFeature);
-  if (!aComposite || aComposite->numberOfSubs() == 0) {
-    // saving of context is enough: result construction contains exactly the needed shape
-    return anIndex - 1;
-  }
-
-  // identify the results of sub-object of the composite by edges
-  // save type of the selected shape in integer attribute
-  TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType();
-  TDataStd_Integer::Set(aLab, (int)aShapeType);
-  gp_Pnt aVertexPos;
-  // curves of the sketch sub-elements are used, so, edges are not equal
-  TColStd_MapOfTransient allCurves;
-  if (aShapeType == TopAbs_VERTEX) { // compare positions
-    aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape));
-  } else {
-    for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) {
-      TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
-      Standard_Real aFirst, aLast;
-      Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-      allCurves.Add(aCurve);
-    }
-  }
-  std::shared_ptr<Model_Document> aMyDoc =
-    std::dynamic_pointer_cast<Model_Document>(document());
-  // iterate and store the result ids of sub-elements and sub-elements to sub-labels
-  Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab);
-  const int aSubNum = aComposite->numberOfSubs();
-  // subs are placed on unique labels because of #2248: sketch curve may produce several edges,
-  // but #2401 - on stable labels
-  NCollection_Map<int> aUsedIDMap; // already used lab tags for placement of shapes
-
-  for(int a = 0; a < aSubNum; a++) {
-    FeaturePtr aSub = aComposite->subFeature(a);
-    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
-    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
-    // there may be many shapes (circle and center): register if at least one is in selection
-    for(; aRes != aResults.cend(); aRes++) {
-      ResultConstructionPtr aConstr =
-        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
-      if (!aConstr->shape()) {
-        continue;
-      }
-      if (aShapeType != TopAbs_VERTEX) {
-        if (aConstr->shape()->isEdge()) {
-          const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
-          TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
-          if (!anEdge.IsNull()) {
+      std::list<std::shared_ptr<GeomAPI_Shape> > aFaces;
+      GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(),
+        aWirePtr->norm(), aWirePtr, aFaces);
+      NCollection_DataMap<TopoDS_Face, TColStd_ListOfInteger> aNewIndices; // edges indices
+      std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aFIter = aFaces.begin();
+      for (; aFIter != aFaces.end(); aFIter++) {
+        std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(*aFIter));
+        // put them to a label, trying to keep the same faces on the same labels
+        if (aFace.get() && !aFace->isNull()) {
+          TopoDS_Face aTopoFace = TopoDS::Face(aFace->impl<TopoDS_Shape>());
+          aNewIndices.Bind(aTopoFace, TColStd_ListOfInteger());
+          // keep new indices of sub-elements used in this face
+          for (TopExp_Explorer anEdges(aTopoFace, TopAbs_EDGE); anEdges.More(); anEdges.Next()) {
+            TopoDS_Edge anEdge = TopoDS::Edge(anEdges.Current());
             Standard_Real aFirst, aLast;
             Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-            if (allCurves.Contains(aCurve)) {
-              int anID = aComposite->subFeatureId(a);
-              if (aShapeType != TopAbs_EDGE) { // face needs the sub-edges on sub-labels
-                // add edges to sub-label to support naming for edges selection
-                TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE);
-                for(; anEdgeExp.More(); anEdgeExp.Next()) {
-                  TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
-                  Standard_Real aFirst, aLast;
-                  Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-                  if (Model_CurvesHasher::IsEqual(aFaceCurve, aCurve)) {
-                    while(aUsedIDMap.Contains(anID))
-                      anID += 100000;
-                    aUsedIDMap.Add(anID);
-                    TDF_Label aSubLab = aLab.FindChild(anID);
-                    std::string aFullNameSub = fullName(aComposite, anEdge);
-                    saveSubName(aComposite, aSubLab, isSelectionMode, anEdge, aMyDoc, aFullNameSub);
-
-                    int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge);
-                    if (anOrient != 0) {
-                      // store the orientation of edge relatively to face if needed
-                      TDataStd_Integer::Set(aSubLab, anOrient);
-                    }
-                  }
-                }
-              } else { // put vertices of the selected edge to sub-labels
-                // add edges to sub-label to support naming for edges selection
-                for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_VERTEX);
-                      anEdgeExp.More(); anEdgeExp.Next()) {
-                    TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current());
-                    while(aUsedIDMap.Contains(anID))
-                      anID += 100000;
-                    aUsedIDMap.Add(anID);
-                    TDF_Label aSubLab = aLab.FindChild(anID);
-                    std::string aFullNameSub = fullName(aComposite, aV);
-                    saveSubName(aComposite, aSubLab, isSelectionMode, aV, aMyDoc, aFullNameSub);
-                }
-              }
+            if (aCurvesIndices.IsBound(aCurve)) {
+              int anIndex = aCurvesIndices.Find(aCurve);
+              if ((aFirst > aLast) != (anEdge.Orientation() == TopAbs_REVERSED))
+                anIndex = -anIndex;
+              aNewIndices.ChangeFind(aTopoFace).Append(anIndex);
             }
           }
         }
       }
-    }
-  }
-  std::string aFullName = fullName(aComposite, aSubShape, aRefs);
-  // store the selected as primitive
-  registerSubShape(aLab, aSubShape, aFullName, 0, aMyDoc, isSelectionMode);
-  return anIndex - 1;
-}
-
-std::shared_ptr<GeomAPI_Shape> Model_ResultConstruction::shape(const int theIndex,
-  const std::shared_ptr<ModelAPI_Document> theExtDoc)
-{
-  std::shared_ptr<GeomAPI_Shape> aResult;
-  if (theIndex == 0)
-    return aResult; // the whole shape, so, NULL
-
-  bool isExt;
-  TDF_Label aLab = startLabel(theExtDoc, isExt).FindChild(theIndex + 1);
-  if (!aLab.IsNull()) { // index is not bad
-    Handle(TNaming_NamedShape) aSelection;
-    if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
-      TopoDS_Shape aSelShape = aSelection->Get();
-      if (aSelShape.IsNull())
-        return aResult; // shape equal to context => null
-      aResult = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
-      aResult->setImpl(new TopoDS_Shape(aSelShape));
-    }
-  }
-
-  return aResult;
-}
-
-bool Model_ResultConstruction::update(const int theIndex,
-  const std::shared_ptr<ModelAPI_Document> theExtDoc, bool& theModified)
-{
-  theModified = false;
-  bool anExt;
-  TDF_Label aLab = startLabel(theExtDoc, anExt).FindChild(theIndex + 1, Standard_True);
-  if (theIndex == 0 || aLab.IsAttribute(kFULL_RESULT_ID)) { // full for external same as index == 0
-    // it is just reference to construction, not sub-shape
-    // if there is a sketch, the sketch-naming must be updated
-    if (!isInfinite()) {
-      // update all faces named by the whole result
-      bool aRes = true;
-      Handle(TDataStd_IntPackedMap) anIndices;
-      if (aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), anIndices)) {
-        NCollection_Map<TopoDS_Shape> aFaces; // collect faces, updated in the tree
-        TColStd_MapIteratorOfPackedMapOfInteger anIndexIter(anIndices->GetMap());
-        Handle(TColStd_HPackedMapOfInteger) aNewPackedMap =
-          new TColStd_HPackedMapOfInteger; // with only faces that are ok
-        // iterate to find existing faces, updated
-        for(; anIndexIter.More(); anIndexIter.Next()) {
-          if (update(anIndexIter.Key(), theExtDoc, theModified)) {
-            GeomShapePtr aFace = shape(anIndexIter.Key(), theExtDoc);
-            if (!aFaces.Contains(aFace->impl<TopoDS_Shape>())) {
-              aNewPackedMap->ChangeMap().Add(anIndexIter.Key());
-              aFaces.Add(aFace->impl<TopoDS_Shape>());
+      NCollection_DataMap<int, TopoDS_Face> aFacesOrder; // faces -> tag where they must be set
+      NCollection_List<TopoDS_Face> anUnorderedFaces; // faces that may be located at any index
+      // searching for the best new candidate to old location
+      NCollection_DataMap<TopoDS_Face, TColStd_ListOfInteger>::Iterator aNewIter(aNewIndices);
+      for (; aNewIter.More(); aNewIter.Next()) {
+        double aBestFound = 0, aBestNotFound = 1.e+100;
+        int aBestTag = 0;
+        const TColStd_ListOfInteger& aNewInd = aNewIter.Value();
+        // old faces indices where they where located
+        TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID());
+        for (; anOldIter.More(); anOldIter.Next()) {
+          int aTag = anOldIter.Value()->Label().Tag();
+          if (aFacesOrder.IsBound(aTag))
+            continue; // already found a best candidate
+          Handle(TDataStd_IntPackedMap) anOldIndices =
+            Handle(TDataStd_IntPackedMap)::DownCast(anOldIter.Value());
+          double aFound = 0, aNotFound = 0;
+          TColStd_ListOfInteger::Iterator aNewIndIter(aNewInd);
+          for (; aNewIndIter.More(); aNewIndIter.Next()) {
+            if (anOldIndices->Contains(aNewIndIter.Value())) {
+              aFound += 1.;
+            }
+            else if (anOldIndices->Contains(-aNewIndIter.Value())) { // different orientation
+              aFound += 0.001;
+            }
+            else {
+              aNotFound += 1.;
             }
           }
-        }
-        // then iterate all existing faces to find new faces
-        int aCurrentFacesNum = facesNum();
-        for(int a = 0; a < aCurrentFacesNum; a++) {
-          GeomShapePtr aFace = face(a);
-          if (!aFaces.Contains(aFace->impl<TopoDS_Shape>())) {
-            // add this one
-            int aNewFaceIndex = select(aFace, theExtDoc, -1);
-            if (aNewFaceIndex > 0) {
-              aNewPackedMap->ChangeMap().Add(aNewFaceIndex);
+          if (aNotFound < aBestNotFound) {
+            if (aFound > aBestFound) {
+              aBestNotFound = aNotFound;
+              aBestFound = aFound;
+              aBestTag = aTag;
             }
           }
         }
-        anIndices->ChangeMap(aNewPackedMap);
-      }
-      return aRes;
-    } else {
-      // check is this modified or not
-      std::shared_ptr<GeomAPI_Shape> aNewShape = shape();
-      TopoDS_Shape anOldSh;
-      Handle(TNaming_NamedShape) aNS;
-      if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
-        anOldSh = aNS->Get();
-      }
-      if (aNewShape.get()) {
-        if (anOldSh.IsNull())
-          theModified = true;
-        else {
-          std::shared_ptr<GeomAPI_Shape> anOldShape(new GeomAPI_Shape);
-          anOldShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(anOldSh));
-          theModified = !anOldShape->isEqual(aNewShape);
+        if (aBestTag != 0) { // found an appropriate face
+          aFacesOrder.Bind(aBestTag, aNewIter.Key());
+        } else {
+          anUnorderedFaces.Append(aNewIter.Key());
         }
       }
-      else if (!anOldSh.IsNull()) {
-        theModified = true;
-      }
-
-      // For correct naming selection, put the shape into the naming structure.
-      // It seems sub-shapes are not needed: only this shape is (and can be ) selected.
-      TNaming_Builder aBuilder(aLab);
-      aBuilder.Generated(aNewShape->impl<TopoDS_Shape>());
-    }
-    return shape() && !shape()->isNull();
-  }
-  // construction: identification by the results indexes, recompute faces and
-  // take the face that more close by the indexes
-  ResultPtr aThisPtr = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
-  FeaturePtr aContextFeature = document()->feature(aThisPtr);
+      aShapeLab.ForgetAllAttributes(); // clear all previously stored
+      TNaming_Builder aBuilder(aShapeLab); // store the compound to get it ready on open of document
+      aBuilder.Generated(aShape);
+      // set new faces to the labels
+      int aCurrentTag = 1;
+      NCollection_List<TopoDS_Face>::Iterator anUnordered(anUnorderedFaces);
+      for(int aCurrentTag = 1; !aFacesOrder.IsEmpty() || anUnordered.More(); aCurrentTag++) {
+        TopoDS_Face aFaceToPut;
+        if (aFacesOrder.IsBound(aCurrentTag)) {
+          aFaceToPut = aFacesOrder.Find(aCurrentTag);
+          aFacesOrder.UnBind(aCurrentTag);
+        } else if (anUnordered.More()){
+          aFaceToPut = anUnordered.Value();
+          anUnordered.Next();
+        }
 
-  // sketch sub-element
-  if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature).get())
-  {
-    // update the referenced object if it is sub
-    Handle(TDF_Reference) aRef;
-    if (aLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
-      int aFaceIndex = aRef->Get().Tag();
-      // don't check selection since face may disappear, but the shape stays correct
-      Model_ResultConstruction::update(aFaceIndex, theExtDoc, theModified);
-    }
-    // getting a type of selected shape
-    Handle(TDataStd_Integer) aTypeAttr;
-    if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) {
-      return false;
-    }
-    TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get());
-    // selected indexes will be needed in each "if"
-    Handle(TDataStd_IntPackedMap) aSubIds;
-    std::shared_ptr<GeomAPI_Shape> aNewSelected;
-    bool aNoIndexes =
-      !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0;
-    // for now working only with composite features
-    CompositeFeaturePtr aComposite =
-      std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
-    if (!aComposite.get() || aComposite->numberOfSubs() == 0) {
-      return false;
-    }
+        if (!aFaceToPut.IsNull()) {
+          TopTools_MapOfShape aFaceEdges;
+          for(TopExp_Explorer anEdges(aFaceToPut, TopAbs_EDGE); anEdges.More(); anEdges.Next()) {
+            aFaceEdges.Add(anEdges.Current());
+          }
 
-    if (aShapeType == TopAbs_FACE || aShapeType == TopAbs_WIRE) {
-      // compound is for the whole sketch selection
-      // If this is a wire with plane defined then it is a sketch-like object
-      if (!facesNum()) // no faces, update can not work correctly
-        return false;
-      // if there is no edges indexes, any face can be used: take the first
-      std::shared_ptr<GeomAPI_Shape> aNewSelected;
-      if (aNoIndexes) {
-        aNewSelected = face(0);
-      } else { // searching for most looks-like initial face by the indexes
-        // prepare edges of the current result for the fast searching
-        // curves and orientations of edges
-        NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher> allCurves;
-        const int aSubNum = aComposite->numberOfSubs();
-        for(int a = 0; a < aSubNum; a++) {
-          int aSubID = aComposite->subFeatureId(a);
-          if (aSubIds->Contains(aSubID)) {
-            FeaturePtr aSub = aComposite->subFeature(a);
-            const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
-            std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes;
-            for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) {
-              ResultConstructionPtr aConstr =
-                std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
-              if (aConstr->shape() && aConstr->shape()->isEdge()) {
-                const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
-                TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
-                if (!anEdge.IsNull()) {
-                  Standard_Real aFirst, aLast;
-                  Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-                  // searching for orientation information
-                  int anOrient = 0;
-                  Handle(TDataStd_Integer) anInt;
-                  if (aLab.FindChild(aSubID).FindAttribute(TDataStd_Integer::GetID(), anInt)) {
-                    anOrient = anInt->Get();
-                  }
-                  allCurves.Bind(aCurve, anOrient);
-                }
+          TDF_Label aLab = aShapeLab.FindChild(aCurrentTag);
+          TNaming_Builder aFaceBuilder(aLab);
+          aFaceBuilder.Generated(aFaceToPut);
+          // store also indices of the new face edges
+          Handle(TDataStd_IntPackedMap) aNewMap = TDataStd_IntPackedMap::Set(aLab);
+          const TColStd_ListOfInteger& aNewInd = aNewIndices.Find(aFaceToPut);
+          std::stringstream aName;
+          aName<<"Face";
+          TopExp_Explorer aPutEdges(aFaceToPut, TopAbs_EDGE);
+          TNaming_Builder* anEdgesBuilder = 0;
+          for(TColStd_ListOfInteger::Iterator anIter(aNewInd); anIter.More(); anIter.Next()) {
+            int anIndex = anIter.Value();
+            aNewMap->Add(anIndex);
+            aName<<"-"<<aComponentsNames[anIndex > 0 ? anIndex : -anIndex];
+            if (anIter.Value() > 0)
+              aName<<"f";
+            else
+              aName<<"r";
+            // collect all edges of the face which are modified in sub-label of the face
+            if (anEdgeIndices.IsBound(anIndex) &&
+                !aFaceEdges.Contains(anEdgeIndices.Find(anIndex))) {
+              if (!anEdgesBuilder) {
+                TDF_Label anEdgesLabel = aLab.FindChild(1);
+                anEdgesBuilder = new TNaming_Builder(anEdgesLabel);
+                TDataStd_Name::Set(anEdgesLabel, "SubEdge");
               }
+              anEdgesBuilder->Modify(anEdgeIndices.Find(anIndex), aPutEdges.Current());
             }
+            aPutEdges.Next();
           }
-        }
-        aNewSelected = Model_SelectionNaming::findAppropriateFace(
-          aThisPtr, allCurves, aShapeType == TopAbs_WIRE);
-      }
-      if (aNewSelected) { // store this new selection
-        select(aNewSelected, theExtDoc, theIndex);
-        theModified = true;
-        return true;
-      } else {
-        // if the selection is not found, put the empty shape:
-        // it's better to have disappeared shape, than the old, the lost one
-        TNaming_Builder anEmptyBuilder(aLab);
-        return false;
-      }
-    } else if (aShapeType == TopAbs_EDGE) {
-      // just reselect the edge by the id
-      const int aSubNum = aComposite->numberOfSubs();
-      for(int a = 0; a < aSubNum; a++) {
-        // if aSubIds take any, the first appropriate
-        if (aSubIds->IsEmpty() || aSubIds->Contains(aComposite->subFeatureId(a))) {
-          // found the appropriate feature
-          FeaturePtr aFeature = aComposite->subFeature(a);
-          std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
-            aFeature->results().cbegin();
-          for(;aResIter != aFeature->results().cend(); aResIter++) {
-            ResultConstructionPtr aRes =
-              std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
-            if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found!
-              select(aRes->shape(), theExtDoc, theIndex);
-              theModified = true;
-              return true;
-            }
-          }
-        }
-      }
-    } else if (aShapeType == TopAbs_VERTEX) {
-      // just reselect the vertex by the id of edge
-      const int aSubNum = aComposite->numberOfSubs();
-      for(int a = 0; a < aSubNum; a++) {
-        // if aSubIds take any, the first appropriate
-        int aFeatureID = aComposite->subFeatureId(a);
-        if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID) ||
-          aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA) ||
-          aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) {
-            // searching for deltas
-            int aVertexNum = 0;
-            if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1;
-            else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2;
-            // found the feature with appropriate edge
-            FeaturePtr aFeature = aComposite->subFeature(a);
-            std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
-              aFeature->results().cbegin();
-            for(;aResIter != aFeature->results().cend(); aResIter++) {
-              ResultConstructionPtr aRes =
-                std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
-              if (aRes && aRes->shape()) {
-                if (aRes->shape()->isVertex() && aVertexNum == 0) { // found!
-                  select(aRes->shape(), theExtDoc, theIndex);
-                  theModified = true;
-                  return true;
-                } else if (aRes->shape()->isEdge() && aVertexNum > 0) {
-                  const TopoDS_Shape& anEdge = aRes->shape()->impl<TopoDS_Shape>();
-                  int aVIndex = 1;
-                  for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
-                    if (aVIndex == aVertexNum) { // found!
-                      std::shared_ptr<GeomAPI_Shape> aVertex(new GeomAPI_Shape);
-                      aVertex->setImpl(new TopoDS_Shape(aVExp.Current()));
-                      select(aVertex, theExtDoc, theIndex);
-                      theModified = true;
-                      return true;
-                    }
-                    aVIndex++;
-                  }
-                }
-              }
-            }
+          TDataStd_Name::Set(aLab, TCollection_ExtendedString(aName.str().c_str()));
+          aMyDoc->addNamingName(aLab, aName.str());
         }
       }
     }
-  } else { // simple construction element: the selected is that needed
-    select(shape(), theExtDoc, theIndex);
-    theModified = true;
-    return true;
   }
-  return false; // unknown case
 }
index b5ea41cd985bb9589aa74b3c07ceae5ef82d6174..3ba48777fc81fc3e42ae1607519b03d6203a1181 100644 (file)
@@ -39,22 +39,13 @@ class Model_ResultConstruction : public ModelAPI_ResultConstruction
 {
   std::shared_ptr<ModelAPI_Feature> myOwner;  ///< owner of this result
   std::shared_ptr<GeomAPI_Shape> myShape;  ///< shape of this result created "on the fly"
-  bool myFacesUpToDate; ///< is true if faces in myuFaces are computed and up to date
-  /// stores the up to date faces if they exist
-  std::vector<std::shared_ptr<GeomAPI_Face> > myFaces;
-  bool myIsInHistory;
-  bool myIsInfinite;
  public:
   /// Retuns the parameters of color definition in the resources config manager
   MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName,
                                             std::string& theDefault);
 
   /// By default object is displayed in the object browser.
-  MODEL_EXPORT virtual bool isInHistory()
-  {
-    return myIsInHistory;
-  }
-
+  MODEL_EXPORT virtual bool isInHistory();
   /// Sets the result
   MODEL_EXPORT virtual void setShape(std::shared_ptr<GeomAPI_Shape> theShape);
   /// Returns the shape-result produced by this feature
@@ -76,39 +67,16 @@ class Model_ResultConstruction : public ModelAPI_ResultConstruction
   /// The construction element is never concealed
   MODEL_EXPORT virtual void setIsConcealed(const bool theValue);
 
-  // methods related to selection of sub-shapes in construction, used by SelectionAttribute
-
-  /// Selects theSubShape in the construction. Returns an index of the selected sub-shape.
-  /// Puts the selected shape with a needed BRepNaming sub-structure to the data tree of result.
-  /// If theSubShape is null, it selects the whole construction and returns zero index.
-  /// If theIndex is not -1, it re-selects over the existing data (used for update selection).
-  /// If theExtDoc is document where this selection is needed, if it differs from this,
-  /// naming structures will be located there.
-  int select(const std::shared_ptr<GeomAPI_Shape>& theSubShape,
-    const std::shared_ptr<ModelAPI_Document> theExtDoc, const int theIndex = -1);
-
-  /// Returns already selected shape by the given index. Zero index means the whole construction,
-  /// so, the returned shape in this case is null.
-  /// If theExtDoc is document where this selection is needed, if it differs from this,
-  /// naming structures will be located there.
-  std::shared_ptr<GeomAPI_Shape> shape(const int theIndex,
-    const std::shared_ptr<ModelAPI_Document> theExtDoc);
-
-  /// Updates the existing selection by the index.
-  /// Returns false if update is failed. Returns theModified true if the selection was updated.
-  /// If theExtDoc is document where this selection is needed, if it differs from this,
-  /// naming structures will be updated there.
-  bool update(const int theIndex, const std::shared_ptr<ModelAPI_Document> theExtDoc,
-    bool& theModified);
+  /// Updates the shape taking the current value from the data structure, returns true
+  /// if update has been correctly done
+  MODEL_EXPORT virtual bool updateShape();
 
  protected:
   /// Makes a body on the given feature
   Model_ResultConstruction();
 
-  /// Searchies for the working label selection/update will start from
-  /// Returns true if this is label of the external document.
-  /// theExtDoc is document where this selection is required
-  TDF_Label startLabel(const std::shared_ptr<ModelAPI_Document> theExtDoc, bool& theExternal);
+  /// Stores shape in the data structure to allow identification it by the naming
+  void storeShape(std::shared_ptr<GeomAPI_Shape> theShape);
 
   friend class Model_Objects;
 };
index 6edfd2c001f4cb4e470fe5bb69cc6d94e49ccb7f..bd252e8d7438bcfd272a98ae2ddf08c33a9ba29f 100755 (executable)
@@ -117,10 +117,6 @@ public:
                                         const std::string& theName,
                                         int& theTag) = 0;
 
-  /// Converts evolution of sub-shapes stored in naming structure to selection
-  /// (theFlag = true) and back (theFlag = false)
-  virtual void evolutionToSelection(const bool theFlag) = 0;
-
   /// Returns true if the latest modification of this body in the naming history
   // is equal to the given shape
   virtual bool isLatestEqual(const GeomShapePtr& theShape) = 0;
index ff637277d5d1c72940ae44e7714b1c85e0aadb9a..225102be5723411a3191b4536c986c4138d2029e 100644 (file)
@@ -63,6 +63,10 @@ class ModelAPI_ResultConstruction : public ModelAPI_Result
   /// Sets the result
   virtual void setShape(std::shared_ptr<GeomAPI_Shape> theShape) = 0;
 
+  /// Updates the shape taking the current value from the data structure, returns true
+  /// if update has been correctly done
+  virtual bool updateShape() = 0;
+
   /// Sets the flag that it must be displayed in history (default is true)
   virtual void setIsInHistory(const bool isInHistory) = 0;
 
index f3bf654eaf15b63714b991bda5d07f67ebd53d85..38af7997fd63307bae79ce8ab37429bb6c7c7c74 100644 (file)
@@ -24,11 +24,13 @@ SET(PROJECT_HEADERS
     Selector.h
     Selector_Selector.h
     Selector_NameGenerator.h
+    Selector_NExplode.h
 )
 
 SET(PROJECT_SOURCES
     Selector_Selector.cpp
     Selector_NameGenerator.cpp
+    Selector_NExplode.cpp
 )
 
 SET(PROJECT_LIBRARIES
diff --git a/src/Selector/Selector_NExplode.cpp b/src/Selector/Selector_NExplode.cpp
new file mode 100644 (file)
index 0000000..018f6b4
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "Selector_NExplode.h"
+
+#include <TopoDS_Shape.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <GProp_GProps.hxx>
+#include <BRepGProp.hxx>
+#include <NCollection_DataMap.hxx>
+#include <Precision.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepBndLib.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_MapOfShape.hxx>
+
+#include <vector>
+#include <algorithm>
+
+static std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S)
+{
+  // Computing of CentreOfMass
+  gp_Pnt GPoint;
+  double Len;
+
+  if (S.ShapeType() == TopAbs_VERTEX) {
+    GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
+    Len = (double)S.Orientation();
+  }
+  else {
+    GProp_GProps GPr;
+    if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
+      BRepGProp::LinearProperties(S, GPr);
+    }
+    else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
+      BRepGProp::SurfaceProperties(S, GPr);
+    }
+    else {
+      BRepGProp::VolumeProperties(S, GPr);
+    }
+    GPoint = GPr.CentreOfMass();
+    Len = GPr.Mass();
+  }
+
+  double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
+  return std::make_pair(dMidXYZ, Len);
+}
+
+/*!
+* \brief Sort shapes in the list by their coordinates.
+*/
+struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
+{
+  typedef NCollection_DataMap<TopoDS_Shape, std::pair<double, double> > DataMapOfShapeDouble;
+
+  CompareShapes(DataMapOfShapeDouble* theCashMap) : myMap(theCashMap) {}
+
+  bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs);
+
+  DataMapOfShapeDouble* myMap;
+};
+
+bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
+  const TopoDS_Shape& theShape2)
+{
+  if (!myMap->IsBound(theShape1)) {
+    myMap->Bind(theShape1, ShapeToDouble(theShape1));
+  }
+
+  if (!myMap->IsBound(theShape2)) {
+    myMap->Bind(theShape2, ShapeToDouble(theShape2));
+  }
+
+  std::pair<double, double> val1 = myMap->Find(theShape1);
+  std::pair<double, double> val2 = myMap->Find(theShape2);
+
+  double tol = Precision::Confusion();
+  bool exchange = Standard_False;
+
+  double dMidXYZ = val1.first - val2.first;
+  if (dMidXYZ >= tol) {
+    exchange = Standard_True;
+  }
+  else if (Abs(dMidXYZ) < tol) {
+    double dLength = val1.second - val2.second;
+    if (dLength >= tol) {
+      exchange = Standard_True;
+    }
+    else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
+      // equal values possible on shapes such as two halves of a sphere and
+      // a membrane inside the sphere
+      Bnd_Box box1,box2;
+      BRepBndLib::Add(theShape1, box1);
+      if (!box1.IsVoid()) {
+        BRepBndLib::Add(theShape2, box2);
+        Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
+        if (dSquareExtent >= tol) {
+          exchange = Standard_True;
+        }
+        else if (Abs(dSquareExtent) < tol) {
+          Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
+          box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+          val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
+          box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+          val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
+          if ((val1 - val2) >= tol) {
+            exchange = Standard_True;
+          }
+        }
+      }
+    } else // compare adresses if shapes are geometrically equal
+      return theShape1.TShape().get() > theShape2.TShape().get();
+  }
+
+  //return val1 < val2;
+  return !exchange;
+}
+
+Selector_NExplode::Selector_NExplode(const TopoDS_ListOfShape& theShapes)
+{
+  std::vector<TopoDS_Shape> aShapesVec;
+
+  for(TopoDS_ListOfShape::Iterator anIter(theShapes); anIter.More(); anIter.Next()) {
+      aShapesVec.push_back(anIter.Value());
+  }
+
+  CompareShapes::DataMapOfShapeDouble aCash;
+  CompareShapes shComp(&aCash);
+  std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
+
+  std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
+  for (; anIter != aShapesVec.end(); ++anIter) {
+    mySorted.Append(*anIter);
+  }
+}
+
+int Selector_NExplode::index(const TopoDS_Shape& theSubShape)
+{
+  TopoDS_ListOfShape::Iterator anIter(mySorted);
+  for(int anIndex = 1; anIter.More(); anIter.Next(), anIndex++) {
+    if (anIter.Value().IsSame(theSubShape))
+      return anIndex;
+  }
+  return -1; // not found
+}
+
+TopoDS_Shape Selector_NExplode::shape(const int theIndex)
+{
+  TopoDS_ListOfShape::Iterator anIter(mySorted);
+  for(int anIndex = 1; anIter.More(); anIter.Next(), anIndex++) {
+    if (anIndex == theIndex)
+      return anIter.Value();
+  }
+  return TopoDS_Shape(); // not found
+}
diff --git a/src/Selector/Selector_NExplode.h b/src/Selector/Selector_NExplode.h
new file mode 100644 (file)
index 0000000..4e020c1
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_NExplode_H_
+#define Selector_NExplode_H_
+
+#include "Selector.h"
+
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_ListOfShape.hxx>
+
+/// \class Selector_NExplode
+/// \ingroup DataModel
+/// \brief Sort shapes by their centers of mass, using formula X*999 + Y*99 + Z*0.9.
+/// Algorithm is copied from GEOM module, which uses nexplode Draw command from OCCT.
+/// Used for getting index of sub0shape in WeakNaming algorithm.
+class Selector_NExplode
+{
+ public:
+   /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes.
+   SELECTOR_EXPORT Selector_NExplode(const TopoDS_ListOfShape& theShapes);
+
+   /// Returns an index (started from one) of sub-shape in the sorted list. Returns 0 if not found.
+   SELECTOR_EXPORT int index(const TopoDS_Shape& theSubShape);
+   /// Returns a shape by an index (started from one). Returns null if not found.
+   SELECTOR_EXPORT TopoDS_Shape shape(const int theIndex);
+
+protected:
+  TopoDS_ListOfShape mySorted; ///< keepthe the ordered list of shapes
+};
+
+#endif
index f97d20c8c34d7d1e19ca5d82b26acc712c995605..2d8089485c7e49ae0a574c29e7bbb977a4f4ea12 100644 (file)
@@ -21,6 +21,7 @@
 #include <Selector_Selector.h>
 
 #include <Selector_NameGenerator.h>
+#include <Selector_NExplode.h>
 
 #include <TDF_ChildIDIterator.hxx>
 #include <TopoDS_Iterator.hxx>
@@ -50,9 +51,12 @@ static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171");
 static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f");
 // array of the neighbor levels
 static const Standard_GUID kLEVELS_ARRAY("ee4c4b45-e859-4e86-aa4f-6eac68e0ca1f");
+// weak index (integer) of the sub-shape
+static const Standard_GUID kWEAK_INDEX("e9373a61-cabc-4ee8-aabf-aea47c62ed87");
 
 Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
 {
+  myWeakIndex = -1;
 }
 
 TDF_Label Selector_Selector::label()
@@ -127,10 +131,15 @@ static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theV
     aNBConnectors.Add(aValExp.Current());
   }
 
+  TopTools_MapOfShape alreadyProcessed;
+  alreadyProcessed.Add(theValue);
+
   for(int aLevel = 1; aLevel <= theLevel; aLevel++) {
     TopoDS_ListOfShape aGoodCandidates;
     TopExp_Explorer aCandidate(theContext, theValue.ShapeType());
     for(; aCandidate.More(); aCandidate.Next()) {
+      if (alreadyProcessed.Contains(aCandidate.Current()))
+        continue;
       TopExp_Explorer aCandConnector(aCandidate.Current(), aConnectorType);
       for(; aCandConnector.More(); aCandConnector.Next()) {
         if (aNBConnectors.Contains(aCandConnector.Current())) // candidate is neighbor
@@ -150,6 +159,7 @@ static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theV
         for(; aGoodConnector.More(); aGoodConnector.Next()) {
           aNBConnectors.Add(aGoodConnector.Current());
         }
+        alreadyProcessed.Add(aGood.Value());
       }
     }
   }
@@ -189,6 +199,7 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext,
           }
         }
       }
+      aFirst = false;
     }
   }
   if (aMatches.IsEmpty())
@@ -258,7 +269,9 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape
     // try to find the shape of the higher level type in the context shape
     bool aFacesTried = false; // for identification of vertices, faces are tried, then edges
     while(aSelectionType != TopAbs_FACE || !aFacesTried) {
-      if (aSelectionType == TopAbs_FACE && theValue.ShapeType() == TopAbs_VERTEX) {
+      if (aSelectionType == TopAbs_FACE) {
+        if (theValue.ShapeType() != TopAbs_VERTEX)
+          break;
         aFacesTried = true;
         aSelectionType = TopAbs_EDGE;
       } else
@@ -318,7 +331,7 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape
       if (!aResult.IsNull() && aResult.IsSame(theValue)) {
         std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
         for(; aNBIter != aNBs.end(); aNBIter++) {
-          if (!selectBySubSelector(theContext, aNBIter->first)) {
+          if (!selectBySubSelector(theContext, aNBIter->first, false)) {
             return false; // something is wrong because before this selection was ok
           }
           myNBLevel.push_back(aNBIter->second);
@@ -385,9 +398,55 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape
     findBases(aModifList.First(), theValue, true, myBases);
     if (!myBases.IsEmpty()) {
       myFinal = aModifList.First()->Label();
-      myType = SELTYPE_MODIFICATION;
-      return !myBases.IsEmpty();
+      TopoDS_ListOfShape aCommon;
+      findModificationResult(aCommon);
+      // trying to search by neighbours
+      if (aCommon.Extent() > 1) { // more complicated selection
+        if (!theUseNeighbors)
+          return false;
+
+        // searching by neighbours
+        std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
+        for(int aLevel = 1; true; aLevel++) {
+          TopTools_MapOfShape aNewNB;
+          findNeighbors(theContext, theValue, aLevel, aNewNB);
+          if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
+            break;
+          }
+          // check which can be named correctly, without by neighbors type
+          for(TopTools_MapOfShape::Iterator aNBIter(aNewNB); aNBIter.More(); ) {
+            Selector_Selector aSelector(myLab.FindChild(1));
+            if (aSelector.select(theContext, aNBIter.Value(), false)) { // add to the list of good NBs
+              aNBs.push_back(std::pair<TopoDS_Shape, int>(aNBIter.Value(), aLevel));
+            }
+            aNewNB.Remove(aNBIter.Key());
+            aNBIter.Initialize(aNewNB);
+          }
+          TopoDS_Shape aResult = findNeighbor(theContext, aNBs);
+          if (!aResult.IsNull() && aResult.IsSame(theValue)) {
+            std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
+            for(; aNBIter != aNBs.end(); aNBIter++) {
+              if (!selectBySubSelector(theContext, aNBIter->first)) {
+                return false; // something is wrong because before this selection was ok
+              }
+              myNBLevel.push_back(aNBIter->second);
+
+            }
+            myType = SELTYPE_FILTER_BY_NEIGHBOR;
+            return true;
+          }
+        }
+        // filter by neighbours did not help
+        if (aCommon.Extent() > 1) { // weak naming between the common results
+          Selector_NExplode aNexp(aCommon);
+          myWeakIndex = aNexp.index(theValue);
+          if (myWeakIndex == -1)
+            return false;
+        }
+      }
     }
+    myType = SELTYPE_MODIFICATION;
+    return !myBases.IsEmpty();
   }
 
   // not found a good result
@@ -423,6 +482,9 @@ void Selector_Selector::store()
       anArray->SetValue(anIndex, aBIter.Value());
     }
     anArray->SetValue(myBases.Extent(), myFinal); // final is in the end of array
+    if (myWeakIndex != -1) {
+      TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
+    }
     break;
   }
   case SELTYPE_FILTER_BY_NEIGHBOR: {
@@ -485,6 +547,10 @@ bool Selector_Selector::restore()
         myBases.Append(anArray->Value(anIndex));
       }
       myFinal = anArray->Value(anUpper);
+      Handle(TDataStd_Integer) aWeakInt;
+      if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
+        myWeakIndex = aWeakInt->Get();
+      }
       return true;
     }
     return false;
@@ -531,7 +597,29 @@ static void findFinals(const TopoDS_Shape& theBase, const TDF_Label& theFinal,
       }
     }
   }
+}
 
+void Selector_Selector::findModificationResult(TopoDS_ListOfShape& theCommon) {
+  for(TDF_LabelList::Iterator aBase(myBases); aBase.More(); aBase.Next()) {
+    TopTools_MapOfShape aFinals;
+    for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next())
+      findFinals(aBaseShape.NewShape(), myFinal, aFinals);
+    if (!aFinals.IsEmpty()) {
+      if (theCommon.IsEmpty()) { // just copy all to common
+        for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) {
+          theCommon.Append(aFinal.Key());
+        }
+      } else { // keep only shapes presented in both lists
+        for(TopoDS_ListOfShape::Iterator aCommon(theCommon); aCommon.More(); ) {
+          if (aFinals.Contains(aCommon.Value())) {
+            aCommon.Next();
+          } else { // common is not found, remove it
+            theCommon.Remove(aCommon);
+          }
+        }
+      }
+    }
+  }
 }
 
 bool Selector_Selector::solve(const TopoDS_Shape& theContext)
@@ -599,28 +687,14 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext)
   }
   case SELTYPE_MODIFICATION: {
     TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
-    for(TDF_LabelList::Iterator aBase(myBases); aBase.More(); aBase.Next()) {
-      TopTools_MapOfShape aFinals;
-      for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next())
-        findFinals(aBaseShape.NewShape(), myFinal, aFinals);
-      if (!aFinals.IsEmpty()) {
-        if (aFinalsCommon.IsEmpty()) { // just copy all to common
-          for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) {
-            aFinalsCommon.Append(aFinal.Key());
-          }
-        } else { // keep only shapes presented in both lists
-          for(TopoDS_ListOfShape::Iterator aCommon(aFinalsCommon); aCommon.More(); ) {
-            if (aFinals.Contains(aCommon.Value())) {
-              aCommon.Next();
-            } else { // common is not found, remove it
-              aFinalsCommon.Remove(aCommon);
-            }
-          }
-        }
-      }
-    }
+    findModificationResult(aFinalsCommon);
     if (aFinalsCommon.Extent() == 1) // only in this case result is valid: found only one shape
       aResult = aFinalsCommon.First();
+    else if (aFinalsCommon.Extent() > 1 && myWeakIndex) {
+      Selector_NExplode aNExp(aFinalsCommon);
+      aResult = aNExp.shape(myWeakIndex);
+
+    }
     break;
   }
   case SELTYPE_FILTER_BY_NEIGHBOR: {
@@ -687,10 +761,15 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
     for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) {
       if (aBase != myBases.begin())
         aResult += "&";
-      if (aBase->FindAttribute(TDataStd_Name::GetID(), aName))
+      if (!aBase->FindAttribute(TDataStd_Name::GetID(), aName))
         return "";
       aResult += theNameGenerator->contextName(*aBase) + "/" +
         std::string(TCollection_AsciiString(aName->Get()).ToCString());
+      if (myWeakIndex != -1) {
+        std::ostringstream aWeakStr;
+        aWeakStr<<"&weak_name_"<<myWeakIndex;
+        aResult += aWeakStr.str();
+      }
     }
     return aResult;
   }
@@ -715,10 +794,10 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
 }
 
 bool Selector_Selector::selectBySubSelector(
-  const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+  const TopoDS_Shape theContext, const TopoDS_Shape theValue, const bool theUseNeighbors)
 {
   mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
-  if (!mySubSelList.back().select(theContext, theValue)) {
+  if (!mySubSelList.back().select(theContext, theValue, theUseNeighbors)) {
     mySubSelList.clear(); // if one of the selector is failed, all become invalid
     return false;
   }
index cbed4c98376f0208d485cc03f8f89972cbc14861..2fe4dcddad94eb822032b454df2190bfeadef298 100644 (file)
@@ -52,6 +52,7 @@ class Selector_Selector
   std::list<Selector_Selector> mySubSelList; ///< list of sub-selectors if needed
   TDF_Label myFinal; ///< final label of the primitive or generation, where the value is
   TDF_LabelList myBases; ///< initial labels that contain shapes that produce the modification
+  int myWeakIndex; ///< index of the shape among commons for the modification type (-1 - not set)
 
   std::list<int> myNBLevel; ///< list of integers corresponding to subsellist neighborhood level
 
@@ -66,7 +67,7 @@ class Selector_Selector
   /// Initializes the selector structure on the label.
   /// Stores the name data to restore after modification.
    SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
-     const bool theUseNeighbors = false);
+     const bool theUseNeighbors = true);
 
   /// Stores the name to the label and sub-labels tree
    SELECTOR_EXPORT void store();
@@ -88,7 +89,10 @@ private:
 
   /// Create and keep in the list the sub-sulector that select the given value.
   /// Returns true if selection is correct.
-  bool selectBySubSelector(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
+  bool selectBySubSelector(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
+    const bool theUseNeighbors = true);
+  /// Searches the final shapes presented in all results from bases basing on the modification fields
+  void findModificationResult(TopoDS_ListOfShape& theCommon);
 };
 
 #endif
index a9823830700559907394b85759940a911e842a53..20a98e32746a791e4f45682b3822035870cc8e3d 100644 (file)
@@ -65,9 +65,6 @@ class SketchPlugin_Feature : public ModelAPI_Feature
     return true;
   }
 
-  /// Construction result is allways recomuted on the fly
-  SKETCHPLUGIN_EXPORT virtual bool isPersistentResult() {return false;}
-
   /// Returns true is sketch element is under the rigid constraint
   SKETCHPLUGIN_EXPORT virtual bool isFixed() {return false;}
 
index 3e7328e77cc15623cdfb930d5964e25228331bf6..57dde7c5c8367abd5ab2bfc5c4863118b807287f 100644 (file)
@@ -204,9 +204,6 @@ class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_ICu
   /// Returns true if feature or reuslt belong to this composite feature as subs
   SKETCHPLUGIN_EXPORT virtual bool isSub(ObjectPtr theObject) const;
 
-  /// Construction result is allways recomuted on the fly
-  SKETCHPLUGIN_EXPORT virtual bool isPersistentResult() {return false;}
-
   SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
 
   /// Exchanges IDs of two given features: needed for fillet feature better naming (issue 769)