]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #1662: implementation of Recover feature.
authormpv <mpv@opencascade.com>
Thu, 4 Aug 2016 14:00:54 +0000 (17:00 +0300)
committermpv <mpv@opencascade.com>
Thu, 4 Aug 2016 14:00:54 +0000 (17:00 +0300)
To do: select as base not result, but feature (in GUI widget)

27 files changed:
src/FeaturesAPI/CMakeLists.txt
src/FeaturesAPI/FeaturesAPI.i
src/FeaturesAPI/FeaturesAPI_Recover.cpp [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_Recover.h [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_swig.h
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Recover.cpp
src/FeaturesPlugin/FeaturesPlugin_Recover.h
src/FeaturesPlugin/Test/TestRecover.py [new file with mode: 0644]
src/FeaturesPlugin/icons/recover.png [new file with mode: 0644]
src/FeaturesPlugin/plugin-Features.xml
src/FeaturesPlugin/recover_widget.xml
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Validator.cpp
src/Model/Model_Validator.h
src/ModelAPI/ModelAPI_Validator.h
src/ModelHighAPI/CMakeLists.txt
src/ModelHighAPI/ModelHighAPI.i
src/ModelHighAPI/ModelHighAPI_Reference.cpp [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_Reference.h [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_Tools.cpp
src/ModelHighAPI/ModelHighAPI_Tools.h
src/ModelHighAPI/ModelHighAPI_swig.h
src/ModelHighAPI/Test/TestReference.py [new file with mode: 0644]
src/PythonAPI/model/features/__init__.py
src/SketchPlugin/SketchPlugin_Validators.cpp

index ac6f97e99a42858b609d2b4c29cf904dbbe50584..1db8f2dd69765e6b3b03ad9ee6bb28c9ef633c1b 100644 (file)
@@ -12,6 +12,7 @@ SET(PROJECT_HEADERS
   FeaturesAPI_Partition.h
   FeaturesAPI_Pipe.h
   FeaturesAPI_Placement.h
+  FeaturesAPI_Recover.h
   FeaturesAPI_RemoveSubShapes.h
   FeaturesAPI_Revolution.h
   FeaturesAPI_RevolutionBoolean.h
@@ -28,6 +29,7 @@ SET(PROJECT_SOURCES
   FeaturesAPI_Partition.cpp
   FeaturesAPI_Pipe.cpp
   FeaturesAPI_Placement.cpp
+  FeaturesAPI_Recover.cpp
   FeaturesAPI_RemoveSubShapes.cpp
   FeaturesAPI_Revolution.cpp
   FeaturesAPI_RevolutionBoolean.cpp
index 748634b664a47bf2091123e5faebbca7070ecaa1..d2c9f968a0ecba19b569ca9a027bf4070447b359 100644 (file)
@@ -29,6 +29,7 @@
 %shared_ptr(FeaturesAPI_Partition)
 %shared_ptr(FeaturesAPI_Pipe)
 %shared_ptr(FeaturesAPI_Placement)
+%shared_ptr(FeaturesAPI_Recover)
 %shared_ptr(FeaturesAPI_RemoveSubShapes)
 %shared_ptr(FeaturesAPI_Revolution)
 %shared_ptr(FeaturesAPI_RevolutionBoolean)
@@ -46,6 +47,7 @@
 %include "FeaturesAPI_Partition.h"
 %include "FeaturesAPI_Pipe.h"
 %include "FeaturesAPI_Placement.h"
+%include "FeaturesAPI_Recover.h"
 %include "FeaturesAPI_RemoveSubShapes.h"
 %include "FeaturesAPI_Revolution.h"
 %include "FeaturesAPI_RevolutionBoolean.h"
diff --git a/src/FeaturesAPI/FeaturesAPI_Recover.cpp b/src/FeaturesAPI/FeaturesAPI_Recover.cpp
new file mode 100644 (file)
index 0000000..4fdf104
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        FeaturesAPI_Recover.cpp
+// Created:     07 June 2016
+// Author:      Dmitry Bobylev
+
+#include "FeaturesAPI_Recover.h"
+
+#include <ModelHighAPI_Reference.h>
+#include <ModelHighAPI_Tools.h>
+
+FeaturesAPI_Recover::FeaturesAPI_Recover(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+FeaturesAPI_Recover::FeaturesAPI_Recover(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+  const ModelHighAPI_Reference& theBaseFeature,
+  const std::list<ModelHighAPI_Selection>& theRecoveredList, const bool thePersistent)
+: ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setBaseFeature(theBaseFeature);
+    setRecoveredList(theRecoveredList);
+    setIsPersistent(thePersistent);
+  }
+}
+
+FeaturesAPI_Recover::~FeaturesAPI_Recover()
+{}
+
+void FeaturesAPI_Recover::setBaseFeature(const ModelHighAPI_Reference& theBaseFeature)
+{
+  fillAttribute(theBaseFeature, mybaseFeature);
+  // do not need to execute because on attribute changed it does everything anyway
+}
+
+void FeaturesAPI_Recover::setRecoveredList(const std::list<ModelHighAPI_Selection>& theRecoverList)
+{
+  fillAttribute(theRecoverList, myrecoveredList);
+  // do not need to execute because on attribute changed it does everything anyway
+}
+
+void FeaturesAPI_Recover::setIsPersistent(bool thePersistent)
+{
+  fillAttribute(thePersistent, myisPersistent);
+  // do not need to execute because on attribute changed it does everything anyway
+}
+
+RecoverPtr addRecover(const std::shared_ptr<ModelAPI_Document>& thePart,
+  const ModelHighAPI_Reference& theBaseFeature,
+  const std::list<ModelHighAPI_Selection>& theRecoveredList, const bool thePersistent)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Recover::ID());
+  return RecoverPtr(new FeaturesAPI_Recover(
+    aFeature, theBaseFeature, theRecoveredList, thePersistent));
+}
diff --git a/src/FeaturesAPI/FeaturesAPI_Recover.h b/src/FeaturesAPI/FeaturesAPI_Recover.h
new file mode 100644 (file)
index 0000000..28c8e18
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        FeaturesAPI_Recover.h
+// Created:     04 August 2016
+// Author:      Mikhail Ponikarov
+
+#ifndef FeaturesAPI_Recover_H_
+#define FeaturesAPI_Recover_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_Recover.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Reference;
+
+/// \class FeaturesAPI_Recover
+/// \ingroup CPPHighAPI
+/// \brief Interface for Recover feature.
+class FeaturesAPI_Recover: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Recover(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  FeaturesAPI_Recover(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                      const ModelHighAPI_Reference& theBaseFeature,
+                      const std::list<ModelHighAPI_Selection>& theRecoveredList,
+                      const bool thePersistent = false);
+
+  /// Destructor.
+  FEATURESAPI_EXPORT
+  virtual ~FeaturesAPI_Recover();
+
+  INTERFACE_3(FeaturesPlugin_Recover::ID(),
+              baseFeature, FeaturesPlugin_Recover::BASE_FEATURE(), ModelAPI_AttributeReference, /** Concealed feature */,
+              recoveredList, FeaturesPlugin_Recover::RECOVERED_ENTITIES(), ModelAPI_AttributeRefList, /** Recover list*/,
+              isPersistent, FeaturesPlugin_Recover::PERSISTENT(), ModelAPI_AttributeBoolean, /** Is persistent flag */)
+
+  /// Set base feature.
+  FEATURESAPI_EXPORT
+  void setBaseFeature(const ModelHighAPI_Reference& theBaseFeature);
+
+  /// Set recovered list of the base feature
+  FEATURESAPI_EXPORT
+  void setRecoveredList(const std::list<ModelHighAPI_Selection>& theRecoverList);
+
+  /// Set auxiliary
+  FEATURESAPI_EXPORT
+  void setIsPersistent(bool thePersistent);
+
+};
+
+/// Pointer on Recover object.
+typedef std::shared_ptr<FeaturesAPI_Recover> RecoverPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Recover feature.
+FEATURESAPI_EXPORT
+RecoverPtr addRecover(const std::shared_ptr<ModelAPI_Document>& thePart,
+                      const ModelHighAPI_Reference& theBaseFeature,
+                      const std::list<ModelHighAPI_Selection>& theRecoveredList,
+                      const bool thePersistent = false);
+
+#endif // FeaturesAPI_Recover_H_
index 0710405ad894fa33b747c4885a0a77fa6ed91eb5..f8da2bcfafc44d752b452ac95d54bc04efccc205 100644 (file)
@@ -18,6 +18,7 @@
   #include "FeaturesAPI_Partition.h"
   #include "FeaturesAPI_Pipe.h"
   #include "FeaturesAPI_Placement.h"
+  #include "FeaturesAPI_Recover.h"
   #include "FeaturesAPI_RemoveSubShapes.h"
   #include "FeaturesAPI_Revolution.h"
   #include "FeaturesAPI_RevolutionBoolean.h"
index 5b5ab88fe9ef95119e2332fe57c1c0598eafe245..61eddab92624b71461d38670fe47ae8a9c6f3efb 100644 (file)
@@ -132,4 +132,5 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestIntersection.py
                TestUnion.py
                TestRemoveSubShapes.py
-               TestPipe.py)
+               TestPipe.py
+               TestRecover.py)
index 5eb5aa84e27911e9e68b7d56a398197c2134dd36..5bdff264fcb0f19c7ac866d3bea76509edbecc81 100644 (file)
 #include <ModelAPI_Document.h>
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_Tools.h>
 
 using namespace std;
 
@@ -21,13 +24,108 @@ FeaturesPlugin_Recover::FeaturesPlugin_Recover()
 
 void FeaturesPlugin_Recover::initAttributes()
 {
-  data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeReference::typeId());
+  data()->addAttribute(BASE_FEATURE(), ModelAPI_AttributeReference::typeId());
   data()->addAttribute(RECOVERED_ENTITIES(), ModelAPI_AttributeRefList::typeId());
+  data()->addAttribute(PERSISTENT(), ModelAPI_AttributeBoolean::typeId());
 
-  /// temporary modification for empty list
-  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), RECOVERED_ENTITIES());
+  myPersistent = boolean(PERSISTENT())->value();
+  // temporary modification for empty list
+  // ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), RECOVERED_ENTITIES());
+
+  synchronizeRegistered();
 }
 
 void FeaturesPlugin_Recover::execute()
 {
+  synchronizeRegistered();
+}
+
+void FeaturesPlugin_Recover::attributeChanged(const std::string& theID)
+{
+  synchronizeRegistered();
+}
+
+void FeaturesPlugin_Recover::synchronizeRegistered()
+{
+  FeaturePtr aBase = baseFeature();
+  bool aNewPersistent = boolean(PERSISTENT())->value();
+  if (aNewPersistent != myPersistent)
+    clearRegistered();
+
+  std::set<ObjectPtr> aRecoveredInList;
+  // add unconcealed which are not in the myRegistered map
+  if (isStable() && !isDisabled()) { // if unstable, clear any unconcealment effect
+    AttributeRefListPtr aRecovered = reflist(RECOVERED_ENTITIES());
+    for(int anIndex = aRecovered->size() - 1; anIndex >= 0; anIndex--) {
+      ObjectPtr anObj = aRecovered->object(anIndex);
+      aRecoveredInList.insert(anObj);
+      if (myRegistered.find(anObj) == myRegistered.end()) {
+        // not found, so register a new
+        ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
+        ModelAPI_Session::get()->validators()->registerUnconcealment(
+          aRes, aNewPersistent ? FeaturePtr() : aBase);
+        myRegistered.insert(anObj);
+      }
+    }
+  }
+  // remove unconcealed which are not in the stored list, but in the map
+  std::set<std::shared_ptr<ModelAPI_Object> >::iterator aMyReg = myRegistered.begin();
+  while(aMyReg != myRegistered.end()) {
+    if (aRecoveredInList.find(*aMyReg) == aRecoveredInList.end()) {
+      ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(*aMyReg);
+      ModelAPI_Session::get()->validators()->disableUnconcealment(
+        aRes, aNewPersistent ? FeaturePtr() : myCurrentBase);
+      myRegistered.erase(aMyReg);
+      aMyReg = myRegistered.begin(); // restart iteration because after erase iterator may be bad
+    } else {
+      aMyReg++;
+    }
+  }
+  myCurrentBase = aBase;
+  myPersistent = aNewPersistent;
+}
+
+void FeaturesPlugin_Recover::erase()
+{
+  // clears myRegistered before all information is destroyed
+  clearRegistered();
+  ModelAPI_Feature::erase();
+}
+
+bool FeaturesPlugin_Recover::setStable(const bool theFlag)
+{
+  bool aRes = ModelAPI_Feature::setStable(theFlag);
+  synchronizeRegistered();
+  return aRes;
+}
+
+bool FeaturesPlugin_Recover::setDisabled(const bool theFlag)
+{
+  bool aRes = ModelAPI_Feature::setDisabled(theFlag);
+  synchronizeRegistered();
+  return aRes;
+}
+
+FeaturePtr FeaturesPlugin_Recover::baseFeature()
+{
+  // for the current moment it can be result of feature of feature: GUI is not debugged
+  ObjectPtr aBaseObj = reference(BASE_FEATURE())->value();
+  FeaturePtr aResult;
+  if (aBaseObj.get() == NULL)
+    return aResult;
+  aResult = std::dynamic_pointer_cast<ModelAPI_Feature>(aBaseObj);
+  if (aResult.get() == NULL)
+    aResult = aBaseObj->document()->feature(std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObj));
+  return aResult;
+}
+
+void FeaturesPlugin_Recover::clearRegistered()
+{
+  std::set<std::shared_ptr<ModelAPI_Object> >::iterator aMyReg = myRegistered.begin();
+  for(; aMyReg != myRegistered.end(); aMyReg++) {
+    ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(*aMyReg);
+    ModelAPI_Session::get()->validators()->disableUnconcealment(
+      aRes, myPersistent ? FeaturePtr() : myCurrentBase);
+  }
+  myRegistered.clear();
 }
