From 4dd10dddeec6b5861d90ee784aaa18129638ce36 Mon Sep 17 00:00:00 2001 From: Artem Zhidkov Date: Tue, 23 Jun 2020 09:11:41 +0300 Subject: [PATCH 1/1] Task #3231: Sketcher Offset of a curve Improve searching of coincidences in context of B-spline curve --- src/SketchPlugin/SketchPlugin_Offset.cpp | 19 ++-- src/SketchPlugin/SketchPlugin_Tools.cpp | 131 +++++++++++++++++------ src/SketchPlugin/SketchPlugin_Tools.h | 10 +- 3 files changed, 118 insertions(+), 42 deletions(-) diff --git a/src/SketchPlugin/SketchPlugin_Offset.cpp b/src/SketchPlugin/SketchPlugin_Offset.cpp index d789c85a7..f941bc315 100644 --- a/src/SketchPlugin/SketchPlugin_Offset.cpp +++ b/src/SketchPlugin/SketchPlugin_Offset.cpp @@ -164,12 +164,19 @@ bool SketchPlugin_Offset::findWireOneWay (const FeaturePtr& theFirstEdge, FeaturePtr aNextEdgeFeature; int nbFound = 0; - std::set aCoincPoints = - SketchPlugin_Tools::findPointsCoincidentToPoint(theEndPoint); - - std::set::iterator aPointsIt = aCoincPoints.begin(); - for (; aPointsIt != aCoincPoints.end(); aPointsIt++) { - AttributePoint2DPtr aP = (*aPointsIt); + std::set aCoincPoints; + std::map aCoincPointsInArray; + SketchPlugin_Tools::findPointsCoincidentToPoint(theEndPoint, aCoincPoints, aCoincPointsInArray); + + // store all found attributes to a single array + std::set anAllCoincPoints; + anAllCoincPoints.insert(aCoincPoints.begin(), aCoincPoints.end()); + for (auto it = aCoincPointsInArray.begin(); it != aCoincPointsInArray.end(); ++it) + anAllCoincPoints.insert(it->first); + + std::set::iterator aPointsIt = anAllCoincPoints.begin(); + for (; aPointsIt != anAllCoincPoints.end(); aPointsIt++) { + AttributePtr aP = (*aPointsIt); FeaturePtr aCoincFeature = std::dynamic_pointer_cast(aP->owner()); // Condition 1: not a point feature diff --git a/src/SketchPlugin/SketchPlugin_Tools.cpp b/src/SketchPlugin/SketchPlugin_Tools.cpp index 68765a14e..6209b788d 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.cpp +++ b/src/SketchPlugin/SketchPlugin_Tools.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -113,10 +114,10 @@ std::shared_ptr getCoincidencePoint(const FeaturePtr theStartCoin return aPnt; } -std::set findCoincidentConstraints(const FeaturePtr& theFeature) +std::set findCoincidentConstraints(const ObjectPtr& theObject) { std::set aCoincident; - const std::set& aRefsList = theFeature->data()->refsToMe(); + const std::set& aRefsList = theObject->data()->refsToMe(); std::set::const_iterator aIt; for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { FeaturePtr aConstrFeature = std::dynamic_pointer_cast((*aIt)->owner()); @@ -199,38 +200,53 @@ std::set findFeaturesCoincidentToPoint(const AttributePoint2DPtr& th // Useful to find points coincident to a given point. class CoincidentPoints { + static const int THE_DEFAULT_INDEX = -1; + public: - void addCoincidence(const AttributePoint2DPtr& thePoint1, - const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr()) + void addCoincidence(const AttributePtr& thePoint1, const int theIndex1, + const AttributePtr& thePoint2, const int theIndex2) { - std::list< std::set >::iterator aFound1 = find(thePoint1); - std::list< std::set >::iterator aFound2 = find(thePoint2); + auto aFound1 = find(thePoint1, theIndex1); + auto aFound2 = find(thePoint2, theIndex2); if (aFound1 == myCoincidentPoints.end()) { if (aFound2 == myCoincidentPoints.end()) { - std::set aNewSet; - aNewSet.insert(thePoint1); + std::map > aNewSet; + aNewSet[thePoint1].insert(theIndex1); if (thePoint2) - aNewSet.insert(thePoint2); + aNewSet[thePoint2].insert(theIndex2); myCoincidentPoints.push_back(aNewSet); } else - aFound2->insert(thePoint1); + (*aFound2)[thePoint1].insert(theIndex1); } else if (aFound2 == myCoincidentPoints.end()) { if (thePoint2) - aFound1->insert(thePoint2); + (*aFound1)[thePoint2].insert(theIndex2); } else { - aFound1->insert(aFound2->begin(), aFound2->end()); + for (auto it = aFound2->begin(); it != aFound2->end(); ++it) + (*aFound1)[it->first].insert(it->second.begin(), it->second.end()); myCoincidentPoints.erase(aFound2); } } - std::set coincidentPoints(const AttributePoint2DPtr& thePoint) + void coincidentPoints(const AttributePoint2DPtr& thePoint, + std::set& thePoints, + std::map& thePointsInArray) { collectCoincidentPoints(thePoint); - std::list< std::set >::iterator aFound = find(thePoint); - if (aFound == myCoincidentPoints.end()) - return std::set(); - return *aFound; + auto aFound = find(thePoint, THE_DEFAULT_INDEX); + if (aFound != myCoincidentPoints.end()) { + for (auto it = aFound->begin(); it != aFound->end(); ++it) { + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast(it->first); + if (aPoint) + thePoints.insert(aPoint); + else { + AttributePoint2DArrayPtr aPointArray = + std::dynamic_pointer_cast(it->first); + if (aPointArray) + thePointsInArray[aPointArray] = *it->second.begin(); + } + } + } } private: @@ -239,7 +255,11 @@ private: { // iterate through coincideces for the given feature std::set aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature); - std::set::const_iterator aCIt = aCoincidences.begin(); + if (theFeature->getKind() == SketchPlugin_Point::ID()) { + std::set aCoincToRes = + SketchPlugin_Tools::findCoincidentConstraints(theFeature->lastResult()); + aCoincidences.insert(aCoincToRes.begin(), aCoincToRes.end()); + } std::set::const_iterator aCIt = aCoincidences.begin(); for (; aCIt != aCoincidences.end(); ++aCIt) { if (theCoincidences.find(*aCIt) != theCoincidences.end()) @@ -248,12 +268,18 @@ private: // iterate on coincident attributes for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); - if (aRefAttr && !aRefAttr->isObject()) - { - FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner()); - if (anOwner != theFeature) - coincidences(anOwner, theCoincidences); + if (!aRefAttr) + continue; + FeaturePtr anOwner; + if (aRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + if (aFeature->getKind() == SketchPlugin_Point::ID()) + anOwner = aFeature; } + else + anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner()); + if (anOwner && anOwner != theFeature) + coincidences(anOwner, theCoincidences); } } } @@ -262,7 +288,8 @@ private: // (two points may be coincident through the third point) void collectCoincidentPoints(const AttributePoint2DPtr& thePoint) { - AttributePoint2DPtr aPoints[2]; + AttributePtr aPoints[2]; + int anIndicesInArray[2]; FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner()); std::set aCoincidences; @@ -270,38 +297,72 @@ private: std::set::const_iterator aCIt = aCoincidences.begin(); for (; aCIt != aCoincidences.end(); ++aCIt) { - aPoints[0] = AttributePoint2DPtr(); - aPoints[1] = AttributePoint2DPtr(); + aPoints[0] = aPoints[1] = AttributePtr(); + anIndicesInArray[0] = anIndicesInArray[1] = THE_DEFAULT_INDEX; for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); - if (aRefAttr && !aRefAttr->isObject()) - aPoints[aPtInd++] = std::dynamic_pointer_cast(aRefAttr->attr()); + if (!aRefAttr) + continue; + if (aRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID()) + aPoints[aPtInd++] = aFeature->attribute(SketchPlugin_Point::COORD_ID()); + } + else { + AttributePoint2DPtr aPointAttr = + std::dynamic_pointer_cast(aRefAttr->attr()); + AttributePoint2DArrayPtr aPointArray = + std::dynamic_pointer_cast(aRefAttr->attr()); + if (aPointAttr) + aPoints[aPtInd++] = aPointAttr; + else if (aPointArray) { + AttributeIntegerPtr anIndexAttr = (*aCIt)->integer(i == 0 ? + SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_A() : + SketchPlugin_ConstraintCoincidenceInternal::INDEX_ENTITY_B()); + aPoints[aPtInd] = aPointArray; + anIndicesInArray[aPtInd++] = anIndexAttr->value(); + } + } } if (aPoints[0] && aPoints[1]) - addCoincidence(aPoints[0], aPoints[1]); + addCoincidence(aPoints[0], anIndicesInArray[0], aPoints[1], anIndicesInArray[1]); } } - std::list< std::set >::iterator find(const AttributePoint2DPtr& thePoint) + std::list< std::map > >::iterator find(const AttributePtr& thePoint, + const int theIndex) { - std::list< std::set >::iterator aSeek = myCoincidentPoints.begin(); - for (; aSeek != myCoincidentPoints.end(); ++aSeek) - if (aSeek->find(thePoint) != aSeek->end()) + auto aSeek = myCoincidentPoints.begin(); + for (; aSeek != myCoincidentPoints.end(); ++aSeek) { + auto aFound = aSeek->find(thePoint); + if (aFound != aSeek->end() && aFound->second.find(theIndex) != aFound->second.end()) return aSeek; + } return myCoincidentPoints.end(); } private: - std::list< std::set > myCoincidentPoints; + std::list< std::map > > myCoincidentPoints; }; std::set findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint) +{ + std::set aPoints; + std::map aPointsInArray; + findPointsCoincidentToPoint(thePoint, aPoints, aPointsInArray); + return aPoints; +} + +void findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint, + std::set& thePoints, + std::map& thePointsInArray) { CoincidentPoints aCoincidentPoints; - return aCoincidentPoints.coincidentPoints(thePoint); + aCoincidentPoints.coincidentPoints(thePoint, thePoints, thePointsInArray); } + void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId) { diff --git a/src/SketchPlugin/SketchPlugin_Tools.h b/src/SketchPlugin/SketchPlugin_Tools.h index 1a12945c9..11aa5a1ac 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.h +++ b/src/SketchPlugin/SketchPlugin_Tools.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -49,7 +50,7 @@ void clearExpressions(FeaturePtr theFeature); std::shared_ptr getCoincidencePoint(const FeaturePtr theStartCoin); /// Find all Coincident constraints referred to the feature or its attribute -std::set findCoincidentConstraints(const FeaturePtr& theFeature); +std::set findCoincidentConstraints(const ObjectPtr& theObject); /// Finds lines coincident at point /// \param[in] theStartCoin coincidence feature @@ -67,6 +68,13 @@ std::set findFeaturesCoincidentToPoint(const AttributePoint2DPtr& th /// Find all points the given point is coincident to. std::set findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint); +/// Find all points the given point is coincident to. +/// Returns GeomDataAPI_Point2D attribute and +/// GeomDataAPI_Point2DArray with the index of coincident point. +void findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint, + std::set& thePoints, + std::map& thePointsInArray); + void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId); /// Create new constraint between given attributes -- 2.30.2