X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintCoincidence.cpp;h=04e6db8d21c62e7c460d973106f8c830f7c4b664;hb=f003def34d1a3dd56e87329920d1950f080c58d1;hp=a5b6001e7efd03e2d301ae14fcc6bd0b106c6a75;hpb=bc06873747d5ea9bc0e8d6bd56641eebe33ac08d;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp index a5b6001e7..04e6db8d2 100644 --- a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp @@ -4,13 +4,37 @@ #include +void SketchSolver_ConstraintCoincidence::getAttributes( + double& theValue, + std::vector& theAttributes) +{ + SketchSolver_Constraint::getAttributes(theValue, theAttributes); + if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN) + return; + + if (theAttributes[1] != SLVS_E_UNKNOWN) + myType = SLVS_C_POINTS_COINCIDENT; + else if (theAttributes[2] != SLVS_E_UNKNOWN) { + // check the type of entity (line or circle) + Slvs_Entity anEnt = myStorage->getEntity(theAttributes[2]); + if (anEnt.type == SLVS_E_LINE_SEGMENT) + myType = SLVS_C_PT_ON_LINE; + else if (anEnt.type == SLVS_E_CIRCLE || anEnt.type == SLVS_E_ARC_OF_CIRCLE) + myType = SLVS_C_PT_ON_CIRCLE; + else + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); + } else + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); +} + + bool SketchSolver_ConstraintCoincidence::hasConstraint(ConstraintPtr theConstraint) const { if (myBaseConstraint == theConstraint) return true; - std::map::const_iterator anIt = myExtraCoincidence.begin(); + std::map::const_iterator anIt = myExtraCoincidence.begin(); for (; anIt != myExtraCoincidence.end(); anIt++) - if (anIt->first == theConstraint) + if (anIt->second == theConstraint) return true; return false; } @@ -19,22 +43,22 @@ std::list SketchSolver_ConstraintCoincidence::constraints() const { std::list aConstraints; aConstraints.push_back(myBaseConstraint); - std::map::const_iterator anIt = myExtraCoincidence.begin(); + std::map::const_iterator anIt = myExtraCoincidence.begin(); for (; anIt != myExtraCoincidence.end(); anIt++) - aConstraints.push_back(anIt->first); + aConstraints.push_back(anIt->second); return aConstraints; } bool SketchSolver_ConstraintCoincidence::isCoincide( std::shared_ptr theConstraint) const { - std::map::const_iterator aFeatIter = myFeatureMap.begin(); - for (; aFeatIter != myFeatureMap.end(); aFeatIter++) - if (theConstraint->myFeatureMap.find(aFeatIter->first) != theConstraint->myFeatureMap.end()) - return true; - std::map::const_iterator anAttrIter = myAttributeMap.begin(); - for (; anAttrIter != myAttributeMap.end(); anAttrIter++) - if (theConstraint->myAttributeMap.find(anAttrIter->first) != theConstraint->myAttributeMap.end()) + // 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()) return true; return false; } @@ -59,10 +83,10 @@ void SketchSolver_ConstraintCoincidence::attach( // Copy data. addConstraint(theConstraint->myBaseConstraint); - std::map::iterator aConstrIter = + std::map::iterator aConstrIter = theConstraint->myExtraCoincidence.begin(); for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++) - addConstraint(aConstrIter->first); + addConstraint(aConstrIter->second); // Clear the lists to not remove the entities on destruction theConstraint->mySlvsConstraints.clear(); theConstraint->myFeatureMap.clear(); @@ -72,10 +96,16 @@ void SketchSolver_ConstraintCoincidence::attach( Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint( Slvs_hEntity thePoint1, Slvs_hEntity thePoint2) { + bool hasDuplicated = myStorage->hasDuplicatedConstraint(); Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2, SLVS_E_UNKNOWN, 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; } @@ -96,6 +126,7 @@ void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstrai if (anEntityID == SLVS_E_UNKNOWN) anEntityID = changeEntity(aRefAttr->attr(), aType); anEntities.push_back(anEntityID); + myCoincidentPoints.insert(aRefAttr->attr()); } Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front()); @@ -103,38 +134,123 @@ void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstrai std::vector::iterator anEntIter = anEntities.begin(); for (; anEntIter != anEntities.end(); anEntIter++) aNewConstr = addConstraint(aBaseCoincidence.ptA, *anEntIter); - myExtraCoincidence[theConstraint] = aNewConstr; + myExtraCoincidence[aNewConstr] = theConstraint; +} + +void SketchSolver_ConstraintCoincidence::process() +{ + SketchSolver_Constraint::process(); + + // Fill the list of coincident points + std::list anAttrList = + myBaseConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + std::list::iterator anIt = anAttrList.begin(); + for (; anIt != anAttrList.end(); anIt++) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*anIt); + if (!aRefAttr || aRefAttr->isObject()) + continue; + myCoincidentPoints.insert(aRefAttr->attr()); + } } bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint) { cleanErrorMsg(); + if (mySlvsConstraints.empty()) + return true; ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint; int aPos = -1; // position of constraint in the list (-1 for base constraint) + std::map::iterator anExtraIt; if (aConstraint != myBaseConstraint) { - std::map::const_iterator anIt = myExtraCoincidence.begin(); - for (aPos = 0; anIt != myExtraCoincidence.end(); anIt++, aPos++) - if (anIt->first == aConstraint) + anExtraIt = myExtraCoincidence.begin(); + for (aPos = 0; anExtraIt != myExtraCoincidence.end(); anExtraIt++, aPos++) + if (anExtraIt->second == aConstraint) break; if (aPos >= (int)myExtraCoincidence.size()) return false; // there is no constraint, which is specified to remove + else { + bool isEmpty = anExtraIt->first == SLVS_E_UNKNOWN; + myExtraCoincidence.erase(anExtraIt); + if (isEmpty) + return false; + } } bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]); mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos)); - cleanRemovedEntities(); if (aPos < 0 && !myExtraCoincidence.empty()) { - // Need to specify another base coincidence constraint - myBaseConstraint = myExtraCoincidence.begin()->first; - myExtraCoincidence.erase(myExtraCoincidence.begin()); - std::vector::iterator aCIter = mySlvsConstraints.begin(); - Slvs_Constraint aBase = myStorage->getConstraint(*aCIter); - for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) { - Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter); - aConstr.ptA = aBase.ptA; - myStorage->updateConstraint(aConstr); + anExtraIt = myExtraCoincidence.begin(); + // Remove invalid constraints + while (anExtraIt != myExtraCoincidence.end()) { + if (!anExtraIt->second->data() || !anExtraIt->second->data()->isValid()) { + std::map::iterator aTempIt = anExtraIt++; + if (aTempIt->first != SLVS_E_UNKNOWN) { + myStorage->removeConstraint(aTempIt->first); + std::vector::iterator anIt = mySlvsConstraints.begin(); + for (; anIt != mySlvsConstraints.end(); anIt++) + if (*anIt == aTempIt->first) { + mySlvsConstraints.erase(anIt); + break; + } + } + myExtraCoincidence.erase(aTempIt); + continue; + } + anExtraIt++; + } + // Find first non-extra conststraint + anExtraIt = myExtraCoincidence.begin(); + while (anExtraIt != myExtraCoincidence.end() && anExtraIt->first == SLVS_E_UNKNOWN) + anExtraIt++; + if (anExtraIt != myExtraCoincidence.end()) { + // Need to specify another base coincidence constraint + myBaseConstraint = anExtraIt->second; + myExtraCoincidence.erase(anExtraIt); + std::vector::iterator aCIter = mySlvsConstraints.begin(); + Slvs_Constraint aBase = myStorage->getConstraint(*aCIter); + for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) { + Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter); + aConstr.ptA = aBase.ptA; + myStorage->updateConstraint(aConstr); + } + } + } + // Clear removed attributes + std::set aParamRemoved; + std::set anEntRemoved; + std::set aConstrRemoved; + myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved); + std::map::iterator anAttrIter = myAttributeMap.begin(); + while (anAttrIter != myAttributeMap.end()) { + if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) { + std::map::iterator aTempIt = anAttrIter++; + myCoincidentPoints.erase(aTempIt->first); + myAttributeMap.erase(aTempIt); + continue; + } + anAttrIter++; + } + + // Go through remaining extra coincidence and try to add or remove them + anExtraIt = myExtraCoincidence.begin(); + while (anExtraIt != myExtraCoincidence.end()) { + if (anExtraIt->first == SLVS_E_UNKNOWN) { + if (!anExtraIt->second->data() || !anExtraIt->second->data()->isValid()) { + std::map::iterator aTempIt = anExtraIt++; + myExtraCoincidence.erase(aTempIt); + continue; + } + if (mySlvsConstraints.empty()) { + myBaseConstraint = anExtraIt->second; + std::map::iterator aTempIt = anExtraIt++; + myExtraCoincidence.erase(aTempIt); + process(); + continue; + } else + addConstraint(anExtraIt->second); } + anExtraIt++; } - return true; + return mySlvsConstraints.empty(); }