index e24db88c1d33279a6eb2701fb7846facd1370e5d..9016ddbd8076c807019f1ff671d15a6b42b8a702 100644 (file)
  */
 class FeaturesPlugin_Recover : public ModelAPI_Feature
 {
+  /// List of already registered unconcealed pairs of unconcealed result and feature that caused
+  /// concealment. If attributes of this feature were changed, this list helps to synchronise
+  /// the current state with validators.
+  std::set<std::shared_ptr<ModelAPI_Object> > myRegistered;
+  /// The last stored Base to unregister Unconcealed when even attributes are already erased.
+  FeaturePtr myCurrentBase;
+  /// previous state of persistent flag
+  bool myPersistent;
  public:
   /// Extrusion kind
   inline static const std::string& ID()
   {
-    static const std::string MY_GROUP_ID("Recover");
-    return MY_GROUP_ID;
+    static const std::string MY_RECOVER_ID("Recover");
+    return MY_RECOVER_ID;
   }
-  /// Attribute name of base shape.
-  inline static const std::string& BASE_SHAPE_ID()
+  /// Attribute name of base feature.
+  inline static const std::string& BASE_FEATURE()
   {
-    static const std::string MY_BASE_SHAPE_ID("base_shape");
-    return MY_BASE_SHAPE_ID;
+    static const std::string MY_BASE_FEATURE("base_feature");
+    return MY_BASE_FEATURE;
   }
 
-  /// Attribute name of base shape.
+  /// Attribute name of recovered results list.
   inline static const std::string& RECOVERED_ENTITIES()
   {
-    static const std::string MY_RECOVERED_ENTITIES_ID("recovered_entities");
+    static const std::string MY_RECOVERED_ENTITIES_ID("recovered");
     return MY_RECOVERED_ENTITIES_ID;
   }
 
+  /// Attribute name of persistenc concealment flag.
+  inline static const std::string& PERSISTENT()
+  {
+    static const std::string MY_PERSISTENT_ID("persistent");
+    return MY_PERSISTENT_ID;
+  }
+
   /// Returns the kind of a feature
   FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
   {
@@ -54,6 +69,26 @@ class FeaturesPlugin_Recover : public ModelAPI_Feature
   /// Use plugin manager for features creation
   FeaturesPlugin_Recover();
 
+  /// Called on change of any argument-attribute of this object. Needed here for synchronization
+  /// of registered unconcealed.
+  virtual void attributeChanged(const std::string& theID);
+
+  /// Synchronises myRegistered before all attributes are erased
+  virtual void erase();
+
+  /// on unstability of feature, remove all unconcealment effect
+  virtual bool setStable(const bool theFlag);
+  /// on disable of feature, remove all unconcealment effect
+  virtual bool setDisabled(const bool theFlag);
+private:
+  /// Synchronises registration of unconcealed entities with the attributes values of this feature
+  void synchronizeRegistered();
+
+  /// Returns the base feature of this
+  FeaturePtr baseFeature();
+
+  /// erases all registered cashed values
+  void clearRegistered();
 };
 
 #endif
diff --git a/src/FeaturesPlugin/Test/TestRecover.py b/src/FeaturesPlugin/Test/TestRecover.py
new file mode 100644 (file)
index 0000000..28a47fc
--- /dev/null
@@ -0,0 +1,66 @@
+# Test made with high level API
+# -----------------------------
+
+import model
+
+# Initialisation
+
+model.begin()
+mypartset = model.moduleDocument()
+
+
+# Creating a new Part, two circles, extrusions on them and Boolean CUT
+
+mypart = model.addPart(mypartset).document()
+
+sk1 = model.addSketch(mypart, model.defaultPlane("XOY"))
+c1 = sk1.addCircle(0, 0, 100)
+bigcyl = model.addExtrusion(mypart, sk1.selectFace(), 100)
+
+sk2 = model.addSketch(mypart, model.defaultPlane("XOY"))
+c2 = sk2.addCircle(20, 30, 30)
+smallcyl = model.addExtrusion(mypart, sk2.selectFace(), 150)
+
+cut = model.addCut(mypart, bigcyl.result(), smallcyl.result())
+
+model.do()
+
+# check bodies number is 1: only Boolean result
+assert(mypart.size("Bodies") == 1)
+
+model.addRecover(mypart, cut, smallcyl.result())
+
+model.end()
+
+# check that one is recovered
+assert(mypart.size("Bodies") == 2)
+
+model.undo()
+
+# check bodies number is 1: recover is canceled
+assert(mypart.size("Bodies") == 1)
+
+
+# check persistent flag of recover: never concealed
+model.begin()
+
+recover = model.addRecover(mypart, cut, smallcyl.result(), True)
+assert(mypart.size("Bodies") == 2)
+sk3 = model.addSketch(mypart, model.defaultPlane("XOY"))
+c3 = sk3.addCircle(0, 0, 90)
+big2 = model.addExtrusion(mypart, sk3.selectFace(), 110)
+
+cut2 = model.addCut(mypart, big2.result(), smallcyl.result())
+
+model.end()
+
+# two booleans and small cylinder
+assert(mypart.size("Bodies") == 3)
+
+
+# make the flag as not-persistent => cylinder must be disappeared
+model.begin()
+recover.setIsPersistent(False)
+model.end()
+# only two booleans
+assert(mypart.size("Bodies") == 2)
diff --git a/src/FeaturesPlugin/icons/recover.png b/src/FeaturesPlugin/icons/recover.png
new file mode 100644 (file)
index 0000000..5b5619c
Binary files /dev/null and b/src/FeaturesPlugin/icons/recover.png differ
index 98786b67b967aaa2462b0834159ae0e89a456492..cd08911d61c63b139e11dea127117ad2ef9b3eb1 100644 (file)
         icon="icons/Features/shape_group.png">
         <source path="group_widget.xml"/>
       </feature>
-    </group>
-    <group id="Recover">
       <feature id="Recover"
         title="Recover"
         tooltip="Visualize concealed objects"
-        icon="">
+        icon="icons/Features/recover.png">
         <source path="recover_widget.xml"/>
       </feature>
     </group>
index daf0d16b5994704718fed29b8a68fdfcfbf05c82..51582a8b79aa906cff82f3c169ff22d722ee090b 100644 (file)
@@ -1,12 +1,13 @@
 <!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
 
 <source>
-  <shape_selector id="base_shape"
-                  label="Shape:"
-                  tooltip="Select a feature of concealed objects."
+  <shape_selector id="base_feature"
+                  label="Feature:"
+                  tooltip="Select a feature that conceals results."
                   shape_types="objects"/>
-  <concealed_objects_view id="recovered_entities"
-                  tooltip="Concealed objects"
-                  base_shape_attribute="base_shape"
+  <concealed_objects_view id="recovered"
+                  tooltip="Concealed results to be recevered"
+                  base_shape_attribute="base_feature"
                   obligatory="0"/>
-</source>
\ No newline at end of file
+  <boolvalue id="persistent" label="Persistent" default="false" tooltip="Makes unable to conceal result again" obligatory="0"/>
+</source>
index fe4ec99dbc8ddc9877ad1389edcfce3f49e78057..60714f8becb2a6d490c21542327ee6954207acbf 100644 (file)
@@ -455,7 +455,8 @@ void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID,
     // the second condition is for history upper than concealment causer, so the feature result may
     // be displayed and previewed; also for avoiding of quick show/hide on history
     // moving deep down
-    if (aRes && !theFeature->isDisabled()) {
+    if (aRes && !theFeature->isDisabled() && 
+        !ModelAPI_Session::get()->validators()->isUnconcealed(aRes, theFeature)) {
       aRes->setIsConcealed(true);
     }
   }
@@ -473,9 +474,11 @@ void Model_Data::updateConcealmentFlag()
           std::shared_ptr<ModelAPI_Result> aRes = 
             std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
           if (aRes.get()) {
-            aRes->setIsConcealed(true); // set concealed
+            if (!ModelAPI_Session::get()->validators()->isUnconcealed(aRes, aFeature)) {
+              aRes->setIsConcealed(true); // set concealed
+              return;
+            }
           }
-          return;
         }
       }
     }
