Salome HOME
Issue #1664: In the Sketcher, add the function Split a segment:
authornds <nds@opencascade.com>
Thu, 28 Jul 2016 16:54:13 +0000 (19:54 +0300)
committernds <nds@opencascade.com>
Thu, 28 Jul 2016 16:54:13 +0000 (19:54 +0300)
1. cash for attribute point 2d to projected point to avoid repeated geometrical calculations
2. restart of split operation: highlight sub-shapes

13 files changed:
src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp
src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h
src/ModuleBase/ModuleBase_IModule.h
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_OperationPrs.cpp
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherReetntrantMgr.cpp
src/PartSet/PartSet_WidgetSubShapeSelector.cpp
src/PartSet/PartSet_WidgetSubShapeSelector.h
src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp
src/SketchPlugin/SketchPlugin_ConstraintSplit.h
src/SketchPlugin/SketchPlugin_Validators.cpp

index 5621684a472a3d38ce58f19f603bc4adbecd491e..f27954b1008b617485735f4b6bf001e624a695ce 100755 (executable)
@@ -120,7 +120,9 @@ namespace ModelGeomAlgo_Point2D {
                             const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
                             const std::shared_ptr<GeomAPI_Dir>& theDirX,
                             const std::shared_ptr<GeomAPI_Dir>& theDirY,
-                            std::set<std::shared_ptr<GeomAPI_Pnt> >& thePoints)
+                            std::set<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
+                            std::map<std::shared_ptr<GeomDataAPI_Point2D>,
+                                     std::shared_ptr<GeomAPI_Pnt> >& theAttributeToPoint)
   {
     std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
                                                             aLast = theAttributes.end();
@@ -129,8 +131,10 @@ namespace ModelGeomAlgo_Point2D {
       std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
       std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
       std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
-      if (isPointOnEdge(theBaseShape, aPoint, aProjectedPoint))
+      if (isPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
         thePoints.insert(aProjectedPoint);
+        theAttributeToPoint[anAttribute] = aProjectedPoint;
+      }
     }
   }
 
index be1521bdc460313c56fb54362784d1b42d7d7099..826dde4a6d71917aee31fcd03478b16c59b62f90 100755 (executable)
@@ -21,6 +21,7 @@ class GeomDataAPI_Point2D;
 #include <memory>
 #include <string>
 #include <set>
+#include <map>
 
 
 namespace ModelGeomAlgo_Point2D {
@@ -68,7 +69,9 @@ namespace ModelGeomAlgo_Point2D {
                               const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
                               const std::shared_ptr<GeomAPI_Dir>& theDirX,
                               const std::shared_ptr<GeomAPI_Dir>& theDirY,
-                              std::set<std::shared_ptr<GeomAPI_Pnt> >& thePoints);
+                              std::set<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
+                              std::map<std::shared_ptr<GeomDataAPI_Point2D>,
+                                       std::shared_ptr<GeomAPI_Pnt> >& theAttributeToPoint);
 
   /// Finds projected point to the given shape line
   /// \param theBaseShape a shape of check
index e0937f09e21e600298048c02dfd1cd71fe38d697..75cd6e62aea767d8aea70b9a7f9e0746788ed713 100755 (executable)
@@ -201,6 +201,11 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
   /// \param theTypes a selection modes to be extended\r
   virtual void customSubShapesSelectionModes(QIntList& theTypes) {}\r
 \r
+  /// Return true if the custom presentation is activated\r
+  /// \param theFlag a flag of level of customization, which means that only part of sub-elements\r
+  /// \return boolean value\r
+  virtual bool isCustomPrsActivated(const ModuleBase_CustomizeFlag& theFlag) const { return false; };\r
+\r
   /// Activate custom presentation for the object. Default realization is empty.\r
   /// \param theFeature a feature instance\r
   /// \param theFlag a flag of level of customization, which means that only part of sub-elements\r
