From ced1c42d80f02b1efa749ecdf35e620dcca4d9cc Mon Sep 17 00:00:00 2001 From: nds Date: Mon, 29 Feb 2016 18:19:07 +0300 Subject: [PATCH] Coincidence to rectangle macro feature: 1. Get point of sub-feature to set coincidence. 2. Deactivate rectangle lines for better selection of axis/lines, otherwise the line's point is highlighted instead of desirable axis/line. --- .../ModuleBase_OperationFeature.cpp | 34 +++--- src/PartSet/PartSet_Tools.cpp | 102 +++++++++++------- src/PartSet/PartSet_Tools.h | 14 +++ src/PartSet/PartSet_WidgetPoint2d.cpp | 60 ++++++----- 4 files changed, 133 insertions(+), 77 deletions(-) diff --git a/src/ModuleBase/ModuleBase_OperationFeature.cpp b/src/ModuleBase/ModuleBase_OperationFeature.cpp index 6dcda35c2..cee58efb0 100755 --- a/src/ModuleBase/ModuleBase_OperationFeature.cpp +++ b/src/ModuleBase/ModuleBase_OperationFeature.cpp @@ -36,7 +36,7 @@ // the define to check the activated object as a sub-feature by argument of // the operation feature. E.g. rectangle feature(operation), line(in argument) to be not activated -//#define DEBUG_DO_NOT_ACTIVATE_SUB_FEATURE +#define DEBUG_DO_NOT_ACTIVATE_SUB_FEATURE #ifdef DEBUG_DO_NOT_ACTIVATE_SUB_FEATURE #include #endif @@ -195,23 +195,27 @@ bool ModuleBase_OperationFeature::hasObject(ObjectPtr theObj) const return true; } #ifdef DEBUG_DO_NOT_ACTIVATE_SUB_FEATURE - FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObj); - std::list anAttributes = aFeature->data()->attributes( - ModelAPI_AttributeRefList::typeId()); - std::list::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end(); - bool aFoundObject = false; - for (; anIt != aLast && !aFoundObject; anIt++) { - std::shared_ptr aCurSelList = - std::dynamic_pointer_cast(*anIt); - for (int i = 0, aNb = aCurSelList->size(); i < aNb && !aFoundObject; i++) { - ObjectPtr anObject = aCurSelList->object(i); - FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); - if (aFeature.get()) { - aFoundObject = anObjectFeature == aFeature; + if (aFeature->isMacro()) { + // macro feature may refers to sub-features, which also should be deactivated when the operation + // is active, e.g. rectangle'lines. + FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObj); + std::list anAttributes = aFeature->data()->attributes( + ModelAPI_AttributeRefList::typeId()); + std::list::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end(); + bool aFoundObject = false; + for (; anIt != aLast && !aFoundObject; anIt++) { + std::shared_ptr aCurSelList = + std::dynamic_pointer_cast(*anIt); + for (int i = 0, aNb = aCurSelList->size(); i < aNb && !aFoundObject; i++) { + ObjectPtr anObject = aCurSelList->object(i); + FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); + if (aFeature.get()) { + aFoundObject = anObjectFeature == aFeature; + } } } + return aFoundObject; } - return aFoundObject; #endif } return false; diff --git a/src/PartSet/PartSet_Tools.cpp b/src/PartSet/PartSet_Tools.cpp index a41dc94fd..8ee41ea47 100755 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@ -185,26 +185,6 @@ std::shared_ptr PartSet_Tools::document() return ModelAPI_Session::get()->moduleDocument(); } -/*std::shared_ptr PartSet_Tools::getFeaturePoint(FeaturePtr theFeature, - double theX, double theY) -{ - std::shared_ptr aClickedPoint = std::shared_ptr( - new GeomAPI_Pnt2d(theX, theY)); - std::list > anAttiributes = - theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list >::const_iterator anIt = anAttiributes.begin(), - aLast = anAttiributes.end(); - std::shared_ptr aFPoint; - for (; anIt != aLast && !aFPoint; anIt++) { - std::shared_ptr aCurPoint = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(*anIt); - if (aCurPoint && aCurPoint->pnt()->distance(aClickedPoint) < Precision::Confusion()) - aFPoint = aCurPoint; - } - - return aFPoint; -}*/ - void PartSet_Tools::setFeatureValue(FeaturePtr theFeature, double theValue, const std::string& theAttribute) { @@ -308,14 +288,73 @@ void PartSet_Tools::createConstraint(CompositeFeaturePtr theSketch, }*/ +std::shared_ptr PartSet_Tools::findFirstEqualPointInArgumentFeatures( + const FeaturePtr& theFeature, const std::shared_ptr& thePoint) +{ + std::shared_ptr aFeaturePoint; + + // may be feature is not updated yet, execute is not performed and references features + // are not created. Case: rectangle macro feature + ModuleBase_ModelWidget::updateObject(theFeature); + + std::list anAttributes = theFeature->data()->attributes( + ModelAPI_AttributeRefList::typeId()); + std::list::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end(); + for (; anIt != aLast && !aFeaturePoint.get(); anIt++) { + std::shared_ptr aCurSelList = + std::dynamic_pointer_cast(*anIt); + for (int i = 0, aNb = aCurSelList->size(); i < aNb && !aFeaturePoint.get(); i++) { + ObjectPtr anObject = aCurSelList->object(i); + FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); + if (aFeature.get()) + aFeaturePoint = PartSet_Tools::findFirstEqualPoint(aFeature, thePoint); + } + } + return aFeaturePoint; +} + +std::shared_ptr PartSet_Tools::findFirstEqualPoint(const FeaturePtr& theFeature, + const std::shared_ptr& thePoint) +{ + std::shared_ptr aFPoint; + + // find the given point in the feature attributes + std::list > anAttiributes = + theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list >::const_iterator anIt = anAttiributes.begin(), + aLast = anAttiributes.end(); + for (; anIt != aLast && !aFPoint; anIt++) { + std::shared_ptr aCurPoint = + std::dynamic_pointer_cast(*anIt); + if (aCurPoint && (aCurPoint->pnt()->distance(thePoint) < Precision::Confusion())) { + aFPoint = aCurPoint; + break; + } + } + return aFPoint; +} + void PartSet_Tools::setConstraints(CompositeFeaturePtr theSketch, FeaturePtr theFeature, const std::string& theAttribute, double theClickedX, double theClickedY) { + if (!theFeature.get()) + return; + + std::shared_ptr aClickedPoint = std::shared_ptr( + new GeomAPI_Pnt2d(theClickedX, theClickedY)); + // find a feature point by the selection mode - //std::shared_ptr aPoint = featurePoint(theMode); - std::shared_ptr aFeaturePoint = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(theFeature->data()->attribute(theAttribute)); + std::shared_ptr aFeaturePoint; + if (theFeature->isMacro()) { + // the macro feature will be removed after the operation is stopped, so we need to build + // coicidence to possible sub-features + aFeaturePoint = PartSet_Tools::findFirstEqualPointInArgumentFeatures(theFeature, aClickedPoint); + } + else { + aFeaturePoint = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(theFeature->data()->attribute(theAttribute)); + } if (!aFeaturePoint) return; @@ -328,25 +367,12 @@ void PartSet_Tools::setConstraints(CompositeFeaturePtr theSketch, FeaturePtr the std::list aFeatures = aRefList->list(); std::list::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end(); std::list > anAttiributes; - std::shared_ptr aClickedPoint = std::shared_ptr( - new GeomAPI_Pnt2d(theClickedX, theClickedY)); for (; anIt != aLast; anIt++) { FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); if (!aFeature.get() || theFeature == aFeature) continue; - // find the given point in the feature attributes - anAttiributes = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list >::const_iterator anIt = anAttiributes.begin(), - aLast = anAttiributes.end(); - std::shared_ptr aFPoint; - for (; anIt != aLast && !aFPoint; anIt++) { - std::shared_ptr aCurPoint = - std::dynamic_pointer_cast(*anIt); - if (aCurPoint && (aCurPoint->pnt()->distance(aClickedPoint) < Precision::Confusion())) { - aFPoint = aCurPoint; - break; - } - } + std::shared_ptr aFPoint = PartSet_Tools::findFirstEqualPoint(aFeature, + aClickedPoint); if (aFPoint) PartSet_Tools::createConstraint(theSketch, aFPoint, aFeaturePoint); } diff --git a/src/PartSet/PartSet_Tools.h b/src/PartSet/PartSet_Tools.h index 1b35d9068..752951dbd 100755 --- a/src/PartSet/PartSet_Tools.h +++ b/src/PartSet/PartSet_Tools.h @@ -111,6 +111,20 @@ public: std::shared_ptr thePoint1, std::shared_ptr thePoint2); + /// Finds in the feature's sub-features first Point2D attribute with the given point coordinates + /// \param theFeature a feature with sub-feature attributes + /// \param thePoint a point to provided searched coordinates + /// \return found point or null + static std::shared_ptr PartSet_Tools::findFirstEqualPointInArgumentFeatures( + const FeaturePtr& theFeature, const std::shared_ptr& thePoint); + + /// Finds in the feature first Point2D attribute with the given point coordinates + /// \param theFeature a feature with point attributes + /// \param thePoint a point to provided searched coordinates + /// \return found point or null + static std::shared_ptr findFirstEqualPoint(const FeaturePtr& theFeature, + const std::shared_ptr& thePoint); + /// Creates constrains of the current /// \param theSketch a sketch feature /// \param theFeature a source feature diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index 50ac3e3ee..03cd49c32 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -386,16 +386,33 @@ bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView, void PartSet_WidgetPoint2D::setConstraintWith(const ObjectPtr& theObject) { + std::shared_ptr aFeaturePoint; + if (feature()->isMacro()) { + AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); + std::shared_ptr anAttrPoint = + std::dynamic_pointer_cast(aThisAttr); + if (anAttrPoint.get()) { + // the macro feature will be removed after the operation is stopped, so we need to build + // coicidence to possible sub-features + aFeaturePoint = PartSet_Tools::findFirstEqualPointInArgumentFeatures(feature(), + anAttrPoint->pnt()); + } + } + else { + AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); + aFeaturePoint = std::dynamic_pointer_cast(aThisAttr); + } + if (!aFeaturePoint.get()) + return; + // Create point-edge coincedence FeaturePtr aFeature = mySketch->addFeature(SketchPlugin_ConstraintCoincidence::ID()); std::shared_ptr aData = aFeature->data(); std::shared_ptr aRef1 = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); - std::shared_ptr aThisPoint = - std::dynamic_pointer_cast(aThisAttr); - aRef1->setAttr(aThisPoint); + + aRef1->setAttr(aFeaturePoint); std::shared_ptr aRef2 = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B())); @@ -410,8 +427,6 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous if (theEvent->button() != Qt::LeftButton) return; - bool isCoincidenceEnabled = MyFeaturesForCoincedence.contains(myFeature->getKind().c_str()); - ModuleBase_ISelection* aSelection = myWorkshop->selection(); Handle(V3d_View) aView = theWnd->v3dView(); // TODO: This fragment doesn't work because bug in OCC Viewer. It can be used after fixing. @@ -429,13 +444,11 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous aSPFeature = std::dynamic_pointer_cast(aSelectedFeature); if ((!aSPFeature && !aShape.IsNull()) || (aSPFeature.get() && aSPFeature->isExternal())) { - ResultPtr aFixedObject; - if (isCoincidenceEnabled) { - anExternal = true; - aFixedObject = PartSet_Tools::findFixedObjectByExternal(aShape, aObject, mySketch); - if (!aFixedObject.get()) - aFixedObject = PartSet_Tools::createFixedObjectByExternal(aShape, aObject, mySketch); - } + ResultPtr aFixedObject; + anExternal = true; + aFixedObject = PartSet_Tools::findFixedObjectByExternal(aShape, aObject, mySketch); + if (!aFixedObject.get()) + aFixedObject = PartSet_Tools::createFixedObjectByExternal(aShape, aObject, mySketch); 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 @@ -487,20 +500,19 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous bool isAuxiliaryFeature = false; if (getPoint2d(aView, aShape, aX, aY)) { setPoint(aX, aY); + feature()->execute(); PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); } else if (aShape.ShapeType() == TopAbs_EDGE) { - if (isCoincidenceEnabled) { - setConstraintWith(aObject); - setValueState(Stored); // in case of edge selection, Apply state should also be updated - - FeaturePtr anObjectFeature = ModelAPI_Feature::feature(aObject); - std::string anAuxiliaryAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID(); - AttributeBooleanPtr anAuxiliaryAttr = std::dynamic_pointer_cast( - anObjectFeature->data()->attribute(anAuxiliaryAttribute)); - if (anAuxiliaryAttr.get()) - isAuxiliaryFeature = anAuxiliaryAttr->value(); - } + setConstraintWith(aObject); + setValueState(Stored); // in case of edge selection, Apply state should also be updated + + FeaturePtr anObjectFeature = ModelAPI_Feature::feature(aObject); + std::string anAuxiliaryAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID(); + AttributeBooleanPtr anAuxiliaryAttr = std::dynamic_pointer_cast( + anObjectFeature->data()->attribute(anAuxiliaryAttribute)); + if (anAuxiliaryAttr.get()) + isAuxiliaryFeature = anAuxiliaryAttr->value(); } // 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 -- 2.39.2