index c8a5a03d8d043b7a5ab392199010761bdeda676a..6264e68b5ae1b054ff348b2f9cd87a418f41f76f 100644 (file)
@@ -74,6 +74,7 @@ class Model_Data : public ModelAPI_Data
   friend class Model_AttributeRefAttrList;
   friend class Model_AttributeSelection;
   friend class Model_AttributeSelectionList;
+  friend class Model_ValidatorsFactory;
 
  public:
   /// The simplest constructor. "setLabel" must be called just after to initialize correctly.
index ed7ffac935fbe369404336b7f315d183b0077ea8..f7a58ddb68058b0100fd161fb011e5892e04097e 100644 (file)
@@ -13,6 +13,7 @@
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_AttributeValidator.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
 #include <Model_Data.h>
 
 #include <Events_InfoMessage.h>
@@ -313,6 +314,54 @@ bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string th
   return aFind != myConcealed.end() && aFind->second.find(theAttribute) != aFind->second.end();
 }
 
+void Model_ValidatorsFactory::registerUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
+{
+  if (myUnconcealed.find(theUnconcealed) == myUnconcealed.end()) {
+    myUnconcealed[theUnconcealed] = std::list<std::shared_ptr<ModelAPI_Feature> >();
+  }
+  myUnconcealed[theUnconcealed].push_back(theCanceledFeat);
+  std::dynamic_pointer_cast<Model_Data>(theUnconcealed->data())->updateConcealmentFlag();
+}
+
+void Model_ValidatorsFactory::disableUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
+{
+  std::map<std::shared_ptr<ModelAPI_Result>, std::list<std::shared_ptr<ModelAPI_Feature> > >
+    ::iterator aResFound = myUnconcealed.find(theUnconcealed);
+  if (aResFound != myUnconcealed.end()) {
+    std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anIter = aResFound->second.begin();
+    for(; anIter != aResFound->second.end(); anIter++) {
+      if (*anIter == theCanceledFeat) {
+        aResFound->second.erase(anIter);
+        std::dynamic_pointer_cast<Model_Data>(theUnconcealed->data())->updateConcealmentFlag();
+        break;
+      }
+    }
+  }
+}
+
+bool Model_ValidatorsFactory::isUnconcealed(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat)
+{
+  std::map<std::shared_ptr<ModelAPI_Result>, std::list<std::shared_ptr<ModelAPI_Feature> > >
+    ::iterator aResFound = myUnconcealed.find(theUnconcealed);
+  if (aResFound != myUnconcealed.end()) {
+    std::list<std::shared_ptr<ModelAPI_Feature> >::iterator aFeatIter = aResFound->second.begin();
+    for(; aFeatIter != aResFound->second.end(); aFeatIter++) {
+      if (aFeatIter->get()) {
+        if ((*aFeatIter)->isDisabled()) continue;
+        if (*aFeatIter == theCanceledFeat)
+          return true; // this is exactly canceled
+        if (theCanceledFeat->document()->isLater(*aFeatIter, theCanceledFeat))
+          return true; // if unconcealed feature (from the list) is later than concealed
+      } else
+        return true; // empty attribute means that everything is canceled
+    }
+  }
+  return false;
+}
+
 void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute,
                             const std::list<std::pair<std::string, std::string> >& theCases)
 {
@@ -331,7 +380,7 @@ void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string t
     aFindAttrID = aFindFeature->second.find(theAttribute);
   }
   std::list<std::pair<std::string, std::string> >::const_iterator aCasesIt = theCases.begin(),
