From 15111f4cbb13a94699c54f152ce308820e8f24dc Mon Sep 17 00:00:00 2001 From: nds Date: Thu, 28 Jul 2016 19:54:13 +0300 Subject: [PATCH] Issue #1664: In the Sketcher, add the function Split a segment: 1. cash for attribute point 2d to projected point to avoid repeated geometrical calculations 2. restart of split operation: highlight sub-shapes --- src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp | 8 +- src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h | 5 +- src/ModuleBase/ModuleBase_IModule.h | 5 + src/PartSet/PartSet_Module.cpp | 7 +- src/PartSet/PartSet_Module.h | 5 + src/PartSet/PartSet_OperationPrs.cpp | 10 +- src/PartSet/PartSet_SketcherMgr.cpp | 2 +- src/PartSet/PartSet_SketcherReetntrantMgr.cpp | 24 ++-- .../PartSet_WidgetSubShapeSelector.cpp | 130 +++++------------- src/PartSet/PartSet_WidgetSubShapeSelector.h | 11 +- .../SketchPlugin_ConstraintSplit.cpp | 54 +++++--- .../SketchPlugin_ConstraintSplit.h | 10 +- src/SketchPlugin/SketchPlugin_Validators.cpp | 4 +- 13 files changed, 134 insertions(+), 141 deletions(-) diff --git a/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp b/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp index 5621684a4..f27954b10 100755 --- a/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp +++ b/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp @@ -120,7 +120,9 @@ namespace ModelGeomAlgo_Point2D { const std::shared_ptr& theOrigin, const std::shared_ptr& theDirX, const std::shared_ptr& theDirY, - std::set >& thePoints) + std::set >& thePoints, + std::map, + std::shared_ptr >& theAttributeToPoint) { std::set >::const_iterator anIt = theAttributes.begin(), aLast = theAttributes.end(); @@ -129,8 +131,10 @@ namespace ModelGeomAlgo_Point2D { std::shared_ptr aPnt2d = anAttribute->pnt(); std::shared_ptr aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY); std::shared_ptr aProjectedPoint; - if (isPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) + if (isPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) { thePoints.insert(aProjectedPoint); + theAttributeToPoint[anAttribute] = aProjectedPoint; + } } } diff --git a/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h b/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h index be1521bdc..826dde4a6 100755 --- a/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h +++ b/src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h @@ -21,6 +21,7 @@ class GeomDataAPI_Point2D; #include #include #include +#include namespace ModelGeomAlgo_Point2D { @@ -68,7 +69,9 @@ namespace ModelGeomAlgo_Point2D { const std::shared_ptr& theOrigin, const std::shared_ptr& theDirX, const std::shared_ptr& theDirY, - std::set >& thePoints); + std::set >& thePoints, + std::map, + std::shared_ptr >& theAttributeToPoint); /// Finds projected point to the given shape line /// \param theBaseShape a shape of check diff --git a/src/ModuleBase/ModuleBase_IModule.h b/src/ModuleBase/ModuleBase_IModule.h index e0937f09e..75cd6e62a 100755 --- a/src/ModuleBase/ModuleBase_IModule.h +++ b/src/ModuleBase/ModuleBase_IModule.h @@ -201,6 +201,11 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject /// \param theTypes a selection modes to be extended virtual void customSubShapesSelectionModes(QIntList& theTypes) {} + /// 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 { return false; }; + /// Activate custom presentation for the object. Default realization is empty. /// \param theFeature a feature instance /// \param theFlag a flag of level of customization, which means that only part of sub-elements diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 8c818d861..101dfc15a 100755 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -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) { diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index 014790aa4..64ae1c099 100755 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -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 diff --git a/src/PartSet/PartSet_OperationPrs.cpp b/src/PartSet/PartSet_OperationPrs.cpp index d5e812723..529f0371d 100755 --- a/src/PartSet/PartSet_OperationPrs.cpp +++ b/src/PartSet/PartSet_OperationPrs.cpp @@ -349,13 +349,9 @@ void PartSet_OperationPrs::getHighlightedShapes(ModuleBase_IWorkshop* theWorksho theObjectShapes.clear(); QList 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 aShapes; QList::const_iterator anIIt = aValues.begin(), diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index ce2b209ce..a46d07f9d 100755 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -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(anActiveWidget); if (aProcessor) aProcessor->mouseMoved(theWnd, theEvent); diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp index fb8ce49e7..52972494f 100755 --- a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp +++ b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp @@ -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(anActiveWidget); + if (aProcessor) + aProcessor->mouseMoved(theWnd, theEvent); + } } } return aProcessed; diff --git a/src/PartSet/PartSet_WidgetSubShapeSelector.cpp b/src/PartSet/PartSet_WidgetSubShapeSelector.cpp index 46c20acea..35480469d 100755 --- a/src/PartSet/PartSet_WidgetSubShapeSelector.cpp +++ b/src/PartSet/PartSet_WidgetSubShapeSelector.cpp @@ -86,7 +86,10 @@ void PartSet_WidgetSubShapeSelector::mouseMoved(ModuleBase_IViewWindow* theWindo const std::set& aShapes = myCashedShapes[anObject]; if (!aShapes.empty()) { gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); - std::shared_ptr 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 aPoint = PartSet_Tools::convertTo3D(aX, anY, mySketch); std::set::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>& 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 anEdge(new GeomAPI_Edge(aBaseShape)); std::shared_ptr aFirstPnt = anEdge->firstPoint(); std::shared_ptr aLastPnt = anEdge->lastPoint(); - std::shared_ptr aFirstPnt2D = PartSet_Tools::convertTo2D(mySketch, aFirstPnt); - std::shared_ptr aLastPnt2D = PartSet_Tools::convertTo2D(mySketch, aLastPnt); - + std::shared_ptr aFirstPointAttr, aLastPointAttr; /// find the points in feature attributes FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject); std::list a2DPointAttributes = aBaseFeature->data()->attributes( GeomDataAPI_Point2D::typeId()); std::list::const_iterator anIt = a2DPointAttributes.begin(), aLast = a2DPointAttributes.end(); - std::shared_ptr aFirstPointAttr, aLastPointAttr; for (; anIt != aLast; anIt++) { std::shared_ptr anAttributePoint = std::dynamic_pointer_cast(*anIt); - if (aFirstPnt2D->isEqual(anAttributePoint->pnt())) + std::shared_ptr aPoint2D = anAttributePoint->pnt(); + std::shared_ptr 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 > aRefAttributes = myCashedReferences[aBaseObject]; - std::set >::const_iterator aRefIt = aRefAttributes.begin(), - aRefLast = aRefAttributes.end(); - for (; aRefIt != aRefLast; aRefIt++) { - std::shared_ptr 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 anAttribute = aRIt->first; + std::shared_ptr 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 > aShapes; + std::map, std::shared_ptr > aPointToAttributes; std::set > aRefAttributes; - // current feature FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); std::set anEdgeShapes; @@ -246,73 +248,11 @@ void PartSet_WidgetSubShapeSelector::fillObjectShapes(const ObjectPtr& theObject std::shared_ptr aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); std::set > 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(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 aSPFeature = - std::dynamic_pointer_cast(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); -} -*/ diff --git a/src/PartSet/PartSet_WidgetSubShapeSelector.h b/src/PartSet/PartSet_WidgetSubShapeSelector.h index b93f4d074..b20cf882d 100644 --- a/src/PartSet/PartSet_WidgetSubShapeSelector.h +++ b/src/PartSet/PartSet_WidgetSubShapeSelector.h @@ -9,12 +9,11 @@ #define PartSet_WidgetSubShapeSelector_H #include "PartSet.h" +#include "PartSet_MouseProcessor.h" #include -#include #include -#include #include @@ -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 myCurrentSubShape; std::map > myCashedShapes; - std::map > myCashedReferences; + + typedef std::map, + std::shared_ptr > PntToAttributesMap; + std::map myCashedReferences; /// Pointer to a sketch CompositeFeaturePtr mySketch; diff --git a/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp b/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp index 1b59de535..a98724cfa 100755 --- a/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintSplit.cpp @@ -18,6 +18,9 @@ //#include #include +#include +#include + #include #include #include @@ -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) diff --git a/src/SketchPlugin/SketchPlugin_ConstraintSplit.h b/src/SketchPlugin/SketchPlugin_ConstraintSplit.h index edbc4c68c..b083ff2ad 100755 --- a/src/SketchPlugin/SketchPlugin_ConstraintSplit.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintSplit.h @@ -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& theFirstAttribute, const std::shared_ptr& theSecondAttribute); diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index d094a04c7..8f4c1fc1d 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -899,9 +899,9 @@ bool SketchPlugin_SplitValidator::isValid(const AttributePtr& theAttribute, std::shared_ptr aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); std::set > aPoints; - + std::map, std::shared_ptr > 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()) -- 2.39.2