X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintCoincidence.cpp;h=ae4a89bcc63d3d457fab1f59da8ce078b4b2a7ba;hb=ca925f26180f15699a77e76461679f11abd499ba;hp=e1242606ea82f1f6c216f3f46da63f628175c105;hpb=8f10db487ef409d859a62aa6e2235a17d9b56723;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp index e1242606e..ae4a89bcc 100644 --- a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp @@ -1,381 +1,142 @@ +// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// + #include #include -#include - -#include -#include +#include +#include -#include +#include +#include -void SketchSolver_ConstraintCoincidence::getAttributes( - double& theValue, - std::vector& theAttributes) +static void getCoincidentFeatureExtremities(const ConstraintPtr& theConstraint, + const StoragePtr& theStorage, + EntityWrapperPtr theExtremities[2]) { - SketchSolver_Constraint::getAttributes(theValue, theAttributes); - if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN) - return; + for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { + AttributeRefAttrPtr aRefAttr = theConstraint->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); + if (!aRefAttr || !aRefAttr->isObject()) + continue; - if (theAttributes[1] != SLVS_E_UNKNOWN) { - myType = SLVS_C_POINTS_COINCIDENT; + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + if (!aFeature) + continue; - // set coordinates of slave (second) point equal to the master (first) point - Slvs_Entity aFirst = myStorage->getEntity(theAttributes[0]); - Slvs_Entity aSecond = myStorage->getEntity(theAttributes[1]); - for (int i = 0; i < 4; i++) - if (aFirst.param[i] != SLVS_E_UNKNOWN && aSecond.param[i] != SLVS_E_UNKNOWN) { - Slvs_Param aPar1 = myStorage->getParameter(aFirst.param[i]); - Slvs_Param aPar2 = myStorage->getParameter(aSecond.param[i]); - aPar2.val = aPar1.val; - myStorage->updateParameter(aPar2); - } + if (aFeature->getKind() == SketchPlugin_Line::ID()) { + theExtremities[0] = theStorage->entity(aFeature->attribute(SketchPlugin_Line::START_ID())); + theExtremities[1] = theStorage->entity(aFeature->attribute(SketchPlugin_Line::END_ID())); + } else if (aFeature->getKind() == SketchPlugin_Arc::ID()) { + theExtremities[0] = theStorage->entity(aFeature->attribute(SketchPlugin_Arc::START_ID())); + theExtremities[1] = theStorage->entity(aFeature->attribute(SketchPlugin_Arc::END_ID())); + } } - 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; - return myExtraCoincidence.find(theConstraint) != myExtraCoincidence.end(); -} - -std::list SketchSolver_ConstraintCoincidence::constraints() const -{ - std::list aConstraints; - aConstraints.push_back(myBaseConstraint); - std::map::const_iterator anIt = myExtraCoincidence.begin(); - for (; anIt != myExtraCoincidence.end(); anIt++) - aConstraints.push_back(anIt->first); - return aConstraints; -} - -bool SketchSolver_ConstraintCoincidence::isCoincide( - std::shared_ptr theConstraint) const -{ - std::set::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin(); - for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++) - if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end()) - return true; - return false; -} - -void SketchSolver_ConstraintCoincidence::attach( - std::shared_ptr theConstraint) +void SketchSolver_ConstraintCoincidence::process() { cleanErrorMsg(); - // Remove constraints from theConstraint - std::vector::iterator aCIter = theConstraint->mySlvsConstraints.begin(); - for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++) - theConstraint->myStorage->removeConstraint(*aCIter); - - if (myStorage == theConstraint->myStorage) { - // Clean removed items - std::set aRemParams; - std::set aRemEnts; - std::set aRemConstr; - theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr); - - if (!aRemEnts.empty()) { - std::map::iterator aFeatIt = theConstraint->myFeatureMap.begin(); - while (aFeatIt != theConstraint->myFeatureMap.end()) { - if (aRemEnts.find(aFeatIt->second) != aRemEnts.end()) { - // remove feature - std::map::iterator aRemoveIt = aFeatIt++; - theConstraint->myFeatureMap.erase(aRemoveIt); - } else - ++aFeatIt; - } - std::map::iterator anAttrIt = theConstraint->myAttributeMap.begin(); - while (anAttrIt != theConstraint->myAttributeMap.end()) { - if (aRemEnts.find(anAttrIt->second) != aRemEnts.end()) { - // remove attribute - std::map::iterator aRemoveIt = anAttrIt++; - theConstraint->myAttributeMap.erase(aRemoveIt); - } else - ++anAttrIt; - } - } + if (!myBaseConstraint || !myStorage) { + // Not enough parameters are assigned + return; } - // Copy data. - addConstraint(theConstraint->myBaseConstraint); - std::map::iterator aConstrIter = - theConstraint->myExtraCoincidence.begin(); - for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++) - addConstraint(aConstrIter->first); - // Clear the lists to not remove the entities on destruction - theConstraint->mySlvsConstraints.clear(); - theConstraint->myFeatureMap.clear(); - theConstraint->myAttributeMap.clear(); -} + EntityWrapperPtr aValue; + std::vector anAttributes; + getAttributes(aValue, anAttributes); + if (!myErrorMsg.empty()) + return; + if (anAttributes.empty()) { + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); + return; + } -Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint( - Slvs_hEntity thePoint1, Slvs_hEntity thePoint2) -{ - if (thePoint1 == thePoint2) - return SLVS_E_UNKNOWN; + mySolverConstraint = PlaneGCSSolver_Tools::createConstraint( + myBaseConstraint, getType(), + aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]); - 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; + myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP()); + myStorage->notify(myBaseConstraint); } -Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity( - Slvs_hEntity thePoint, Slvs_hEntity theEntity) +bool SketchSolver_ConstraintCoincidence::remove() { - // 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; + myInSolver = false; + myFeatureExtremities[0] = EntityWrapperPtr(); + myFeatureExtremities[1] = EntityWrapperPtr(); + return SketchSolver_Constraint::remove(); } -void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint) +void SketchSolver_ConstraintCoincidence::getAttributes( + EntityWrapperPtr& theValue, + std::vector& theAttributes) { - if (mySlvsConstraints.empty()) { - // This constraint is empty, rebuild it from scratch - myBaseConstraint = theConstraint; - process(); + SketchSolver_Constraint::getAttributes(theValue, theAttributes); + if (!myErrorMsg.empty() || !theAttributes[0]) { + theAttributes.clear(); return; } - std::list anAttrList = - theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); - std::list::iterator anIter = anAttrList.begin(); - std::vector aPoints; - Slvs_hEntity anEntity = SLVS_E_UNKNOWN; - int anEntType; - for (; anIter != anAttrList.end(); anIter++) { - Slvs_hEntity aPointID = SLVS_E_UNKNOWN; - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*anIter); - if (!aRefAttr) - continue; - - AttributePtr aPointAttr; - 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; - // Obtain relations between attributes of the feature and SolveSpace entities - std::list anAttrList = - aFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list::iterator anIt = anAttrList.begin(); - for (; anIt != anAttrList.end(); ++anIt) { - Slvs_hEntity anAttrID = myGroup->getAttributeId(*anIt); - if (anAttrID != SLVS_E_UNKNOWN) - myAttributeMap[*anIt] = anAttrID; - } - } - } - // If the feature is a point, add it to the list of coincident points - if (aFeature->getKind() == SketchPlugin_Point::ID()) { - aPointID = anEntity; - anEntity = SLVS_E_UNKNOWN; - aPointAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID()); - } - } else { - aPointAttr = aRefAttr->attr(); - std::map::const_iterator anAttrFound = - myAttributeMap.find(aPointAttr); - if (anAttrFound != myAttributeMap.end()) - aPointID = anAttrFound->second; - else { - aPointID = myGroup->getAttributeId(aPointAttr); - if (aPointID == SLVS_E_UNKNOWN) - aPointID = changeEntity(aPointAttr, anEntType); - } - } - - if (aPointAttr) { // the point is found - aPoints.push_back(aPointID); - myCoincidentPoints.insert(aPointAttr); - myAttributeMap[aPointAttr] = aPointID; - } - } + if (theAttributes[1]) + myType = CONSTRAINT_PT_PT_COINCIDENT; + else if (theAttributes[2]) { + // check the type of entity (line or circle) + SketchSolver_EntityType anEntType = theAttributes[2]->type(); + if (anEntType == ENTITY_LINE) + myType = CONSTRAINT_PT_ON_LINE; + else if (anEntType == ENTITY_CIRCLE || anEntType == ENTITY_ARC) + myType = CONSTRAINT_PT_ON_CIRCLE; + else + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); - Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN; - 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; - } - } - myExtraCoincidence[theConstraint] = aNewConstr; + // obtain extremity points of the coincident feature for further checking of multi-coincidence + getCoincidentFeatureExtremities(myBaseConstraint, myStorage, myFeatureExtremities); + } else + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); } -void SketchSolver_ConstraintCoincidence::process() +void SketchSolver_ConstraintCoincidence::notify(const FeaturePtr& theFeature, + PlaneGCSSolver_Update* theUpdater) { - SketchSolver_Constraint::process(); + PlaneGCSSolver_UpdateCoincidence* anUpdater = + static_cast(theUpdater); + bool isAccepted = anUpdater->addCoincidence(myAttributes.front(), myAttributes.back()); - // 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()); - } -} + // additionally check the point is coincident to extremity of coincident feature + if (myFeatureExtremities[0] && myFeatureExtremities[1]) { + EntityWrapperPtr aPoint = + myAttributes.front()->type() == ENTITY_POINT ? myAttributes.front() : myAttributes.back(); -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) { - anExtraIt = myExtraCoincidence.find(aConstraint); - if (anExtraIt == myExtraCoincidence.end()) - return false; // there is no constraint, which is specified to remove - else { - bool isEmpty = anExtraIt->second == SLVS_E_UNKNOWN; - if (!isEmpty) { - isEmpty = true; - for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++) - if (mySlvsConstraints[aPos] == anExtraIt->second) { - isEmpty = false; - break; - } - aPos -= 1; - } - myExtraCoincidence.erase(anExtraIt); - if (isEmpty) - return false; - } + for (int i = 0; i < 2; ++i) + isAccepted = isAccepted && !anUpdater->isPointOnEntity(aPoint, myFeatureExtremities[i]); } - bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]); - mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos)); - if (aPos < 0 && !myExtraCoincidence.empty()) { - anExtraIt = myExtraCoincidence.begin(); - // Remove invalid constraints - while (anExtraIt != myExtraCoincidence.end()) { - if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) { - std::map::iterator aTempIt = anExtraIt++; - if (aTempIt->first != SLVS_E_UNKNOWN) { - myStorage->removeConstraint(aTempIt->second); - std::vector::iterator anIt = mySlvsConstraints.begin(); - for (; anIt != mySlvsConstraints.end(); anIt++) - if (*anIt == aTempIt->second) { - mySlvsConstraints.erase(anIt); - break; - } - } - myExtraCoincidence.erase(aTempIt); - continue; - } - anExtraIt++; - } - // Find first non-extra conststraint - anExtraIt = myExtraCoincidence.begin(); - while (anExtraIt != myExtraCoincidence.end() && anExtraIt->second == SLVS_E_UNKNOWN) - anExtraIt++; - if (anExtraIt != myExtraCoincidence.end()) { - // Need to specify another base coincidence constraint - myBaseConstraint = anExtraIt->first; - myExtraCoincidence.erase(anExtraIt); - if (mySlvsConstraints.empty()) { - 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; + if (isAccepted) { + if (!myInSolver) { + myInSolver = true; + myStorage->addConstraint(myBaseConstraint, mySolverConstraint); } - 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->first->data() || !anExtraIt->first->data()->isValid()) { - std::map::iterator aTempIt = anExtraIt++; - myExtraCoincidence.erase(aTempIt); - continue; - } - if (mySlvsConstraints.empty()) { - myBaseConstraint = anExtraIt->first; - std::map::iterator aTempIt = anExtraIt++; - myExtraCoincidence.erase(aTempIt); - process(); - continue; - } else - addConstraint(anExtraIt->first); + } else { + if (myInSolver) { + myInSolver = false; + myStorage->removeConstraint(myBaseConstraint); } - anExtraIt++; } - return mySlvsConstraints.empty(); } -