-                                                                        aCasesLast = theCases.end();
+                                                                       aCasesLast = theCases.end();
   std::map<std::string, std::set<std::string> > aFindCases = aFindAttrID->second;
   for (; aCasesIt != aCasesLast; aCasesIt++) {
     std::pair<std::string, std::string> aCasePair = *aCasesIt;
index 87a9b02da198fec2edf95b2d01b6c43df3fe770f..bda886ec9509c4811f497a27b17456991a6857ab 100644 (file)
@@ -37,6 +37,10 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory
   /// Stores the registered attributes that leads to the concealment of referenced objects in 
   /// data tree. Map from feature kind to set of attribute IDs.
   std::map<std::string, std::set<std::string> > myConcealed;
+  /// Stored the unconcealed results and features that caused the canceled concealment (Recover).
+  /// If the feature is empty, unconcealment is persistent.
+  std::map<std::shared_ptr<ModelAPI_Result>, std::list<std::shared_ptr<ModelAPI_Feature> > >
+    myUnconcealed;
   /// Stores the registered attributes must be checked only if the particular case is activated
   /// Map from feature kind to map of attribute IDs to pair 
   // (switchId (ID of the attribute) and case Ids (possible values of the switch attribute))
@@ -67,8 +71,8 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory
   MODEL_EXPORT virtual void validators(const std::string& theFeatureID,
                                        Validators& theResult) const;
   /// Provides a validator for the attribute, returns NULL if no validator
-  MODEL_EXPORT virtual void validators(const std::string& theFeatureID, const std::string& theAttrID,
-                                       Validators& theResult) const;
+  MODEL_EXPORT virtual void validators(const std::string& theFeatureID, 
+    const std::string& theAttrID, Validators& theResult) const;
 
   /// Returns registered validator by its Id
   MODEL_EXPORT virtual const ModelAPI_Validator* validator(const std::string& theID) const;
@@ -94,9 +98,18 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory
   /// Returns true that it was registered that attribute conceals the referenced result
   virtual bool isConcealed(std::string theFeature, std::string theAttribute);
 
-  /// register the case-attribute (\a myCases set definition)
-  //virtual void registerCase(std::string theFeature, std::string theAttribute,
-  //  std::string theSwitchId, std::string theCaseId);
+  /// Registers (by Recover feature) cancel of concealment of specific result by specific feature.
+  /// If theCanceledFeat is empty, the concealment is canceled for this result forever.
+  virtual void registerUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat);
+
+  /// Disables cancel of concealment of specific result by specific feature.
+  virtual void disableUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat);
+
+  /// Returns true if concealment is canceled.
+  virtual bool isUnconcealed(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat);
 
   /// register the case-attribute (\a myCases set definition)
   virtual void registerCase(std::string theFeature, std::string theAttribute,
index 0557333ba75079b3ae9ae5b4570d627d13becda9..c621363d5e147b15fdf43d7382f336605c88face 100644 (file)
@@ -101,6 +101,19 @@ class MODELAPI_EXPORT ModelAPI_ValidatorsFactory
   /// Returns true that it was registered that attribute conceals the referenced result
   virtual bool isConcealed(std::string theFeature, std::string theAttribute) = 0;
 
+  /// Registers (by Recover feature) cancel of concealment of specific result by specific feature.
+  /// If theCanceledFeat is empty, the concealment is canceled for this result forever.
+  virtual void registerUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat) = 0;
+
+  /// Disables cancel of concealment of specific result by specific feature.
+  virtual void disableUnconcealment(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat) = 0;
+
+  /// Returns true if concealment is canceled.
+  virtual bool isUnconcealed(std::shared_ptr<ModelAPI_Result> theUnconcealed,
+    std::shared_ptr<ModelAPI_Feature> theCanceledFeat) = 0;
+
   /// Register the case-attribute: this attribute is checked only if its case is selected
   virtual void registerCase(std::string theFeature, std::string theAttribute,
     const std::list<std::pair<std::string, std::string> >& theCases) = 0;
