From 45e813af3609dbc2551302cc2f88cb6932a27830 Mon Sep 17 00:00:00 2001 From: nds Date: Tue, 8 Sep 2015 10:47:47 +0300 Subject: [PATCH] 1. Sketch solver invalid state: do not restart the create operation; 2. Line creation: several click in the same point: do not deactivate point widget if the feature already contains this value. [Scenario: start sketch, start line creation, click in the same place; create contour, create other sketch, click in the point on the 1st sketch to create a line. It is not possible] 3. Correction to call customizeCurrentObject only when some is displayed/erased. If this check is absent, there can be a crash. Scenario of the crash is: Create contour, make two lines paralle, make them perpendicular, Undo. Reason: created message of Sketch comes earlies than redisplay of perpendicular. SketchPrs_Perpendicular: getResult -> crash. --- src/PartSet/PartSet_Module.cpp | 4 +- src/PartSet/PartSet_SketcherMgr.cpp | 21 +++- src/PartSet/PartSet_SketcherMgr.h | 4 + src/PartSet/PartSet_WidgetPoint2d.cpp | 153 +++++++++++++++----------- src/PartSet/PartSet_WidgetPoint2d.h | 7 ++ src/XGUI/XGUI_WorkshopListener.cpp | 12 +- 6 files changed, 123 insertions(+), 78 deletions(-) diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 6304bd232..26858896b 100755 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -263,8 +263,8 @@ void PartSet_Module::onOperationCommitted(ModuleBase_Operation* theOperation) myRestartingMode == RM_EmptyFeatureUsed)) { myLastOperationId = aFOperation->id(); myLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature() : FeaturePtr(); - - launchOperation(myLastOperationId); + if (!sketchMgr()->sketchSolverError()) + launchOperation(myLastOperationId); } breakOperationSequence(); } diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index c893f21cf..b4cf246ea 100644 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -11,9 +11,6 @@ #include "PartSet_Tools.h" #include "PartSet_WidgetSketchLabel.h" -#include -#include - #include #include #include @@ -25,14 +22,16 @@ #include #include +#include +#include #include #include #include +#include #include #include -#include -#include #include +#include #include @@ -70,6 +69,7 @@ #include #include +#include #include #include @@ -667,6 +667,17 @@ void PartSet_SketcherMgr::launchEditing() } } +bool PartSet_SketcherMgr::sketchSolverError() +{ + bool anError = false; + CompositeFeaturePtr aSketch = activeSketch(); + if (aSketch.get()) { + AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR()); + anError = !aAttributeString->value().empty(); + } + return anError; +} + const QStringList& PartSet_SketcherMgr::sketchOperationIdList() { diff --git a/src/PartSet/PartSet_SketcherMgr.h b/src/PartSet/PartSet_SketcherMgr.h index cadfd32e5..477fdcb30 100644 --- a/src/PartSet/PartSet_SketcherMgr.h +++ b/src/PartSet/PartSet_SketcherMgr.h @@ -170,6 +170,10 @@ public: /// Restores previously saved selection state void restoreSelection(); + /// Return error state of the sketch feature, true if the error has happened + /// \return boolean value + bool sketchSolverError(); + /// Returns list of strings which contains id's of sketch operations static const QStringList& sketchOperationIdList(); diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index 31a972e2f..1ffc4f4d2 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -311,89 +311,86 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous TopoDS_Shape aShape = aShapes.First(); ObjectPtr aObject = aObjects.front(); FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aObject); + bool anExternal = false; if (aSelectedFeature.get() != NULL) { std::shared_ptr aSPFeature = std::dynamic_pointer_cast(aSelectedFeature); if ((!aSPFeature) && (!aShape.IsNull())) { + anExternal = true; ResultPtr aFixedObject = PartSet_Tools::findFixedObjectByExternal(aShape, aObject, mySketch); if (!aFixedObject.get()) aObject = PartSet_Tools::createFixedObjectByExternal(aShape, aObject, mySketch); - setConstraintWith(aObject); - emit vertexSelected(); - emit focusOutWidget(this); - return; + + double aX, aY; + if (getPoint2d(aView, aShape, aX, aY) && isFeatureContainsPoint(myFeature, aX, aY)) { + // do not create a constraint to the point, which already used by the feature + // if the feature contains the point, focus is not switched + setPoint(aX, aY); + } + else { + setConstraintWith(aObject); + emit vertexSelected(); + emit focusOutWidget(this); + } } } - double aX, aY; - bool isProcessed = false; - if (getPoint2d(aView, aShape, aX, aY)) { - bool aFeatureContainsPoint = false; - - std::shared_ptr aPnt2d = - std::shared_ptr(new GeomAPI_Pnt2d(aX, aY)); - std::list anAttributes = - myFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list::iterator anIter = anAttributes.begin(); - for(; anIter != anAttributes.end(); anIter++) { - AttributePoint2DPtr aPoint2DAttribute = - std::dynamic_pointer_cast(*anIter); - if (aPoint2DAttribute.get()) { - aFeatureContainsPoint = aPoint2DAttribute->pnt()->isEqual(aPnt2d); - } + if (!anExternal) { + double aX, aY; + bool isProcessed = false; + if (getPoint2d(aView, aShape, aX, aY) && isFeatureContainsPoint(myFeature, aX, aY)) { + // when the point is selected, the coordinates of the point should be set into the attribute + // if the feature contains the point, focus is not switched + setPoint(aX, aY); } - // when the point is selected, the coordinates of the point should be set into the attribute - setPoint(aX, aY); - // do not set a coincidence constraint in the attribute if the feature contains a point - // with the same coordinates. It is important for line creation in order to do not set - // the same constraints for the same points, oterwise the result line has zero length. - if (aFeatureContainsPoint) - return; else { - PartSet_Tools::setConstraints(mySketch, feature(), attributeID(),aX, aY); + // do not set a coincidence constraint in the attribute if the feature contains a point + // with the same coordinates. It is important for line creation in order to do not set + // the same constraints for the same points, oterwise the result line has zero length. + if (getPoint2d(aView, aShape, aX, aY)) + PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); + else if (aShape.ShapeType() == TopAbs_EDGE) + setConstraintWith(aObject); + + // it is important to perform updateObject() in order to the current value is + // processed by Sketch Solver. Test case: line is created from a previous point + // to some distance, but in the area of the highlighting of the point. Constraint + // coincidence is created, after the solver is performed, the distance between the + // points of the line becomes less than the tolerance. Validator of the line returns + // false, the line will be aborted, but sketch stays valid. + updateObject(feature()); + emit vertexSelected(); + emit focusOutWidget(this); } - isProcessed = true; - } else if (aShape.ShapeType() == TopAbs_EDGE) { - setConstraintWith(aObject); - isProcessed = true; - } - if (isProcessed) { - // it is important to perform updateObject() in order to the current value is - // processed by Sketch Solver. Test case: line is created from a previous point - // to some distance, but in the area of the highlighting of the point. Constraint - // coincidence is created, after the solver is performed, the distance between the - // points of the line becomes less than the tolerance. Validator of the line returns - // false, the line will be aborted, but sketch stays valid. - updateObject(feature()); - emit vertexSelected(); - emit focusOutWidget(this); - return; } } // End of Bug dependent fragment + else { + // A case when point is taken from mouse event + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView()); + double aX, anY; + PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, anY); - // A case when point is taken from mouse event - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView()); - double aX, anY; - PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, anY); - if (!setPoint(aX, anY)) - return; + // if the feature contains the point, focus is not switched + if (!setPoint(aX, anY) || isFeatureContainsPoint(myFeature, aX, anY)) + return; - /// Start alternative code - //std::shared_ptr aFeaturePoint = std::dynamic_pointer_cast< - // GeomDataAPI_Point2D>(feature()->data()->attribute(attributeID())); - //QList aIgnore; - //aIgnore.append(feature()); - - //double aTolerance = aView->Convert(7); - //std::shared_ptr aAttrPnt = - // PartSet_Tools::findAttributePoint(mySketch, aX, anY, aTolerance, aIgnore); - //if (aAttrPnt.get() != NULL) { - // aFeaturePoint->setValue(aAttrPnt->pnt()); - // PartSet_Tools::createConstraint(mySketch, aAttrPnt, aFeaturePoint); - // emit vertexSelected(); - //} - /// End alternative code - emit focusOutWidget(this); + /// Start alternative code + //std::shared_ptr aFeaturePoint = std::dynamic_pointer_cast< + // GeomDataAPI_Point2D>(feature()->data()->attribute(attributeID())); + //QList aIgnore; + //aIgnore.append(feature()); + + //double aTolerance = aView->Convert(7); + //std::shared_ptr aAttrPnt = + // PartSet_Tools::findAttributePoint(mySketch, aX, anY, aTolerance, aIgnore); + //if (aAttrPnt.get() != NULL) { + // aFeaturePoint->setValue(aAttrPnt->pnt()); + // PartSet_Tools::createConstraint(mySketch, aAttrPnt, aFeaturePoint); + // emit vertexSelected(); + //} + /// End alternative code + emit focusOutWidget(this); + } } @@ -419,6 +416,30 @@ double PartSet_WidgetPoint2D::y() const return myYSpin->value(); } + +bool PartSet_WidgetPoint2D::isFeatureContainsPoint(const FeaturePtr& theFeature, + double theX, double theY) +{ + bool aPointIsFound = false; + AttributePtr aWidgetAttribute = myFeature->attribute(attributeID()); + + std::shared_ptr aPnt2d = + std::shared_ptr(new GeomAPI_Pnt2d(theX, theY)); + std::list anAttributes = + myFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list::iterator anIter = anAttributes.begin(); + for(; anIter != anAttributes.end(); anIter++) { + AttributePoint2DPtr aPoint2DAttribute = + std::dynamic_pointer_cast(*anIter); + if (aPoint2DAttribute == aWidgetAttribute) + continue; + if (aPoint2DAttribute.get()) { + aPointIsFound = aPoint2DAttribute->pnt()->isEqual(aPnt2d); + } + } + return aPointIsFound; +} + void PartSet_WidgetPoint2D::onValuesChanged() { myLockApplyMgr->valuesChanged(); diff --git a/src/PartSet/PartSet_WidgetPoint2d.h b/src/PartSet/PartSet_WidgetPoint2d.h index d8b235c9c..a07107f66 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.h +++ b/src/PartSet/PartSet_WidgetPoint2d.h @@ -112,6 +112,13 @@ protected: /// The methiod called when widget is activated virtual void activateCustom(); + /// Returns true if the feature contains Point2D attribute with the same coordinates + /// The attribute of the widget is not processed. + /// \param theX the X coordinate + /// \param theY the Y coordinate + /// \return boolean result + bool isFeatureContainsPoint(const FeaturePtr& theFeature, double theX, double theY); + private slots: /// Process value changed event void onValuesChanged(); diff --git a/src/XGUI/XGUI_WorkshopListener.cpp b/src/XGUI/XGUI_WorkshopListener.cpp index 6e4879d57..82620e635 100755 --- a/src/XGUI/XGUI_WorkshopListener.cpp +++ b/src/XGUI/XGUI_WorkshopListener.cpp @@ -324,9 +324,10 @@ void XGUI_WorkshopListener::onFeatureRedisplayMsg(const std::shared_ptrupdateViewer(); + if (aRedisplayed) { + customizeCurrentObject(); + aDisplayer->updateViewer(); + } } //****************************************************** void XGUI_WorkshopListener::onFeatureCreatedMsg(const std::shared_ptr& theMsg) @@ -374,12 +375,13 @@ void XGUI_WorkshopListener::onFeatureCreatedMsg(const std::shared_ptrsetDisplayed(false); } } - aDisplayed = customizeCurrentObject() || aDisplayed; //if (myObjectBrowser) // myObjectBrowser->processEvent(theMsg); - if (aDisplayed) + if (aDisplayed) { + customizeCurrentObject(); workshop()->displayer()->updateViewer(); + } //if (aHasPart) { // TODO: Avoid activate last part on loading of document // activateLastPart(); //} -- 2.39.2