From 9894d615f4020072dfa02f374d57c7711be22970 Mon Sep 17 00:00:00 2001 From: nds Date: Tue, 16 May 2017 12:29:41 +0300 Subject: [PATCH] Issue #2155 Trim removes multi-rotation constraint, undo leads to wrong DOF 1. remove multi constraints only if references is to selected objects attribute 2. set tangency constraint to the nearest geometry placed feature. --- src/PartSet/PartSet_MenuMgr.cpp | 14 ++- src/PartSet/PartSet_Tools.cpp | 12 +- src/PartSet/PartSet_Tools.h | 2 +- src/PartSet/PartSet_Validators.cpp | 7 +- src/PartSet/PartSet_WidgetPoint2d.cpp | 7 +- src/SketchPlugin/SketchPlugin_Trim.cpp | 137 ++++++++++------------ src/SketchPlugin/SketchPlugin_Trim.h | 14 +-- src/SketcherPrs/SketcherPrs_SymbolPrs.cpp | 2 +- 8 files changed, 93 insertions(+), 102 deletions(-) diff --git a/src/PartSet/PartSet_MenuMgr.cpp b/src/PartSet/PartSet_MenuMgr.cpp index c65d42515..7dfa91111 100644 --- a/src/PartSet/PartSet_MenuMgr.cpp +++ b/src/PartSet/PartSet_MenuMgr.cpp @@ -160,10 +160,13 @@ bool PartSet_MenuMgr::addViewerMenu(const QMap& theStdActions if (aCoincident.get() != NULL) { QList aCoins; mySelectedFeature = aCoincident; + QList anIsAttributes; PartSet_Tools::findCoincidences(mySelectedFeature, myCoinsideLines, aCoins, - SketchPlugin_ConstraintCoincidence::ENTITY_A()); + SketchPlugin_ConstraintCoincidence::ENTITY_A(), + anIsAttributes); PartSet_Tools::findCoincidences(mySelectedFeature, myCoinsideLines, aCoins, - SketchPlugin_ConstraintCoincidence::ENTITY_B()); + SketchPlugin_ConstraintCoincidence::ENTITY_B(), + anIsAttributes); if (myCoinsideLines.size() > 0) { aIsDetach = true; QMenu* aSubMenu = new QMenu(tr("Detach"), theParent); @@ -171,7 +174,12 @@ bool PartSet_MenuMgr::addViewerMenu(const QMap& theStdActions QAction* aAction; int i = 0; foreach (FeaturePtr aCoins, myCoinsideLines) { - aAction = aSubMenu->addAction(aCoins->data()->name().c_str()); + QString anItemText = aCoins->data()->name().c_str(); +#ifdef _DEBUG + if (anIsAttributes[i]) + anItemText += " [attribute]"; +#endif + aAction = aSubMenu->addAction(anItemText); aAction->setData(QVariant(i)); i++; } diff --git a/src/PartSet/PartSet_Tools.cpp b/src/PartSet/PartSet_Tools.cpp index 6550c7767..51a24fa71 100755 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@ -749,7 +749,7 @@ FeaturePtr PartSet_Tools::findFirstCoincidence(const FeaturePtr& theFeature, void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList& theList, QList& theCoincidencies, - std::string theAttr) + std::string theAttr, QList& theIsAttributes) { std::shared_ptr aOrig = getCoincedencePoint(theStartCoin); if (aOrig.get() == NULL) @@ -764,6 +764,7 @@ void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList& if (!theList.contains(aFeature)) { theList.append(aFeature); theCoincidencies.append(theStartCoin); + theIsAttributes.append(true); // point attribute on a feature const std::set& aRefsList = aFeature->data()->refsToMe(); std::set::const_iterator aIt; for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { @@ -774,9 +775,9 @@ void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList& std::shared_ptr aPnt = getCoincedencePoint(aConstrFeature); if (aPnt.get() && aOrig->isEqual(aPnt)) { findCoincidences(aConstrFeature, theList, theCoincidencies, - SketchPlugin_ConstraintCoincidence::ENTITY_A()); + SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes); findCoincidences(aConstrFeature, theList, theCoincidencies, - SketchPlugin_ConstraintCoincidence::ENTITY_B()); + SketchPlugin_ConstraintCoincidence::ENTITY_B(), theIsAttributes); } } } @@ -790,6 +791,7 @@ void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList& if (!theList.contains(aFeature)) theList.append(aFeature); theCoincidencies.append(theStartCoin); + theIsAttributes.append(false); // point attribute on a feature const std::set& aRefsList = aResult->data()->refsToMe(); std::set::const_iterator aIt; @@ -801,9 +803,9 @@ void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList& std::shared_ptr aPnt = getCoincedencePoint(aConstrFeature); if (aPnt.get() && aOrig->isEqual(aPnt)) { findCoincidences(aConstrFeature, theList, theCoincidencies, - SketchPlugin_ConstraintCoincidence::ENTITY_A()); + SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes); findCoincidences(aConstrFeature, theList, theCoincidencies, - SketchPlugin_ConstraintCoincidence::ENTITY_B()); + SketchPlugin_ConstraintCoincidence::ENTITY_B(), theIsAttributes); } } } diff --git a/src/PartSet/PartSet_Tools.h b/src/PartSet/PartSet_Tools.h index 1429f9d29..58c928e29 100755 --- a/src/PartSet/PartSet_Tools.h +++ b/src/PartSet/PartSet_Tools.h @@ -247,7 +247,7 @@ public: */ static void findCoincidences(FeaturePtr theStartCoin, QList& theList, QList& theCoincidencies, - std::string theAttr); + std::string theAttr, QList& theIsAttributes); /** * Returns point of a coincedence diff --git a/src/PartSet/PartSet_Validators.cpp b/src/PartSet/PartSet_Validators.cpp index ec18af32f..55e2eee29 100755 --- a/src/PartSet/PartSet_Validators.cpp +++ b/src/PartSet/PartSet_Validators.cpp @@ -639,10 +639,13 @@ bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute, AttributePtr aAR = aRAttr->attr(); if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc aCoinList.insert(aConstrFeature); + QList anIsAttributes; PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins, - SketchPlugin_ConstraintCoincidence::ENTITY_A()); + SketchPlugin_ConstraintCoincidence::ENTITY_A(), + anIsAttributes); PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins, - SketchPlugin_ConstraintCoincidence::ENTITY_B()); + SketchPlugin_ConstraintCoincidence::ENTITY_B(), + anIsAttributes); } } // if there is no coincidence then it is not valid diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index 56b1e9852..7ecf8dbf8 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -837,10 +837,13 @@ bool PartSet_WidgetPoint2D::isOrphanPoint(const FeaturePtr& theFeature, if (aCoincidence.get()) { QList aCoinsideLines; QList aCoins; + QList anIsAttributes; PartSet_Tools::findCoincidences(aCoincidence, aCoinsideLines, aCoins, - SketchPlugin_ConstraintCoincidence::ENTITY_A()); + SketchPlugin_ConstraintCoincidence::ENTITY_A(), + anIsAttributes); PartSet_Tools::findCoincidences(aCoincidence, aCoinsideLines, aCoins, - SketchPlugin_ConstraintCoincidence::ENTITY_B()); + SketchPlugin_ConstraintCoincidence::ENTITY_B(), + anIsAttributes); QList::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end(); for (; anIt != aLast && anOrphanPoint; anIt++) { diff --git a/src/SketchPlugin/SketchPlugin_Trim.cpp b/src/SketchPlugin/SketchPlugin_Trim.cpp index 747351bb3..53a4ad23c 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.cpp +++ b/src/SketchPlugin/SketchPlugin_Trim.cpp @@ -231,10 +231,10 @@ void SketchPlugin_Trim::execute() std::shared_ptr aStartShapePoint2d = convertPoint(aStartShapePoint); std::shared_ptr aLastShapePoint2d = convertPoint(aLastShapePoint); - + /// find features that should be deleted (e.g. Middle Point) or updated (e.g. Length) std::set aFeaturesToDelete, aFeaturesToUpdate; getConstraints(aFeaturesToDelete, aFeaturesToUpdate); - + // find references(attributes and features) to the base feature std::map > aBaseRefAttributes; std::list aRefsToFeature; getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature); @@ -280,12 +280,6 @@ void SketchPlugin_Trim::execute() std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl; std::cout << "---- getRefAttributes:end ----" << std::endl; #endif - // coincidence to result points - // find coincidences to the base object, it should be used when attribute is found - // in myObjectToPoints - //std::map aCoincidencesToBaseFeature; - //getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature); - std::set aFurtherCoincidences; std::set> aModifiedAttributes; const std::string& aKind = aBaseFeature->getKind(); @@ -370,12 +364,13 @@ void SketchPlugin_Trim::execute() anIt != aLast; anIt++) { AttributePtr anAttribute = *anIt; - //if (replaceCoincidenceAttribute(anAttribute, aModifiedAttributes)) - // continue; - if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences)) continue; + // move tangency constraint to the nearest feature if possible + if (aNewFeature.get() && moveTangency(anAttribute, aNewFeature)) + continue; + if (aReplacingResult.get()) { AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(anAttribute); @@ -552,34 +547,55 @@ bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribu return aFoundPoint; } -bool SketchPlugin_Trim::replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute, - const std::set>& theModifiedAttributes) +bool SketchPlugin_Trim::moveTangency(const AttributePtr& theAttribute, + const FeaturePtr& theFeature) { - FeaturePtr aCoincidenceFeature = ModelAPI_Feature::feature(theCoincidenceAttribute->owner()); - if (aCoincidenceFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) + FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); + if (aFeature->getKind() != SketchPlugin_ConstraintTangent::ID()) return false; - AttributeRefAttrPtr aCAttrA = std::dynamic_pointer_cast( - aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributeRefAttrPtr aCAttrB = std::dynamic_pointer_cast( - aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); - AttributePtr aCAttrRefA = aCAttrA->attr(); - AttributePtr aCAttrRefB = aCAttrB->attr(); - - bool isProcessed = false; - for (std::set>::const_iterator - anIt = theModifiedAttributes.begin(); anIt != theModifiedAttributes.end(); anIt++) { - AttributePtr anAttributeBefore = anIt->first; - if (anAttributeBefore == aCAttrRefA) { - aCAttrA->setAttr(anIt->second); - isProcessed = true; - } - if (anAttributeBefore == aCAttrRefB) { - aCAttrB->setAttr(anIt->second); - isProcessed = true; + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + theAttribute); + if (!aRefAttr.get()) + return false; + + // get shape of tangent object to the current + std::string aTangentAttr = SketchPlugin_Constraint::ENTITY_A(); + if (aRefAttr->id() == SketchPlugin_Constraint::ENTITY_A()) + aTangentAttr = SketchPlugin_Constraint::ENTITY_B(); + AttributeRefAttrPtr aTangentRefAttr = std::dynamic_pointer_cast( + aFeature->attribute(aTangentAttr)); + FeaturePtr aTangentFeature = ModelAPI_Feature::feature(aTangentRefAttr->object()); + + // get shape of the feature of the attribute + FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(aRefAttr->object()); + anAttributeFeature->execute(); // the modified value should be applyed to recompute shape + PointToRefsMap aPointToAttributeOrObject; + std::list aFeatures; + aFeatures.push_back(anAttributeFeature); + ModelGeomAlgo_Point2D::getPointsIntersectedShape(aTangentFeature, aFeatures, + aPointToAttributeOrObject); + if (!aPointToAttributeOrObject.empty()) + return true; // the attribute feature has a point of intersection, so we do not replace it + + // get shape of the feature + aPointToAttributeOrObject.clear(); + aFeatures.clear(); + aFeatures.push_back(theFeature); + ModelGeomAlgo_Point2D::getPointsIntersectedShape(aTangentFeature, aFeatures, + aPointToAttributeOrObject); + if (!aPointToAttributeOrObject.empty()) { + std::set anEdgeShapes; + ModelGeomAlgo_Shape::shapesOfType(theFeature, GeomAPI_Shape::EDGE, anEdgeShapes); + if (!anEdgeShapes.empty()) { + ResultPtr aResult = *anEdgeShapes.begin(); + if (aResult.get()) { + aRefAttr->setObject(aResult); + return true; // the attribute feature has a point of intersection, so we do not replace it + } } } - return isProcessed; + return false; } AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) @@ -699,12 +715,16 @@ void SketchPlugin_Trim::getConstraints(std::set& theFeaturesToDelete std::set::const_iterator aIt; for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { - std::shared_ptr aAttr = (*aIt); - FeaturePtr aRefFeature = std::dynamic_pointer_cast(aAttr->owner()); + std::shared_ptr anAttr = (*aIt); + FeaturePtr aRefFeature = std::dynamic_pointer_cast(anAttr->owner()); std::string aRefFeatureKind = aRefFeature->getKind(); - if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() || - aRefFeatureKind == SketchPlugin_MultiRotation::ID() || - aRefFeatureKind == SketchPlugin_MultiTranslation::ID() || + std::string anAttributeId = anAttr->id(); + if ((aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() && + anAttributeId == SketchPlugin_ConstraintMirror::MIRROR_LIST_ID()) || + (aRefFeatureKind == SketchPlugin_MultiRotation::ID() && + anAttributeId == SketchPlugin_MultiRotation::ROTATION_LIST_ID()) || + (aRefFeatureKind == SketchPlugin_MultiTranslation::ID() && + anAttributeId == SketchPlugin_MultiTranslation::TRANSLATION_LIST_ID()) || aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID()) theFeaturesToDelete.insert(aRefFeature); else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) @@ -758,44 +778,6 @@ void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature, } } -/*void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject, - std::map& theCoincidencesToBaseFeature) -{ - const std::set& aRefsList = theObject->data()->refsToMe(); - std::set::const_iterator aIt; - for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { - std::shared_ptr aAttr = (*aIt); - FeaturePtr aRefFeature = std::dynamic_pointer_cast(aAttr->owner()); - if (aRefFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) - continue; - AttributePtr anAttribute; - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast - (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); - if (aRefAttr->isObject() && aRefAttr->object() == theObject) - { - anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B()); - } - else { - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast - (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); - if (aRefAttr->isObject() && aRefAttr->object() == theObject) - anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A()); - } - if (!anAttribute.get()) - continue; - - aRefAttr = std::dynamic_pointer_cast(anAttribute); - if (aRefAttr->isObject()) - continue; // one of attributes of coincidence contains link to an attribute - - anAttribute = aRefAttr->attr(); - if (anAttribute.get()) - { - theCoincidencesToBaseFeature[anAttribute] = aRefFeature; - } - } -}*/ - void SketchPlugin_Trim::updateRefAttConstraints( const std::map >& theBaseRefAttributes, const std::set >& theModifiedAttributes, @@ -1403,7 +1385,6 @@ void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject, ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(), aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID()); // layed on feature coincidences to divide it on several shapes - //SketchPlugin_Sketch* aSketch = sketch(); std::shared_ptr aData = theSketch->data(); std::shared_ptr aC = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); diff --git a/src/SketchPlugin/SketchPlugin_Trim.h b/src/SketchPlugin/SketchPlugin_Trim.h index 6371dad6c..b6b6599cf 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.h +++ b/src/SketchPlugin/SketchPlugin_Trim.h @@ -107,9 +107,10 @@ class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentab private: bool setCoincidenceToAttribute(const AttributePtr& theAttribute, const std::set >& theFurtherCoincidences); - - bool replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute, - const std::set>& theModifiedAttributes); + /// Move tangency constraint to the feature if it is geometrically closely to it + /// \param theAttribute an attribute of a tangent constraint feature + /// \param theFeature a feature that can be set into the attribute + bool moveTangency(const AttributePtr& theAttribute, const FeaturePtr& theFeature); GeomShapePtr getSubShape(const std::string& theObjectAttributeId, const std::string& thePointAttributeId); @@ -141,13 +142,6 @@ private: std::map >& theRefs, std::list& theRefsToFeature); - /// Obtains coincident features to the given object. It is collected in a container - /// by the coincident attribute - /// \param theObject an investigated object - /// \param theCoincidencesToBaseFeature a container of list of referenced attributes - //void getCoincidencesToObject(const std::shared_ptr& theObject, - // std::map& theCoincidencesToBaseFeature); - /// Move constraints from attribute of base feature to attribute after modification /// \param theBaseRefAttributes container of references to the attributes of base feature /// \param theModifiedAttributes container of attributes placed instead of base attributes diff --git a/src/SketcherPrs/SketcherPrs_SymbolPrs.cpp b/src/SketcherPrs/SketcherPrs_SymbolPrs.cpp index 005bf4cbc..3a498d827 100644 --- a/src/SketcherPrs/SketcherPrs_SymbolPrs.cpp +++ b/src/SketcherPrs/SketcherPrs_SymbolPrs.cpp @@ -331,7 +331,7 @@ void SketcherPrs_SymbolPrs::drawShape(const std::shared_ptr& theS Quantity_Color theColor) const { int aColNam = theColor.Name(); - cout<<"### SketcherPrs_SymbolPrs::drawShape "<