index 0e47ce3bdf55e955e94ce7a171e01bc4d6d43a7b..dfd97daaf3479d08a7c7adc122a600755cd88bb6 100644 (file)
@@ -9,6 +9,7 @@ SET(PROJECT_HEADERS
   ModelHighAPI_Interface.h
   ModelHighAPI_Macro.h
   ModelHighAPI_RefAttr.h
+  ModelHighAPI_Reference.h
   ModelHighAPI_Selection.h
   ModelHighAPI_Services.h
   ModelHighAPI_Tools.h
@@ -19,6 +20,7 @@ SET(PROJECT_SOURCES
   ModelHighAPI_Integer.cpp
   ModelHighAPI_Interface.cpp
   ModelHighAPI_RefAttr.cpp
+  ModelHighAPI_Reference.cpp
   ModelHighAPI_Selection.cpp
   ModelHighAPI_Services.cpp
   ModelHighAPI_Tools.cpp
@@ -81,4 +83,5 @@ ADD_UNIT_TESTS(
   TestDouble.py
   TestInteger.py
   TestRefAttr.py
+  TestReference.py
 )
index 20e33804254982f59c4e428414434ba42ea3f5e3..1dd6be785468439f60bae52811ee3e1bbb777ca8 100644 (file)
   }
 }
 