index 8c818d861c0666a7b4edaeee80268643560e114b..101dfc15a5d5f5fe5128674fa59207de3ec9c053 100755 (executable)
@@ -754,7 +754,7 @@ ModuleBase_ModelWidget* PartSet_Module::activeWidget() const
     ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
     if (aOperation) {
       ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
-      anActiveWidget = aPanel->activeWidget();
+      anActiveWidget = aPanel ? aPanel->activeWidget() : 0;
     }
   }
   return anActiveWidget;
@@ -977,6 +977,11 @@ void PartSet_Module::onViewTransformed(int theTrsfType)
     aDisplayer->updateViewer();
 }
 
+bool PartSet_Module::isCustomPrsActivated(const ModuleBase_CustomizeFlag& theFlag) const
+{
+  return myCustomPrs->isActive(theFlag);
+}
+
 void PartSet_Module::activateCustomPrs(const FeaturePtr& theFeature, const ModuleBase_CustomizeFlag& theFlag,
                                        const bool theUpdateViewer)
 {
index 014790aa4d016eeebf2086739735c62c82436172..64ae1c0994aa42677256bb440f90ea018cb586ac 100755 (executable)
@@ -226,6 +226,11 @@ public:
   /// \param theFeature a feature
   void setCustomized(const FeaturePtr& theFeature);
 
+  /// Return true if the custom presentation is activated
+  /// \param theFlag a flag of level of customization, which means that only part of sub-elements
+  /// \return boolean value
+  virtual bool isCustomPrsActivated(const ModuleBase_CustomizeFlag& theFlag) const;
+
   /// Activate custom presentation for the object
   /// \param theFeature a feature instance
   /// \param theFlag a flag of level of customization, which means that only part of sub-elements
index d5e81272352a1ff9f17727c7227f32e4b31a9869..529f0371d81c69019491ee8b0a35c1f883f2c68a 100755 (executable)
@@ -349,13 +349,9 @@ void PartSet_OperationPrs::getHighlightedShapes(ModuleBase_IWorkshop* theWorksho
   theObjectShapes.clear();
 
   QList<ModuleBase_ViewerPrsPtr> aValues;
-  ModuleBase_IPropertyPanel* aPanel = theWorkshop->propertyPanel();
-  if (aPanel) {
-    ModuleBase_ModelWidget* aWidget = aPanel->activeWidget();
-    if (aWidget) {
-      aWidget->getHighlighted(aValues);
-    }
-  }
+  ModuleBase_ModelWidget* anActiveWidget = theWorkshop->module()->activeWidget();
+  if (anActiveWidget)
+    anActiveWidget->getHighlighted(aValues);
 
   QList<GeomShapePtr> aShapes;
   QList<ModuleBase_ViewerPrsPtr>::const_iterator anIIt = aValues.begin(),
index ce2b209ce5267d39a35b0d33c746de2bcac970c9..a46d07f9d7413038f82e3b2086aca17e33aaa3e0 100755 (executable)
@@ -446,7 +446,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
     // 1. perform the widget mouse move functionality and display the presentation
     // the mouse move should be processed in the widget, if it can in order to visualize correct
     // presentation. These widgets correct the feature attribute according to the mouse position
-    ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
+    ModuleBase_ModelWidget* anActiveWidget = myModule->activeWidget();
     PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
     if (aProcessor)
       aProcessor->mouseMoved(theWnd, theEvent);
index fb8ce49e7211efc81f2a6044784380bb6ca97046..52972494fe742cfab0b05335122aa8dca304f03f 100755 (executable)
@@ -58,9 +58,11 @@ ModuleBase_ModelWidget* PartSet_SketcherReetntrantMgr::internalActiveWidget() co
   ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
   if (anOperation) {
     ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
-    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
-    if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector()))
-      aWidget = myInternalActiveWidget;
+    if (aPanel) { // check for case when the operation is started but property panel is not filled
+      ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+      if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector()))
+        aWidget = myInternalActiveWidget;
+    }
   }
   return aWidget;
 }
@@ -125,8 +127,8 @@ void PartSet_SketcherReetntrantMgr::operationAborted(ModuleBase_Operation* theOp
   resetFlags();
 }
 
-bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* /* theWnd*/,
-                                                      QMouseEvent* /* theEvent*/)
+bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* theWnd,
+                                                      QMouseEvent* theEvent)
 {
   bool aProcessed = false;
   if (!isActiveMgr())
@@ -140,7 +142,6 @@ bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* /*
     if (aLastFeature) {
       ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget();
       ModuleBase_IPropertyPanel* aPanel = myWorkshop->currentOperation()->propertyPanel();
-      bool aWidgetIsFilled = false;
 
       FeaturePtr aCurrentFeature = aFOperation->feature();
       bool isLineFeature = false, isArcFeature = false;
@@ -158,11 +159,14 @@ bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* /*
         anActiveWidget = module()->activeWidget();
         aCurrentFeature = anActiveWidget->feature();
         aProcessed = true;
-        if (isLineFeature || isArcFeature)
-          aWidgetIsFilled = true;
-      }
-      if (aWidgetIsFilled)
         aPanel->activateNextWidget(anActiveWidget);
+      } else {
+        // processing mouse move in active widget of restarted operation
+        ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget();
+        PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
+        if (aProcessor)
+          aProcessor->mouseMoved(theWnd, theEvent);
+      }
     }
   }
   return aProcessed;
index 46c20aceac60ed3d84ba0ecfaa805ece786dc4d7..35480469d79694337cc27f03b07b59910334d705 100755 (executable)
@@ -86,7 +86,10 @@ void PartSet_WidgetSubShapeSelector::mouseMoved(ModuleBase_IViewWindow* theWindo
       const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
       if (!aShapes.empty()) {
         gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
-        std::shared_ptr<GeomAPI_Pnt> aPoint(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));
+        double aX, anY;
+        Handle(V3d_View) aView = theWindow->v3dView();
+        PartSet_Tools::convertTo2D(aPnt, mySketch, aView, aX, anY);
+        std::shared_ptr<GeomAPI_Pnt> aPoint = PartSet_Tools::convertTo3D(aX, anY, mySketch);
 
         std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
         for (; anIt != aLast; anIt++) {
@@ -98,7 +101,14 @@ void PartSet_WidgetSubShapeSelector::mouseMoved(ModuleBase_IViewWindow* theWindo
                 myCurrentSubShape->shape() != aBaseShape) {
               myCurrentSubShape->setObject(anObject);
               myCurrentSubShape->setShape(aBaseShape);
-              myWorkshop->module()->customizeObject(myFeature,
+
+              ModuleBase_IModule* aModule = myWorkshop->module();
+
+
+              if (!aModule->isCustomPrsActivated(ModuleBase_IModule::CustomizeHighlightedObjects))
+                aModule->activateCustomPrs(myFeature,
+                                           ModuleBase_IModule::CustomizeHighlightedObjects, true);
+              aModule->customizeObject(myFeature,
                                        ModuleBase_IModule::CustomizeHighlightedObjects, true);
             }
             else
@@ -134,11 +144,6 @@ bool PartSet_WidgetSubShapeSelector::setSelection(
                                           QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theValues,
                                           const bool theToValidate)
 {
-  //if (theToValidate)
-  //  bool aResult = ModuleBase_WidgetShapeSelector::setSelection(theValues, theToValidate);
-  //else {
-  // the sub-shape is selected, initial shape is not highlighted/selected, we need to use
-  // the sub-shape to fill attribute;
   ObjectPtr aBaseObject = myCurrentSubShape->object();
   GeomShapePtr aBaseShape = myCurrentSubShape->shape();
   bool aResult = aBaseObject.get() && aBaseShape.get();
@@ -150,48 +155,45 @@ bool PartSet_WidgetSubShapeSelector::setSelection(
   }
   // secondly fill additional attributes
   if (aResult) {
+    aResult = false;
     if (aBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
       std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aBaseShape));
 
       std::shared_ptr<GeomAPI_Pnt> aFirstPnt = anEdge->firstPoint();
       std::shared_ptr<GeomAPI_Pnt> aLastPnt = anEdge->lastPoint();
-      std::shared_ptr<GeomAPI_Pnt2d> aFirstPnt2D = PartSet_Tools::convertTo2D(mySketch, aFirstPnt);
-      std::shared_ptr<GeomAPI_Pnt2d> aLastPnt2D = PartSet_Tools::convertTo2D(mySketch, aLastPnt);
-
 
+      std::shared_ptr<GeomDataAPI_Point2D> aFirstPointAttr, aLastPointAttr;
       /// find the points in feature attributes
       FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
       std::list<AttributePtr> a2DPointAttributes = aBaseFeature->data()->attributes(
                                                         GeomDataAPI_Point2D::typeId());
       std::list<AttributePtr>::const_iterator anIt = a2DPointAttributes.begin(), 
                                               aLast = a2DPointAttributes.end();
-      std::shared_ptr<GeomDataAPI_Point2D> aFirstPointAttr, aLastPointAttr;
       for (; anIt != aLast; anIt++) {
         std::shared_ptr<GeomDataAPI_Point2D> anAttributePoint = 
                                       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
-        if (aFirstPnt2D->isEqual(anAttributePoint->pnt()))
+        std::shared_ptr<GeomAPI_Pnt2d> aPoint2D = anAttributePoint->pnt();
+        std::shared_ptr<GeomAPI_Pnt> aPoint3D = PartSet_Tools::convertTo3D(aPoint2D->x(),
+                                                                   aPoint2D->y(), mySketch);
+        if (aFirstPnt->isEqual(aPoint3D))
           aFirstPointAttr = anAttributePoint;
-        else if (aLastPnt2D->isEqual(anAttributePoint->pnt()))
+        else if (aLastPnt->isEqual(aPoint3D))
           aLastPointAttr = anAttributePoint;
       }
+
       /// find the points in coincident features
-      if (!aFirstPointAttr.get() || !aLastPointAttr.get()) {
-        std::set<std::shared_ptr<GeomDataAPI_Point2D> > aRefAttributes = myCashedReferences[aBaseObject];
-        std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator aRefIt = aRefAttributes.begin(),
-                                                                        aRefLast = aRefAttributes.end();
-        for (; aRefIt != aRefLast; aRefIt++) {
-          std::shared_ptr<GeomDataAPI_Point2D> anAttributePoint = *aRefIt;
-          double anX = anAttributePoint->x();
-          double anY = anAttributePoint->y();
-          if (!aFirstPointAttr.get() && aFirstPnt2D->isEqual(anAttributePoint->pnt()))
-              aFirstPointAttr = anAttributePoint;
-          if (!aLastPointAttr.get() && aLastPnt2D->isEqual(anAttributePoint->pnt()))
-              aLastPointAttr = anAttributePoint;
-          if (aFirstPointAttr.get() && aLastPointAttr.get())
-            break;
-        }
+      PntToAttributesMap aRefAttributes = myCashedReferences[aBaseObject];
+      PntToAttributesMap::const_iterator aRIt = aRefAttributes.begin(), aRLast = aRefAttributes.end();
+      for (; aRIt != aRLast; aRIt++) {
+        std::shared_ptr<GeomDataAPI_Point2D> anAttribute = aRIt->first;
+        std::shared_ptr<GeomAPI_Pnt> aPoint = aRIt->second;
+        if (!aFirstPointAttr.get() && aFirstPnt->isEqual(aPoint))
+          aFirstPointAttr = anAttribute;
+        if (!aLastPointAttr.get() && aLastPnt->isEqual(aPoint))
+          aLastPointAttr = anAttribute;
+        if (aFirstPointAttr.get() && aLastPointAttr.get())
+          break;
       }
-
       if (!aFirstPointAttr.get() || !aLastPointAttr)
         return false;
 
@@ -202,9 +204,9 @@ bool PartSet_WidgetSubShapeSelector::setSelection(
                                           aFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
       anAPointAttr->setAttr(aFirstPointAttr);
       aBPointAttr->setAttr(aLastPointAttr);
+      aResult = true;
     }
   }
-  //}
 
   return aResult;
 }
@@ -221,8 +223,8 @@ void PartSet_WidgetSubShapeSelector::getHighlighted(
 void PartSet_WidgetSubShapeSelector::fillObjectShapes(const ObjectPtr& theObject)
 {
   std::set<std::shared_ptr<GeomAPI_Shape> > aShapes;
+  std::map<std::shared_ptr<GeomDataAPI_Point2D>, std::shared_ptr<GeomAPI_Pnt> > aPointToAttributes;
   std::set<std::shared_ptr<GeomDataAPI_Point2D> > aRefAttributes;
-
   // current feature
   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
   std::set<GeomShapePtr> anEdgeShapes;
@@ -246,73 +248,11 @@ void PartSet_WidgetSubShapeSelector::fillObjectShapes(const ObjectPtr& theObject
     std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
     std::set<std::shared_ptr<GeomAPI_Pnt> > aPoints;
     ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
-                                                aX->dir(), aY, aPoints);
+                                                aX->dir(), aY, aPoints, aPointToAttributes);
 
     GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes);
   }
   myCashedShapes[theObject] = aShapes;
-  myCashedReferences[theObject] = aRefAttributes;
-}
-
-//********************************************************************
-/*bool PartSet_WidgetSubShapeSelector::activateSelectionAndFilters(bool toActivate)
-{
-  bool aHasSelectionFilter = ModuleBase_WidgetShapeSelector::activateSelectionAndFilters
-                                                                           (toActivate);
-  if (!myUseSketchPlane) {
-    XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
-    PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(aWorkshop->module());
-    bool isUsePlaneFilterOnly = !toActivate;
-    aModule->sketchMgr()->activatePlaneFilter(isUsePlaneFilterOnly);
-  }
-  return aHasSelectionFilter;
+  myCashedReferences[theObject] = aPointToAttributes;
 }
 
-//********************************************************************
-bool PartSet_WidgetSubShapeSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
-{
-  bool aValid = ModuleBase_WidgetShapeSelector::isValidSelectionCustom(thePrs);
-  if (aValid) {
-    ObjectPtr anObject = myWorkshop->selection()->getResult(thePrs);
-    aValid = myExternalObjectMgr->isValidObject(anObject);
-  }
-  return aValid;
-}
-
-void PartSet_WidgetSubShapeSelector::getGeomSelection(const ModuleBase_ViewerPrsPtr& thePrs,
-                                                   ObjectPtr& theObject,
-                                                   GeomShapePtr& theShape)
-{
-  ModuleBase_WidgetShapeSelector::getGeomSelection(thePrs, theObject, theShape);
-
-  FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(theObject);
-  std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
-          std::dynamic_pointer_cast<SketchPlugin_Feature>(aSelectedFeature);
-  // there is no a sketch feature is selected, but the shape exists, try to create an exernal object
-  // TODO: unite with the same functionality in PartSet_WidgetSubShapeSelector
-  if (aSPFeature.get() == NULL) {
-    ObjectPtr anExternalObject = ObjectPtr();
-    if (myExternalObjectMgr->useExternal()) {
-      GeomShapePtr aShape = theShape;
-      if (!aShape.get()) {
-        ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
-        if (aResult.get())
-          aShape = aResult->shape();
-      }
-      if (aShape.get() != NULL && !aShape->isNull())
-        anExternalObject = myExternalObjectMgr->externalObject(theObject, aShape, sketch(), myIsInValidate);
-    }
-    /// the object is null if the selected feature is "external"(not sketch entity feature of the
-    /// current sketch) and it is not created by object manager
-    theObject = anExternalObject;
-  }
-}
-
-//********************************************************************
-void PartSet_WidgetSubShapeSelector::restoreAttributeValue(const AttributePtr& theAttribute,
-                                                        const bool theValid)
-{
-  ModuleBase_WidgetShapeSelector::restoreAttributeValue(theAttribute, theValid);
-  myExternalObjectMgr->removeExternal(sketch(), myFeature, myWorkshop, true);
-}
-*/
index b93f4d0742a91d016c9eaca0c681aef9582b690a..b20cf882d50f55abe7a2e7951a2b9e38426810be 100644 (file)
@@ -9,12 +9,11 @@
 #define PartSet_WidgetSubShapeSelector_H
 
 #include "PartSet.h"
+#include "PartSet_MouseProcessor.h"
 
 #include <ModuleBase_WidgetShapeSelector.h>
-#include <PartSet_MouseProcessor.h>
 
 #include <ModelAPI_CompositeFeature.h>
-#include <GeomDataAPI_Point2D.h>
 
 #include <QObject>
 
@@ -26,6 +25,9 @@ class Config_WidgetAPI;
 class ModuleBase_IViewWindow;
 class ModuleBase_ViewerPrs;
 
+class GeomAPI_Pnt;
+class GeomDataAPI_Point2D;
+
 class QWidget;
 class QMouseEvent;
 
@@ -112,7 +114,10 @@ protected:
 protected:
   std::shared_ptr<ModuleBase_ViewerPrs> myCurrentSubShape;
   std::map<ObjectPtr, std::set<GeomShapePtr> > myCashedShapes;
-  std::map<ObjectPtr, std::set<AttributePoint2DPtr> > myCashedReferences;
+
+  typedef std::map<std::shared_ptr<GeomDataAPI_Point2D>,
+                   std::shared_ptr<GeomAPI_Pnt> > PntToAttributesMap;
+  std::map<ObjectPtr, PntToAttributesMap> myCashedReferences;
 
   /// Pointer to a sketch 
   CompositeFeaturePtr mySketch;
index 1b59de5358d20f23d0bf495597ec40b6fd6cd685..a98724cfa1c5c7647f2c39749b74a88761d69bf6 100755 (executable)
@@ -18,6 +18,9 @@
 //#include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_AttributeRefAttr.h>
 
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_Session.h>
+
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
@@ -851,14 +854,10 @@ void SketchPlugin_ConstraintSplit::splitArc(FeaturePtr& theSplitFeature,
   arrangePoints(aStartPointAttr, anEndPointAttr, aFirstPointAttr, aSecondPointAttr);
 
   /// split feature
-  theSplitFeature = aSketch->addFeature(aFeatureKind);
-  theSplitFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue(
-                SketchPlugin_Arc::ARC_TYPE_CENTER_START_END());
-  fillAttribute(theSplitFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
-                aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
-  fillAttribute(theSplitFeature->attribute(SketchPlugin_Arc::START_ID()), aFirstPointAttr);
-  fillAttribute(theSplitFeature->attribute(SketchPlugin_Arc::END_ID()), aSecondPointAttr);
-  theSplitFeature->execute(); /// to use result of the feature in constraint
+  theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttr, aSecondPointAttr);
+  static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+  aFactory->validate(theSplitFeature); // need to be validated to update the "Apply" state if not previewed
+  std::string anError = theSplitFeature->error();
 
   if (!aStartPointAttr->pnt()->isEqual(aFirstPointAttr->pnt())) {
     theBeforeFeature = aBaseFeature; ///< use base feature to store all constraints here
@@ -872,18 +871,11 @@ void SketchPlugin_ConstraintSplit::splitArc(FeaturePtr& theSplitFeature,
   if (!aSecondPointAttr->pnt()->isEqual(anEndPointAttr->pnt())) {
     if (!theBeforeFeature) {
       theAfterFeature = aBaseFeature; ///< use base feature to store all constraints here
-      fillAttribute(theBeforeFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttr);
-    }
-    else {
-      theAfterFeature = aSketch->addFeature(aFeatureKind);
-      theAfterFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue(
-                    SketchPlugin_Arc::ARC_TYPE_CENTER_START_END());
-      fillAttribute(theAfterFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
-                    aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
       fillAttribute(theAfterFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttr);
-      fillAttribute(theAfterFeature->attribute(SketchPlugin_Arc::END_ID()), anEndPointAttr);
-      theAfterFeature->execute(); /// to use result of the feature in constraint
     }
+    else
+      theAfterFeature = createArcFeature(aBaseFeature, aSecondPointAttr, anEndPointAttr);
+
     createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
                      theSplitFeature->attribute(SketchPlugin_Arc::END_ID()),
                      theAfterFeature->attribute(SketchPlugin_Arc::START_ID()));
@@ -928,6 +920,32 @@ void SketchPlugin_ConstraintSplit::fillAttribute(const AttributePtr& theModified
     aSourceAttribute->setValue(aModifiedAttribute->pnt());
 }
 
+FeaturePtr SketchPlugin_ConstraintSplit::createArcFeature(const FeaturePtr& theBaseFeature,
+                                                          const AttributePtr& theFirstPointAttr,
+                                                          const AttributePtr& theSecondPointAttr)
+{
+  FeaturePtr aFeature;
+  SketchPlugin_Sketch* aSketch = sketch();
+  if (!aSketch || !theBaseFeature.get())
+    return aFeature;
+
+  aFeature = aSketch->addFeature(theBaseFeature->getKind());
+  // update fillet arc: make the arc correct for sure, so, it is not needed to process the "attribute updated"
+  // by arc; moreover, it may cause cyclicity in hte mechanism of updater
+  aFeature->data()->blockSendAttributeUpdated(true);
+
+  aFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue(
+                SketchPlugin_Arc::ARC_TYPE_CENTER_START_END());
+  fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
+                theBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
+  fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPointAttr);
+  fillAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPointAttr);
+  aFeature->data()->blockSendAttributeUpdated(false);
+  aFeature->execute();
+
+  return aFeature;
+}
+
 void SketchPlugin_ConstraintSplit::createConstraint(const std::string& theConstraintId,
                                                     const AttributePtr& theFirstAttribute,
                                                     const AttributePtr& theSecondAttribute)
index edbc4c68c04067be0696b76ebb4a5440860f68b4..b083ff2ad62cc8d1a39b044dba011044df7f6430 100755 (executable)
@@ -122,10 +122,18 @@ private:
   void fillAttribute(const AttributePtr& theModifiedAttribute,
                      const AttributePtr& theSourceAttribute);
 
+  /// Creates an arc feature filled by center of base feature and given points
+  /// \param theBaseFeature another arc feature
+  /// \param theFirstAttribute an attribute with coordinates for the start point
+  /// \param theSecondAttribute an attribute with coordinates for the end point
+  FeaturePtr createArcFeature(const FeaturePtr& theBaseFeature,
+                              const AttributePtr& theFirstPointAttr,
+                              const AttributePtr& theSecondPointAttr);
+
   /// Add feature coincidence constraint between given attributes
   /// \param theConstraintId a constraint index
   /// \param theFirstAttribute an attribute of further coincidence
-  /// \param theFirstAttribute an attribute of further coincidence
+  /// \param theSecondAttribute an attribute of further coincidence
   void createConstraint(const std::string& theConstraintId,
                         const std::shared_ptr<ModelAPI_Attribute>& theFirstAttribute,
                         const std::shared_ptr<ModelAPI_Attribute>& theSecondAttribute);
index d094a04c76358b305793a7db4f77000d7d30cd22..8f4c1fc1d51da44112084db347afaa6e52508403 100755 (executable)
@@ -899,9 +899,9 @@ bool SketchPlugin_SplitValidator::isValid(const AttributePtr& theAttribute,
     std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
     
     std::set<std::shared_ptr<GeomAPI_Pnt> > aPoints;
-
+    std::map<std::shared_ptr<GeomDataAPI_Point2D>, std::shared_ptr<GeomAPI_Pnt> > aPointToAttributes;
     ModelGeomAlgo_Point2D::getPointsInsideShape(anAttrShape, aRefAttributes, aC->pnt(),
-                                                aX->dir(), aDirY, aPoints);
+                                                aX->dir(), aDirY, aPoints, aPointToAttributes);
 
     int aCoincidentToFeature = (int)aPoints.size();
     if (aKind == SketchPlugin_Circle::ID())