From 3c445d389d3cbe4c98403bc62e4b6ba8d06cc314 Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 20 Aug 2015 11:07:52 +0300 Subject: [PATCH] Check the multi coincidence between different types of entities (issue #751) --- .../SketchSolver_ConstraintCoincidence.cpp | 101 ++++++++++++++---- .../SketchSolver_ConstraintCoincidence.h | 3 + .../SketchSolver_ConstraintFillet.cpp | 2 +- .../SketchSolver_ConstraintTangent.cpp | 2 +- src/SketchSolver/SketchSolver_Group.cpp | 5 + src/SketchSolver/SketchSolver_Storage.cpp | 11 +- src/SketchSolver/SketchSolver_Storage.h | 3 + 7 files changed, 104 insertions(+), 23 deletions(-) diff --git a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp index 0840c3714..0e6ee7490 100644 --- a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp @@ -48,10 +48,6 @@ std::list SketchSolver_ConstraintCoincidence::constraints() const bool SketchSolver_ConstraintCoincidence::isCoincide( std::shared_ptr theConstraint) const { - // Multi-coincidence allowed for two points only - if (getType() != theConstraint->getType() || getType() != SLVS_C_POINTS_COINCIDENT) - return false; - std::set::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin(); for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++) if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end()) @@ -112,6 +108,9 @@ void SketchSolver_ConstraintCoincidence::attach( Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint( Slvs_hEntity thePoint1, Slvs_hEntity thePoint2) { + if (thePoint1 == thePoint2) + return SLVS_E_UNKNOWN; + bool hasDuplicated = myStorage->hasDuplicatedConstraint(); Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2, @@ -126,34 +125,96 @@ Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint( return aNewID; } +Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity( + Slvs_hEntity thePoint, Slvs_hEntity theEntity) +{ + // Check the point is not coincident with boundaries of the entity + Slvs_Entity anEnt = myStorage->getEntity(theEntity); + int aPos = anEnt.type == SLVS_E_LINE_SEGMENT ? 0 : 1; + for (; anEnt.point[aPos] != SLVS_E_UNKNOWN; aPos++) + if (anEnt.point[aPos] == thePoint || + myStorage->isCoincident(anEnt.point[aPos], thePoint)) + return SLVS_E_UNKNOWN; + + bool hasDuplicated = myStorage->hasDuplicatedConstraint(); + Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front()); + Slvs_hConstraint aType = anEnt.type == SLVS_E_LINE_SEGMENT ? + SLVS_C_PT_ON_LINE : SLVS_C_PT_ON_CIRCLE; + Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), + aType, myGroup->getWorkplaneId(), 0.0, aBaseCoincidence.ptA, SLVS_E_UNKNOWN, + theEntity, SLVS_E_UNKNOWN); + Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint); + if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) { + // the duplicated constraint appears + myStorage->removeConstraint(aNewID); + return SLVS_E_UNKNOWN; + } + mySlvsConstraints.push_back(aNewID); + return aNewID; +} + void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint) { + if (mySlvsConstraints.empty()) { + // This constraint is empty, rebuild it from scratch + myBaseConstraint = theConstraint; + process(); + return; + } + std::list anAttrList = theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); std::list::iterator anIter = anAttrList.begin(); - std::vector anEntities; + std::vector aPoints; + Slvs_hEntity anEntity = SLVS_E_UNKNOWN; + int anEntType; for (; anIter != anAttrList.end(); anIter++) { AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*anIter); - if (!aRefAttr || aRefAttr->isObject() || - myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end()) + if (!aRefAttr) continue; - int aType; - Slvs_hEntity anEntityID = myGroup->getAttributeId(aRefAttr->attr()); - if (anEntityID == SLVS_E_UNKNOWN) - anEntityID = changeEntity(aRefAttr->attr(), aType); - anEntities.push_back(anEntityID); - myCoincidentPoints.insert(aRefAttr->attr()); + if (aRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + std::map::const_iterator aFeatFound = + myFeatureMap.find(aFeature); + if (aFeatFound != myFeatureMap.end()) + anEntity = aFeatFound->second; + else { + anEntity = myGroup->getFeatureId(aFeature); + if (anEntity == SLVS_E_UNKNOWN) + anEntity = changeEntity(aFeature, anEntType); + else + myFeatureMap[aFeature] = anEntity; + } + } else { + Slvs_hEntity anEntID = SLVS_E_UNKNOWN; + std::map::const_iterator anAttrFound = + myAttributeMap.find(aRefAttr->attr()); + if (anAttrFound != myAttributeMap.end()) + anEntID = anAttrFound->second; + else { + anEntID = myGroup->getAttributeId(aRefAttr->attr()); + if (anEntID == SLVS_E_UNKNOWN) + anEntID = changeEntity(aRefAttr->attr(), anEntType); + else + myAttributeMap[aRefAttr->attr()] = anEntID; + } + aPoints.push_back(anEntID); + myCoincidentPoints.insert(aRefAttr->attr()); + } } Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN; - std::vector::iterator anEntIter = anEntities.begin(); - if (mySlvsConstraints.empty()) { - aNewConstr = addConstraint(*anEntIter, *(anEntIter + 1)); - anEntIter += 2; + if (anEntity != SLVS_E_UNKNOWN) + aNewConstr = addPointOnEntity(aPoints.front(), anEntity); + else { // coincidence between two points + Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front()); + std::vector::const_iterator aPtIter = aPoints.begin(); + for (; aPtIter != aPoints.end(); aPtIter++) { + Slvs_hConstraint aC = addConstraint(aBaseCoincidence.ptA, *aPtIter); + if (aC != SLVS_E_UNKNOWN) + aNewConstr = aC; + } } - Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front()); - for (; anEntIter != anEntities.end(); anEntIter++) - aNewConstr = addConstraint(aBaseCoincidence.ptA, *anEntIter); myExtraCoincidence[theConstraint] = aNewConstr; } diff --git a/src/SketchSolver/SketchSolver_ConstraintCoincidence.h b/src/SketchSolver/SketchSolver_ConstraintCoincidence.h index 43354e80d..47d58e0e2 100644 --- a/src/SketchSolver/SketchSolver_ConstraintCoincidence.h +++ b/src/SketchSolver/SketchSolver_ConstraintCoincidence.h @@ -58,6 +58,9 @@ private: /// \brief Create full SolveSpace structure according to given constraint void addConstraint(ConstraintPtr theConstraint); + /// \brief Create constraint of point concident to the line or circle + Slvs_hConstraint addPointOnEntity(Slvs_hEntity thePoint, Slvs_hEntity theEntity); + private: int myType; ///< type of constraint (applicable SLVS_C_POINTS_COINCIDENT or SLVS_C_PT_ON_LINE or SLVS_C_PT_ON_CIRCLE) std::map myExtraCoincidence; ///< multiple coincidence of points diff --git a/src/SketchSolver/SketchSolver_ConstraintFillet.cpp b/src/SketchSolver/SketchSolver_ConstraintFillet.cpp index a8b9bcf37..3d53b9010 100644 --- a/src/SketchSolver/SketchSolver_ConstraintFillet.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintFillet.cpp @@ -104,7 +104,7 @@ void SketchSolver_ConstraintFillet::process() bool isPointFound = false; for (int i = 0; i < 2 && !isPointFound; i++) for (int j = 2; j < 4 && !isPointFound; j++) - if (myStorage->isCoincident(aPointsToFind[i], aPointsToFind[j])) { + if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) { aCoincInd[0] = i; aCoincInd[1] = j - 2; isPointFound = true; diff --git a/src/SketchSolver/SketchSolver_ConstraintTangent.cpp b/src/SketchSolver/SketchSolver_ConstraintTangent.cpp index 37b59fab2..865065411 100644 --- a/src/SketchSolver/SketchSolver_ConstraintTangent.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintTangent.cpp @@ -61,7 +61,7 @@ void SketchSolver_ConstraintTangent::process() bool isPointFound = false; for (int i = 0; i < 2 && !isPointFound; i++) for (int j = 2; j < 4 && !isPointFound; j++) - if (myStorage->isCoincident(aPointsToFind[i], aPointsToFind[j])) { + if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) { aSlvsOtherFlag = i; aSlvsOther2Flag = j - 2; isPointFound = true; diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index f77a22f33..dbe952f61 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -209,6 +209,11 @@ bool SketchSolver_Group::changeConstraint( std::dynamic_pointer_cast(aConstraint); if (aCoincidence != aCoinc2 && aCoincidence->isCoincide(aCoinc2)) { aCoinc2->attach(aCoincidence); + // update other coincidences + ConstraintConstraintMap::iterator anIt = aCIter; + for (++anIt; anIt != myConstraints.end(); ++anIt) + if (anIt->second == aCIter->second) + anIt->second = aCoinc2; aCIter->second = aCoinc2; } } diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index 793d6d42d..30d3f5790 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -738,7 +738,16 @@ bool SketchSolver_Storage::isCoincident( for (; aCIter != myCoincidentPoints.end(); aCIter++) if (aCIter->find(thePoint1) != aCIter->end() && aCIter->find(thePoint2) != aCIter->end()) return true; - // precise checking of coincidence + return false; +} + +bool SketchSolver_Storage::isEqual( + const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const +{ + if (isCoincident(thePoint1, thePoint2)) + return true; + + // Precise checking of coincidence: verify that points have equal coordinates int aEnt1Pos = Search(thePoint1, myEntities); int aEnt2Pos = Search(thePoint2, myEntities); if (aEnt1Pos >= 0 && aEnt1Pos < (int)myEntities.size() && diff --git a/src/SketchSolver/SketchSolver_Storage.h b/src/SketchSolver/SketchSolver_Storage.h index 346440996..2d1e1cd12 100644 --- a/src/SketchSolver/SketchSolver_Storage.h +++ b/src/SketchSolver/SketchSolver_Storage.h @@ -150,6 +150,9 @@ public: /// \brief Check two points are coincident bool isCoincident(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const; + /// \brief Check two points are coincident or have same coordinates + bool isEqual(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const; + /// \brief Check the entity is horizontal of vertical bool isAxisParallel(const Slvs_hEntity& theEntity) const; -- 2.39.2