+%typemap(in) const ModelHighAPI_Reference & (ModelHighAPI_Reference temp) {
+  std::shared_ptr<ModelAPI_Object> * temp_object;
+  std::shared_ptr<ModelHighAPI_Interface> * temp_interface;
+  int newmem = 0;
+  if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_object, $descriptor(std::shared_ptr<ModelAPI_Object> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+    if (!temp_object) {
+      PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Interface or ModelAPI_Object.");
+      return NULL;
+    }
+    temp = ModelHighAPI_Reference(*temp_object);
+    if (newmem & SWIG_CAST_NEW_MEMORY) {
+      delete temp_object;
+    }
+    $1 = &temp;
+  } else
+  if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_interface, $descriptor(std::shared_ptr<ModelHighAPI_Interface> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+    if (!temp_interface) {
+      PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Interface or ModelAPI_Object.");
+      return NULL;
+    }
+    temp = ModelHighAPI_Reference(*temp_interface);
+    if (newmem & SWIG_CAST_NEW_MEMORY) {
+      delete temp_interface;
+    }
+    $1 = &temp;
+  } else
+  if ((SWIG_ConvertPtr($input, (void **)&$1, $1_descriptor, SWIG_POINTER_EXCEPTION)) == 0) {
+  } else {
+    PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Interface or ModelAPI_Object.");
+    return NULL;
+  }
+}
+
+%typecheck(SWIG_TYPECHECK_POINTER) ModelHighAPI_Reference, const ModelHighAPI_Reference & {
+  std::shared_ptr<ModelAPI_Object> * temp_object;
+  std::shared_ptr<ModelHighAPI_Interface> * temp_interface;
+  int newmem = 0;
+  if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_object, $descriptor(std::shared_ptr<ModelAPI_Object> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+    if (temp_object) {
+      $1 = 1;
+    } else {
+      $1 = 0;
+    }
+  } else
+  if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_interface, $descriptor(std::shared_ptr<ModelHighAPI_Interface> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+    if (temp_interface) {
+      $1 = 1;
+    } else {
+      $1 = 0;
+    }
+  } else {
+    $1 = 0;
+  }
+}
+
 %typemap(out) const ModelHighAPI_Selection & {
   $1_basetype * ptr = new $1_basetype(*$1);
   $result = SWIG_NewPointerObj( (void*) ptr, $1_descriptor, 1 );
 }
 
+%typemap(out) const ModelHighAPI_Reference & {
+  $1_basetype * ptr = new $1_basetype(*$1);
+  $result = SWIG_NewPointerObj( (void*) ptr, $1_descriptor, 1 );
+}
+
 // std::list -> []
 %template(SelectionList) std::list<ModelHighAPI_Selection>;
 %template(RefAttrList) std::list<ModelHighAPI_RefAttr>;
+%template(RefList) std::list<ModelHighAPI_Reference>;
 
 // all supported interfaces
 %include "ModelHighAPI_Double.h"
 %include "ModelHighAPI_Integer.h"
 %include "ModelHighAPI_Interface.h"
 %include "ModelHighAPI_RefAttr.h"
+%include "ModelHighAPI_Reference.h"
 %include "ModelHighAPI_Selection.h"
 %include "ModelHighAPI_Services.h"
 %include "ModelHighAPI_Macro.h"
diff --git a/src/ModelHighAPI/ModelHighAPI_Reference.cpp b/src/ModelHighAPI/ModelHighAPI_Reference.cpp
new file mode 100644 (file)
index 0000000..3e13a0b
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        FeaturesAPI_Reference.cpp
+// Created:     04 August 2016
+// Author:      Mikhail Ponikarov
+
+//--------------------------------------------------------------------------------------
+#include "ModelHighAPI_Reference.h"
+
+#include <ModelAPI_AttributeReference.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+#include "ModelHighAPI_Interface.h"
+//--------------------------------------------------------------------------------------
+ModelHighAPI_Reference::ModelHighAPI_Reference()
+{}
+
+ModelHighAPI_Reference::ModelHighAPI_Reference(
+    const std::shared_ptr<ModelAPI_Object> & theValue)
+: myObject(theValue)
+{}
+
+ModelHighAPI_Reference::ModelHighAPI_Reference(
+    const std::shared_ptr<ModelHighAPI_Interface> & theValue)
+: myObject(std::shared_ptr<ModelAPI_Object>(theValue->defaultResult()))
+{
+}
+
+ModelHighAPI_Reference::~ModelHighAPI_Reference()
+{
+}
+
+//--------------------------------------------------------------------------------------
+void ModelHighAPI_Reference::fillAttribute(
+    const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute) const
+{
+  theAttribute->setValue(myObject);
+}
+
+//--------------------------------------------------------------------------------------
+void ModelHighAPI_Reference::appendToList(
+    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute) const
+{
+  theAttribute->append(myObject);
+}
diff --git a/src/ModelHighAPI/ModelHighAPI_Reference.h b/src/ModelHighAPI/ModelHighAPI_Reference.h
new file mode 100644 (file)
index 0000000..71a6f2a
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        FeaturesAPI_Reference.h
+// Created:     04 August 2016
+// Author:      Mikhail Ponikarov
+
+#ifndef SRC_MODELHIGHAPI_MODELHIGHAPI_REFERENCE_H_
+#define SRC_MODELHIGHAPI_MODELHIGHAPI_REFERENCE_H_
+
+//--------------------------------------------------------------------------------------
+#include "ModelHighAPI.h"
+
+#include <memory>
+#include <string>
+//--------------------------------------------------------------------------------------
+class ModelAPI_Attribute;
+class ModelAPI_AttributeReference;
+class ModelAPI_AttributeRefList;
+class ModelAPI_Object;
+class ModelHighAPI_Interface;
+//--------------------------------------------------------------------------------------
+/**\class ModelHighAPI_Reference
+ * \ingroup CPPHighAPI
+ * \brief Class for filling ModelAPI_AttributeReference
+ */
+class ModelHighAPI_Reference
+{
+public:
+  /// Default constructor
+  MODELHIGHAPI_EXPORT
+  ModelHighAPI_Reference();
+  /// Constructor for object
+  MODELHIGHAPI_EXPORT
+  ModelHighAPI_Reference(const std::shared_ptr<ModelAPI_Object> & theValue);
+  /// Constructor for Interface (use result() for object)
+  MODELHIGHAPI_EXPORT
+  ModelHighAPI_Reference(const std::shared_ptr<ModelHighAPI_Interface> & theValue);
+  /// Destructor
+  MODELHIGHAPI_EXPORT
+  virtual ~ModelHighAPI_Reference();
+
+  /// Fill attribute values
+  MODELHIGHAPI_EXPORT
+  virtual void fillAttribute(const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute) const;
+
+  /// Append to list attribute
+  MODELHIGHAPI_EXPORT
+  virtual void appendToList(const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute) const;
+
+private:
+  std::shared_ptr<ModelAPI_Object> myObject;
+};
+
+//--------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------
+#endif /* SRC_MODELHIGHAPI_MODELHIGHAPI_REFATTR_H_ */
index fb1df5c4c4d14639fa679a78c0700898e518c572..be4e0186f020be400cbafd5d67dee676583dcb72 100644 (file)
@@ -31,6 +31,7 @@
 #include "ModelHighAPI_Double.h"
 #include "ModelHighAPI_Integer.h"
 #include "ModelHighAPI_RefAttr.h"
+#include "ModelHighAPI_Reference.h"
 #include "ModelHighAPI_Selection.h"
 
 #include <algorithm>
@@ -104,6 +105,22 @@ void fillAttribute(const std::list<ModelHighAPI_RefAttr> & theValue,
     it->appendToList(theAttribute);
 }
 
+//--------------------------------------------------------------------------------------
+void fillAttribute(const ModelHighAPI_Reference & theValue,
+                   const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute)
+{
+  theValue.fillAttribute(theAttribute);
+}
+
+//--------------------------------------------------------------------------------------
+void fillAttribute(const std::list<ModelHighAPI_Reference> & theValue,
+                   const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
+{
+  theAttribute->clear();
+  for (auto it = theValue.begin(); it != theValue.end(); ++it)
+    it->appendToList(theAttribute);
+}
+
 //--------------------------------------------------------------------------------------
 void fillAttribute(const std::shared_ptr<ModelAPI_Object> & theValue,
                    const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute)
@@ -120,6 +137,15 @@ void fillAttribute(const std::list<std::shared_ptr<ModelAPI_Object> > & theValue
     theAttribute->append(*it);
 }
 
+MODELHIGHAPI_EXPORT
+void fillAttribute(const std::list<ModelHighAPI_Selection> & theValue,
+                   const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
+{
+  theAttribute->clear();
+  for (auto it = theValue.begin(); it != theValue.end(); ++it)
+    theAttribute->append(it->resultSubShapePair().first); // use only context
+}
+
 //--------------------------------------------------------------------------------------
 void fillAttribute(const ModelHighAPI_Selection & theValue,
                    const std::shared_ptr<ModelAPI_AttributeSelection> & theAttribute)
index d731086b1d801df2fe826448c3b2136628040f12..f5467566d61bc31c1ee3bcb845d86c8f91574c25 100644 (file)
@@ -41,6 +41,7 @@ class ModelAPI_Object;
 class ModelHighAPI_Double;
 class ModelHighAPI_Integer;
 class ModelHighAPI_RefAttr;
+class ModelHighAPI_Reference;
 class ModelHighAPI_Selection;
 //--------------------------------------------------------------------------------------
 MODELHIGHAPI_EXPORT
@@ -84,6 +85,14 @@ MODELHIGHAPI_EXPORT
 void fillAttribute(const std::list<ModelHighAPI_RefAttr> & theValue,
                    const std::shared_ptr<ModelAPI_AttributeRefAttrList> & theAttribute);
 
+MODELHIGHAPI_EXPORT
+void fillAttribute(const ModelHighAPI_Reference & theValue,
+                   const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute);
+
+MODELHIGHAPI_EXPORT
+void fillAttribute(const std::list<ModelHighAPI_Reference> & theValue,
+                   const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute);
+
 MODELHIGHAPI_EXPORT
 void fillAttribute(const std::shared_ptr<ModelAPI_Object> & theValue,
                    const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute);
@@ -92,6 +101,10 @@ MODELHIGHAPI_EXPORT
 void fillAttribute(const std::list<std::shared_ptr<ModelAPI_Object> > & theValue,
                    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute);
 
+MODELHIGHAPI_EXPORT
+void fillAttribute(const std::list<ModelHighAPI_Selection> & theValue,
+                   const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute);
+
 MODELHIGHAPI_EXPORT
 void fillAttribute(const ModelHighAPI_Selection & theValue,
                    const std::shared_ptr<ModelAPI_AttributeSelection> & theAttribute);
index 2205a87963e2cc0309bac3b6ccd544e068b934d3..d430240cc3793feae9c66c8b5447dbdca9cb04e6 100644 (file)
@@ -17,6 +17,7 @@
   #include "ModelHighAPI_Interface.h"
   #include "ModelHighAPI_Macro.h"
   #include "ModelHighAPI_RefAttr.h"
+  #include "ModelHighAPI_Reference.h"
   #include "ModelHighAPI_Selection.h"
   #include "ModelHighAPI_Services.h"
   #include "ModelHighAPI_Tools.h"
diff --git a/src/ModelHighAPI/Test/TestReference.py b/src/ModelHighAPI/Test/TestReference.py
new file mode 100644 (file)
index 0000000..136894e
--- /dev/null
@@ -0,0 +1,35 @@
+import unittest
+
+import ModelAPI
+import ModelHighAPI
+import model
+
+class FeaturesFixture(unittest.TestCase):
+
+    def setUp(self):
+        model.begin()
+        # Create part
+        partset = model.moduleDocument()
+        self.part = model.addPart(partset).document()
+        model.do()
+        self.feature = model.addPoint(self.part, 0, 0, 0)
+
+    def tearDown(self):
+        model.end()
+        model.reset()
+
+
+class RefAttrTestCase(FeaturesFixture):
+
+    def test_create_default(self):
+        ModelHighAPI.ModelHighAPI_Reference()
+
+    def test_create_from_object(self):
+        ModelHighAPI.ModelHighAPI_Reference(self.feature.feature())
+
+    def test_create_from_None(self):
+        ModelHighAPI.ModelHighAPI_Reference(None)
+
+
+if __name__ == "__main__":
+    unittest.main()
index b0f8a075e534b2eb8aa96bb8b62108138be26beb..9d1dd8d174aa7ae83757d9edc0af96c7780dc378 100644 (file)
@@ -10,4 +10,5 @@ from FeaturesAPI import addPartition
 from FeaturesAPI import addExtrusion, addExtrusionCut, addExtrusionFuse
 from FeaturesAPI import addRevolution, addRevolutionCut, addRevolutionFuse
 
-from FeaturesAPI import addGroup
+from FeaturesAPI import addGroup, addRecover
+
index 98c74cb2e55ef847af5f7cacf9b888d1991d52d4..73321550bff7b40a0f034d5f058ca717320961f6 100755 (executable)
@@ -112,7 +112,7 @@ static bool hasCoincidentPoint(FeaturePtr theFeature1, FeaturePtr theFeature2)
 {
   FeaturePtr aCoincidenceFeature = SketchPlugin_ConstraintCoincidence::findCoincidenceFeature
                                                                   (theFeature1, theFeature2);
-  return aCoincidenceFeature.get();
+  return aCoincidenceFeature.get() != NULL;
 }
 
 bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute,