X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSolveSpaceSolver%2FSolveSpaceSolver_Storage.cpp;h=3aabbecbd177487891e926fd0931df7c3d7d46d1;hb=97917d3698f5a2f7fc9596e7c755ff8f6751e373;hp=a34cee193ee18f3cc8d16248c105b6e8d7f898a9;hpb=c5052205bdd490c042da4016ea07950d7eccc112;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp index a34cee193..3aabbecbd 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp @@ -1,8 +1,21 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: SolveSpaceSolver_Storage.cpp -// Created: 18 Mar 2015 -// Author: Artem ZHIDKOV +// Copyright (C) 2014-2019 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 @@ -21,7 +34,7 @@ #include #include #include -#include +#include /** \brief Search the entity/parameter with specified ID in the list of elements * \param[in] theEntityID unique ID of the element @@ -36,7 +49,8 @@ static bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2) /// \brief Compare two entities to be different static bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2); /// \brief Compare two constraints to be different -static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2); +static bool IsNotEqual(const Slvs_Constraint& theConstraint1, + const Slvs_Constraint& theConstraint2); SolveSpaceSolver_Storage::SolveSpaceSolver_Storage(const GroupID& theGroup) @@ -45,7 +59,6 @@ SolveSpaceSolver_Storage::SolveSpaceSolver_Storage(const GroupID& theGroup) myParamMaxID(SLVS_E_UNKNOWN), myEntityMaxID(SLVS_E_UNKNOWN), myConstrMaxID(SLVS_C_UNKNOWN), - myFixed(SLVS_E_UNKNOWN), myDuplicatedConstraint(false) { } @@ -60,8 +73,9 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint) aSlvsConstr = aConstraint->constraint(); // update value of constraint if exist - if (fabs(aSlvsConstr.valA - theConstraint->value()) > tolerance) { - aSlvsConstr.valA = theConstraint->value(); + double aCoeff = aSlvsConstr.type == SLVS_C_DIAMETER ? 2.0 : 1.0; + if (fabs(aSlvsConstr.valA - theConstraint->value() * aCoeff) > tolerance) { + aSlvsConstr.valA = theConstraint->value() * aCoeff; isUpdated = true; } @@ -76,8 +90,12 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint) std::list::iterator anIt = anEntities.begin(); for (; anIt != anEntities.end(); ++anIt) { isUpdated = update(*anIt) || isUpdated; - // do not update constrained entities for Multi constraints - if (aSlvsConstr.type == SLVS_C_MULTI_ROTATION || aSlvsConstr.type == SLVS_C_MULTI_TRANSLATION) + // do not update constrained entities for Multi constraints, + // and for middle point constraint translated to equal lines + ConstraintPtr aBaseConstraint = theConstraint->baseConstraint(); + if (aSlvsConstr.type == SLVS_C_MULTI_ROTATION || aSlvsConstr.type == SLVS_C_MULTI_TRANSLATION || + (aBaseConstraint && aBaseConstraint->getKind() == SketchPlugin_ConstraintMiddle::ID() && + aSlvsConstr.type != SLVS_C_AT_MIDPOINT)) continue; Slvs_hEntity anID = (Slvs_hEntity)(*anIt)->id(); @@ -108,7 +126,7 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint) aConstraint->changeConstraint() = getConstraint(aConstrID); isUpdated = true; // check duplicated constraints based on different attributes - if (myDuplicatedConstraint && !hasDupConstraints && findSameConstraint(aConstraint)) + if (myDuplicatedConstraint && findSameConstraint(aConstraint) && !hasDupConstraints) myDuplicatedConstraint = false; } } @@ -118,7 +136,7 @@ bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint) bool SolveSpaceSolver_Storage::update(EntityWrapperPtr theEntity) { bool isUpdated = false; - std::shared_ptr anEntity = + std::shared_ptr anEntity = std::dynamic_pointer_cast(theEntity); Slvs_Entity aSlvsEnt = getEntity((Slvs_hEntity)anEntity->id()); if (aSlvsEnt.h == SLVS_E_UNKNOWN) @@ -199,14 +217,15 @@ bool SolveSpaceSolver_Storage::update(EntityWrapperPtr theEntity) bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr theParameter) { - std::shared_ptr aParameter = + std::shared_ptr aParameter = std::dynamic_pointer_cast(theParameter); const Slvs_Param& aParam = getParameter((Slvs_hParam)aParameter->id()); if (aParam.h != SLVS_E_UNKNOWN && fabs(aParam.val - aParameter->value()) < tolerance) return false; Slvs_Param aParamToUpd = aParameter->parameter(); if (aParamToUpd.group == SLVS_G_UNKNOWN) - aParamToUpd.group = aParameter->isParametric() ? (Slvs_hGroup)GID_OUTOFGROUP : (Slvs_hGroup)myGroupID; + aParamToUpd.group = aParameter->isParametric() ? (Slvs_hGroup)GID_OUTOFGROUP : + (Slvs_hGroup)myGroupID; Slvs_hParam anID = updateParameter(aParamToUpd); if (aParam.h == SLVS_E_UNKNOWN) // new parameter aParameter->changeParameter() = getParameter(anID); @@ -215,7 +234,8 @@ bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr theParameter) void SolveSpaceSolver_Storage::storeWorkplane(EntityWrapperPtr theSketch) { - myWorkplaneID = (Slvs_hEntity)theSketch->id(); + mySketchID = theSketch->id(); + myWorkplaneID = (Slvs_hEntity)mySketchID; // Update sub-entities of the sketch std::list aSubEntities = theSketch->subEntities(); @@ -244,13 +264,12 @@ void SolveSpaceSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const Gro for (; aSIt != aSubs.end(); ++aSIt) changeGroup(*aSIt, theGroup); - if (theEntity->group() != theGroup) { - theEntity->setGroup(theGroup); - int aPos = Search((Slvs_hEntity)theEntity->id(), myEntities); - if (aPos >= 0 && aPos < (int)myEntities.size()) { - myEntities[aPos].group = (Slvs_hGroup)theGroup; + theEntity->setGroup(theGroup); + int aPos = Search((Slvs_hEntity)theEntity->id(), myEntities); + if (aPos >= 0 && aPos < (int)myEntities.size()) { + if (myEntities[aPos].group != (Slvs_hGroup)theGroup) setNeedToResolve(true); - } + myEntities[aPos].group = (Slvs_hGroup)theGroup; } } @@ -275,11 +294,18 @@ void SolveSpaceSolver_Storage::addCoincidentPoints( { if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT) return; + if (!theMaster->subEntities().empty() || !theSlave->subEntities().empty()) { + EntityWrapperPtr aSubMaster = theMaster->subEntities().empty() ? + theMaster : theMaster->subEntities().front(); + EntityWrapperPtr aSubSlave = theSlave->subEntities().empty() ? + theSlave : theSlave->subEntities().front(); + return addCoincidentPoints(aSubMaster, aSubSlave); + } // Search available coincidence CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(theMaster); CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(theSlave); - if (aMasterFound == myCoincidentPoints.end() && aSlaveFound == myCoincidentPoints.end()) { + if (aMasterFound == myCoincidentPoints.end() || aSlaveFound == myCoincidentPoints.end()) { // try to find master and slave points in the lists of slaves of already existent coincidences CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin(); for (; anIt != myCoincidentPoints.end(); ++anIt) { @@ -318,9 +344,9 @@ void SolveSpaceSolver_Storage::addCoincidentPoints( if (theMaster->id() != theSlave->id()) removeEntity((Slvs_hEntity)theSlave->id()); - std::shared_ptr aPointMaster = + std::shared_ptr aPointMaster = std::dynamic_pointer_cast(theMaster); - std::shared_ptr aPointSlave = + std::shared_ptr aPointSlave = std::dynamic_pointer_cast(theSlave); aPointSlave->changeEntity() = aPointMaster->entity(); aPointSlave->setParameters(aPointMaster->parameters()); @@ -392,6 +418,13 @@ void SolveSpaceSolver_Storage::replaceInConstraints( std::shared_ptr aWrapper = std::dynamic_pointer_cast(*aCIt); + if (theSource->id() == theDest->id()) { + // No need to update SolveSpace constraint if the entities are the same + aWrapper->changeConstraint() = getConstraint((Slvs_hConstraint)aWrapper->id()); + aWrapper->setEntities(aSubs); + continue; + } + // change constraint entities Slvs_Constraint aConstr = aWrapper->constraint(); if (aConstr.ptA == (Slvs_hEntity)theSource->id()) @@ -407,8 +440,14 @@ void SolveSpaceSolver_Storage::replaceInConstraints( aConstr.ptA == aSlvsCIt->ptA && aConstr.ptB == aSlvsCIt->ptB && aConstr.entityA == aSlvsCIt->entityA && aConstr.entityB == aSlvsCIt->entityB && aConstr.entityC == aSlvsCIt->entityC && aConstr.entityD == aSlvsCIt->entityD) { - removeConstraint(aConstr.h); + Slvs_hConstraint anIDToRemove = aConstr.h; aConstr = *aSlvsCIt; + int aShift = (int)(aSlvsCIt - myConstraints.begin()); + removeConstraint(anIDToRemove); + aSlvsCIt = myConstraints.begin() + aShift - 1; + for (; aSlvsCIt != myConstraints.end(); ++aSlvsCIt) + if (aSlvsCIt->h == aConstr.h) + break; break; } @@ -423,7 +462,7 @@ void SolveSpaceSolver_Storage::replaceInConstraints( addSameConstraints(*aCIt2, aWrapper); break; } - } else + } else aConstr.h = updateConstraint(aConstr); aWrapper->changeConstraint() = aConstr; @@ -473,8 +512,8 @@ bool SolveSpaceSolver_Storage::findSameConstraint(ConstraintWrapperPtr theConstr (*aCWIt)->type() == CONSTRAINT_MULTI_TRANSLATION) continue; if ((*aCWIt)->type() == theConstraint->type()) { - const Slvs_Constraint& aCComp = std::dynamic_pointer_cast< - SolveSpaceSolver_ConstraintWrapper>(*aCWIt)->constraint(); + const Slvs_Constraint& aCComp = getConstraint((Slvs_hConstraint)(*aCWIt)->id()); + if (aCBase.ptA == aCComp.ptA && aCBase.ptB == aCComp.ptB && aCBase.entityA == aCComp.entityA && aCBase.entityB == aCComp.entityB && aCBase.entityC == aCComp.entityC && aCBase.entityD == aCComp.entityD && @@ -533,8 +572,10 @@ EntityWrapperPtr SolveSpaceSolver_Storage::calculateMiddlePoint( theX = anArcPoint[0][0] + anArcPoint[2][0]; theY = anArcPoint[0][1] + anArcPoint[2][1]; } else { - std::shared_ptr aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1])); - std::shared_ptr aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1])); + std::shared_ptr + aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1])); + std::shared_ptr + aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1])); double anAngle = aStartDir->angle(aEndDir); if (anAngle < 0) anAngle += 2.0 * PI; @@ -595,10 +636,8 @@ Slvs_hParam SolveSpaceSolver_Storage::updateParameter(const Slvs_Param& theParam // parameter already used, rewrite it int aPos = Search(theParam.h, myParameters); if (aPos >= 0 && aPos < (int)myParameters.size()) { - if (IsNotEqual(myParameters[aPos], theParam)) { - myUpdatedParameters.insert(theParam.h); + if (IsNotEqual(myParameters[aPos], theParam)) setNeedToResolve(true); - } myParameters[aPos] = theParam; return theParam.h; } @@ -713,7 +752,7 @@ bool SolveSpaceSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID) myEntities.erase(myEntities.begin() + aPos); myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h; if (anEntity.distance != SLVS_E_UNKNOWN) - aResult = aResult && removeParameter(anEntity.distance); + aResult = aResult && removeEntity(anEntity.distance); for (int i = 0; i < 4; i++) if (anEntity.param[i] != SLVS_E_UNKNOWN) aResult = removeParameter(anEntity.param[i]) && aResult; @@ -722,105 +761,6 @@ bool SolveSpaceSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID) return aResult; } -void SolveSpaceSolver_Storage::removeUnusedEntities() -{ - std::set anUnusedEntities; - std::vector::const_iterator aEIt = myEntities.begin(); - for (; aEIt != myEntities.end(); ++aEIt) { - if (aEIt->h == aEIt->wrkpl) { - // don't remove workplane - anUnusedEntities.erase(aEIt->point[0]); - anUnusedEntities.erase(aEIt->normal); - continue; - } - anUnusedEntities.insert(aEIt->h); - } - - std::vector::const_iterator aCIt = myConstraints.begin(); - for (; aCIt != myConstraints.end(); ++aCIt) { - Slvs_hEntity aSubs[6] = { - aCIt->entityA, aCIt->entityB, - aCIt->entityC, aCIt->entityD, - aCIt->ptA, aCIt->ptB}; - for (int i = 0; i < 6; i++) { - if (aSubs[i] != SLVS_E_UNKNOWN) { - anUnusedEntities.erase(aSubs[i]); - int aPos = Search(aSubs[i], myEntities); - if (aPos >= 0 && aPos < (int)myEntities.size()) { - for (int j = 0; j < 4; j++) - if (myEntities[aPos].point[j] != SLVS_E_UNKNOWN) - anUnusedEntities.erase(myEntities[aPos].point[j]); - if (myEntities[aPos].distance != SLVS_E_UNKNOWN) - anUnusedEntities.erase(myEntities[aPos].distance); - } - } - } - } - - std::set::const_iterator anEntIt = anUnusedEntities.begin(); - while (anEntIt != anUnusedEntities.end()) { - int aPos = Search(*anEntIt, myEntities); - if (aPos < 0 && aPos >= (int)myEntities.size()) - continue; - Slvs_Entity anEntity = myEntities[aPos]; - // Remove entity if and only if all its parameters unused - bool isUsed = false; - if (anEntity.distance != SLVS_E_UNKNOWN && - anUnusedEntities.find(anEntity.distance) == anUnusedEntities.end()) - isUsed = true; - for (int i = 0; i < 4 && !isUsed; i++) - if (anEntity.point[i] != SLVS_E_UNKNOWN && - anUnusedEntities.find(anEntity.point[i]) == anUnusedEntities.end()) - isUsed = true; - if (isUsed) { - anUnusedEntities.erase(anEntity.distance); - for (int i = 0; i < 4; i++) - if (anEntity.point[i] != SLVS_E_UNKNOWN) - anUnusedEntities.erase(anEntity.point[i]); - std::set::iterator aRemoveIt = anEntIt++; - anUnusedEntities.erase(aRemoveIt); - continue; - } - ++anEntIt; - } - - for (anEntIt = anUnusedEntities.begin(); anEntIt != anUnusedEntities.end(); ++anEntIt) { - int aPos = Search(*anEntIt, myEntities); - if (aPos >= 0 && aPos < (int)myEntities.size()) { - // Remove entity and its parameters - Slvs_Entity anEntity = myEntities[aPos]; - myEntities.erase(myEntities.begin() + aPos); - myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h; - if (anEntity.distance != SLVS_E_UNKNOWN) - removeParameter(anEntity.distance); - for (int i = 0; i < 4; i++) - if (anEntity.param[i] != SLVS_E_UNKNOWN) - removeParameter(anEntity.param[i]); - for (int i = 0; i < 4; i++) - if (anEntity.point[i] != SLVS_E_UNKNOWN) - removeEntity(anEntity.point[i]); - } - } - - if (!anUnusedEntities.empty()) - myNeedToResolve = true; -} - -bool SolveSpaceSolver_Storage::isUsedByConstraints(const Slvs_hEntity& theEntityID) const -{ - std::vector::const_iterator aCIt = myConstraints.begin(); - for (; aCIt != myConstraints.end(); ++aCIt) { - Slvs_hEntity aSubs[6] = { - aCIt->entityA, aCIt->entityB, - aCIt->entityC, aCIt->entityD, - aCIt->ptA, aCIt->ptB}; - for (int i = 0; i < 6; i++) - if (aSubs[i] != SLVS_E_UNKNOWN && aSubs[i] == theEntityID) - return true; - } - return false; -} - const Slvs_Entity& SolveSpaceSolver_Storage::getEntity(const Slvs_hEntity& theEntityID) const { int aPos = Search(theEntityID, myEntities); @@ -833,220 +773,6 @@ const Slvs_Entity& SolveSpaceSolver_Storage::getEntity(const Slvs_hEntity& theEn return aDummy; } -Slvs_hEntity SolveSpaceSolver_Storage::copyEntity(const Slvs_hEntity& theCopied) -{ - int aPos = Search(theCopied, myEntities); - if (aPos < 0 || aPos >= (int)myEntities.size()) - return SLVS_E_UNKNOWN; - - Slvs_Entity aCopy = myEntities[aPos]; - aCopy.h = SLVS_E_UNKNOWN; - int i = 0; - while (aCopy.point[i] != SLVS_E_UNKNOWN) { - aCopy.point[i] = copyEntity(aCopy.point[i]); - i++; - } - if (aCopy.param[0] != SLVS_E_UNKNOWN) { - aPos = Search(aCopy.param[0], myParameters); - i = 0; - while (aCopy.param[i] != SLVS_E_UNKNOWN) { - Slvs_Param aNewParam = myParameters[aPos]; - aNewParam.h = SLVS_E_UNKNOWN; - aCopy.param[i] = addParameter(aNewParam); - i++; - aPos++; - } - } - return addEntity(aCopy); -} - -void SolveSpaceSolver_Storage::copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo) -{ - int aPosFrom = Search(theFrom, myEntities); - int aPosTo = Search(theTo, myEntities); - if (aPosFrom < 0 || aPosFrom >= (int)myEntities.size() || - aPosTo < 0 || aPosTo >= (int)myEntities.size()) - return; - - Slvs_Entity aEntFrom = myEntities[aPosFrom]; - Slvs_Entity aEntTo = myEntities[aPosTo]; - int i = 0; - while (aEntFrom.point[i] != SLVS_E_UNKNOWN) { - copyEntity(aEntFrom.point[i], aEntTo.point[i]); - i++; - } - if (aEntFrom.param[0] != SLVS_E_UNKNOWN) { - aPosFrom = Search(aEntFrom.param[0], myParameters); - aPosTo = Search(aEntTo.param[0], myParameters); - i = 0; - while (aEntFrom.param[i] != SLVS_E_UNKNOWN) { - myParameters[aPosTo++].val = myParameters[aPosFrom++].val; - i++; - } - } -} - - -bool SolveSpaceSolver_Storage::isPointFixed( - const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate) const -{ - // Search the set of coincident points - std::set aCoincident; - aCoincident.insert(thePointID); - - // Check whether one of coincident points is out-of-group - std::set::const_iterator aCoincIt = aCoincident.begin(); - for (; aCoincIt != aCoincident.end(); ++aCoincIt) { - Slvs_Entity aPoint = getEntity(*aCoincIt); - if (aPoint.group == SLVS_G_OUTOFGROUP) - return true; - } - - // Search the Rigid constraint - theFixed = SLVS_C_UNKNOWN; - std::vector::const_iterator aConstrIter = myConstraints.begin(); - for (; aConstrIter != myConstraints.end(); aConstrIter++) - if (aConstrIter->type == SLVS_C_WHERE_DRAGGED && - aCoincident.find(aConstrIter->ptA) != aCoincident.end()) { - theFixed = aConstrIter->h; - if (aConstrIter->ptA == thePointID) - return true; - } - if (theFixed != SLVS_C_UNKNOWN) - return true; - - if (theAccurate) { - // Try to find the fixed entity which uses such point or its coincidence - std::vector::const_iterator anEntIter = myEntities.begin(); - for (; anEntIter != myEntities.end(); anEntIter++) { - for (int i = 0; i < 4; i++) { - Slvs_hEntity aPt = anEntIter->point[i]; - if (aPt != SLVS_E_UNKNOWN && - (aPt == thePointID || aCoincident.find(aPt) != aCoincident.end())) { - if (isEntityFixed(anEntIter->h, true)) - return true; - } - } - } - } - return SLVS_E_UNKNOWN; -} - -bool SolveSpaceSolver_Storage::isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate) const -{ - int aPos = Search(theEntityID, myEntities); - if (aPos < 0 || aPos >= (int)myEntities.size()) - return false; - - // Firstly, find how many points are under Rigid constraint - int aNbFixed = 0; - for (int i = 0; i < 4; i++) { - Slvs_hEntity aPoint = myEntities[aPos].point[i]; - if (aPoint == SLVS_E_UNKNOWN) - continue; - - std::set aCoincident; - aCoincident.insert(aPoint); - - // Search the Rigid constraint - std::vector::const_iterator aConstrIter = myConstraints.begin(); - for (; aConstrIter != myConstraints.end(); aConstrIter++) - if (aConstrIter->type == SLVS_C_WHERE_DRAGGED && - aCoincident.find(aConstrIter->ptA) != aCoincident.end()) - aNbFixed++; - } - - std::list aList; - std::list::iterator anIt; - Slvs_hConstraint aTempID; // used in isPointFixed() method - - if (myEntities[aPos].type == SLVS_E_LINE_SEGMENT) { - if (aNbFixed == 2) - return true; - else if (aNbFixed == 0 || !theAccurate) - return false; - // Additional check (the line may be fixed if it is used by different constraints): - // 1. The line is used in Equal constraint, another entity is fixed and there is a fixed point on line - aList = getConstraintsByType(SLVS_C_PT_ON_LINE); - for (anIt = aList.begin(); anIt != aList.end(); anIt++) - if (anIt->entityA == theEntityID && isPointFixed(anIt->ptA, aTempID)) - break; - if (anIt != aList.end()) { - aList = getConstraintsByType(SLVS_C_EQUAL_LENGTH_LINES); - aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN)); - for (anIt = aList.begin(); anIt != aList.end(); anIt++) - if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) { - Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA; - if (isEntityFixed(anOther, false)) - return true; - } - } - // 2. The line is used in Parallel/Perpendicular/Vertical/Horizontal and Length constraints - aList = getConstraintsByType(SLVS_C_PARALLEL); - aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR)); - aList.splice(aList.end(), getConstraintsByType(SLVS_C_VERTICAL)); - aList.splice(aList.end(), getConstraintsByType(SLVS_C_HORIZONTAL)); - for (anIt = aList.begin(); anIt != aList.end(); anIt++) - if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) { - Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA; - if (isEntityFixed(anOther, false)) - break; - } - if (anIt != aList.end()) { - aList = getConstraintsByType(SLVS_C_PT_PT_DISTANCE); - for (anIt = aList.begin(); anIt != aList.end(); anIt++) - if ((anIt->ptA == myEntities[aPos].point[0] && anIt->ptB == myEntities[aPos].point[1]) || - (anIt->ptA == myEntities[aPos].point[1] && anIt->ptB == myEntities[aPos].point[0])) - return true; - } - // 3. Another verifiers ... - } else if (myEntities[aPos].type == SLVS_E_CIRCLE) { - if (aNbFixed == 0) - return false; - // Search for Diameter constraint - aList = getConstraintsByType(SLVS_C_DIAMETER); - for (anIt = aList.begin(); anIt != aList.end(); anIt++) - if (anIt->entityA == theEntityID) - return true; - if (!theAccurate) - return false; - // Additional check (the circle may be fixed if it is used by different constraints): - // 1. The circle is used in Equal constraint and another entity is fixed - aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS); - for (anIt = aList.begin(); anIt != aList.end(); anIt++) - if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) { - Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA; - if (isEntityFixed(anOther, false)) - return true; - } - // 2. Another verifiers ... - } else if (myEntities[aPos].type == SLVS_E_ARC_OF_CIRCLE) { - if (aNbFixed > 2) - return true; - else if (aNbFixed <= 1) - return false; - // Search for Diameter constraint - aList = getConstraintsByType(SLVS_C_DIAMETER); - for (anIt = aList.begin(); anIt != aList.end(); anIt++) - if (anIt->entityA == theEntityID) - return true; - if (!theAccurate) - return false; - // Additional check (the arc may be fixed if it is used by different constraints): - // 1. The arc is used in Equal constraint and another entity is fixed - aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS); - aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN)); - for (anIt = aList.begin(); anIt != aList.end(); anIt++) - if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) { - Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA; - if (isEntityFixed(anOther, false)) - return true; - } - // 2. Another verifiers ... - } - return false; -} - Slvs_hConstraint SolveSpaceSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint) { @@ -1066,7 +792,7 @@ Slvs_hConstraint SolveSpaceSolver_Storage::addConstraint(const Slvs_Constraint& aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB && aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD) { myDuplicatedConstraint = true; - return aCIt->h; + break; } } @@ -1094,12 +820,35 @@ Slvs_hConstraint SolveSpaceSolver_Storage::updateConstraint(const Slvs_Constrain // Constraint is not found, add new one Slvs_Constraint aConstraint = theConstraint; aConstraint.h = 0; + + // Firstly, check middle-point constraint conflicts with point-on-line + if (aConstraint.type == SLVS_C_AT_MIDPOINT) { + std::vector::const_iterator anIt = myConstraints.begin(); + for (; anIt != myConstraints.end(); ++anIt) + if (anIt->type == SLVS_C_PT_ON_LINE && + anIt->ptA == aConstraint.ptA && + anIt->entityA == aConstraint.entityA) + break; + if (anIt != myConstraints.end()) { + // change the constraint to the lengths equality to avoid conflicts + Slvs_Entity aLine = getEntity(aConstraint.entityA); + Slvs_Entity aNewLine1 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID, + myWorkplaneID, aLine.point[0], aConstraint.ptA); + aNewLine1.h = addEntity(aNewLine1); + Slvs_Entity aNewLine2 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID, + myWorkplaneID, aLine.point[1], aConstraint.ptA); + aNewLine2.h = addEntity(aNewLine2); + aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID, + SLVS_C_EQUAL_LENGTH_LINES, + myWorkplaneID, 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aNewLine1.h, aNewLine2.h); + } + } + return addConstraint(aConstraint); } bool SolveSpaceSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstraintID) { - bool aResult = true; int aPos = Search(theConstraintID, myConstraints); if (aPos >= 0 && aPos < (int)myConstraints.size()) { Slvs_Constraint aConstraint = myConstraints[aPos]; @@ -1107,36 +856,26 @@ bool SolveSpaceSolver_Storage::removeConstraint(const Slvs_hConstraint& theConst myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h; myNeedToResolve = true; - // Remove all entities - Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB, - aConstraint.entityA, aConstraint.entityB, - aConstraint.entityC, aConstraint.entityD}; - for (int i = 0; i < 6; i++) - if (anEntities[i] != SLVS_E_UNKNOWN) - aResult = removeEntity(anEntities[i]) && aResult; - // remove temporary fixed point, if available - if (myFixed == theConstraintID) - myFixed = SLVS_E_UNKNOWN; if (myDuplicatedConstraint) { - // Check the duplicated constraints are still available - myDuplicatedConstraint = false; - std::vector::const_iterator anIt1 = myConstraints.begin(); - std::vector::const_iterator anIt2 = myConstraints.begin(); - for (; anIt1 != myConstraints.end() && !myDuplicatedConstraint; anIt1++) - for (anIt2 = anIt1+1; anIt2 != myConstraints.end() && !myDuplicatedConstraint; anIt2++) { - if (anIt1->type != anIt2->type) - continue; - if (anIt1->ptA == anIt2->ptA && anIt1->ptB == anIt2->ptB && - anIt1->entityA == anIt2->entityA && anIt1->entityB == anIt2->entityB && - anIt1->entityC == anIt2->entityC && anIt1->entityD == anIt2->entityD) - myDuplicatedConstraint = true; + // Find a constraint with same type uses same arguments + std::vector::iterator aCIt = myConstraints.begin(); + for (; aCIt != myConstraints.end(); aCIt++) { + if (aConstraint.type != aCIt->type) + continue; + if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB && + aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB && + aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD) { + myDuplicatedConstraint = false; + break; } + } } } - return aResult; + return true; } -const Slvs_Constraint& SolveSpaceSolver_Storage::getConstraint(const Slvs_hConstraint& theConstraintID) const +const Slvs_Constraint& SolveSpaceSolver_Storage:: + getConstraint(const Slvs_hConstraint& theConstraintID) const { int aPos = Search(theConstraintID, myConstraints); if (aPos >= 0 && aPos < (int)myConstraints.size()) @@ -1148,26 +887,6 @@ const Slvs_Constraint& SolveSpaceSolver_Storage::getConstraint(const Slvs_hConst return aDummy; } -std::list SolveSpaceSolver_Storage::getConstraintsByType(int theConstraintType) const -{ - std::list aResult; - std::vector::const_iterator aCIter = myConstraints.begin(); - for (; aCIter != myConstraints.end(); aCIter++) - if (aCIter->type == theConstraintType) - aResult.push_back(*aCIter); - return aResult; -} - - -void SolveSpaceSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID) -{ - if (myFixed != SLVS_E_UNKNOWN) - return; // the point is already fixed - int aPos = Search(theConstraintID, myConstraints); - if (aPos >= 0 && aPos < (int)myConstraints.size()) - myFixed = theConstraintID; -} - void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver) { @@ -1189,448 +908,39 @@ void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver) aSolver->setParameters(myParameters.data(), (int)myParameters.size()); aSolver->setEntities(myEntities.data(), (int)myEntities.size()); - - // Copy constraints excluding the fixed one - std::vector aConstraints = myConstraints; - if (myFixed != SLVS_E_UNKNOWN) { - Slvs_hEntity aFixedPoint = SLVS_E_UNKNOWN; - std::vector::iterator anIt = aConstraints.begin(); - for (; anIt != aConstraints.end(); anIt++) - if (anIt->h == myFixed) { - aFixedPoint = anIt->ptA; - aConstraints.erase(anIt); - break; - } - // set dragged parameters - int aPos = Search(aFixedPoint, myEntities); - aSolver->setDraggedParameters(myEntities[aPos].param); - } - aSolver->setConstraints(aConstraints.data(), (int)aConstraints.size()); -} - - -bool SolveSpaceSolver_Storage::isEqual( - const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const -{ - // 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() && - aEnt2Pos >= 0 && aEnt2Pos < (int)myEntities.size()) { - double aDist[2]; - int aParamPos; - for (int i = 0; i < 2; i++) { - aParamPos = Search(myEntities[aEnt1Pos].param[i], myParameters); - aDist[i] = myParameters[aParamPos].val; - aParamPos = Search(myEntities[aEnt2Pos].param[i], myParameters); - aDist[i] -= myParameters[aParamPos].val; - } - if (aDist[0] * aDist[0] + aDist[1] * aDist[1] < tolerance * tolerance) - return true; - } - return false; + aSolver->setConstraints(myConstraints.data(), (int)myConstraints.size()); } -std::vector SolveSpaceSolver_Storage::fixEntity(const Slvs_hEntity& theEntity) -{ - std::vector aNewConstraints; - - int aPos = Search(theEntity, myEntities); - if (aPos >= 0 && aPos < (int)myEntities.size()) { - switch (myEntities[aPos].type) { - case SLVS_E_POINT_IN_2D: - case SLVS_E_POINT_IN_3D: - fixPoint(myEntities[aPos], aNewConstraints); - break; - case SLVS_E_LINE_SEGMENT: - fixLine(myEntities[aPos], aNewConstraints); - break; - case SLVS_E_CIRCLE: - fixCircle(myEntities[aPos], aNewConstraints); - break; - case SLVS_E_ARC_OF_CIRCLE: - fixArc(myEntities[aPos], aNewConstraints); - break; - default: - break; - } - } - - return aNewConstraints; -} - -void SolveSpaceSolver_Storage::fixPoint(const Slvs_Entity& thePoint, - std::vector& theCreated) -{ - Slvs_Constraint aConstraint; - Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN; - bool isFixed = isPointFixed(thePoint.h, aConstrID, true); - bool isForceUpdate = (isFixed /*&& isTemporary(aConstrID)*/); - if (!isForceUpdate) { // create new constraint - if (isFixed) return; - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl, - 0.0, thePoint.h, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); - aConstraint.h = addConstraint(aConstraint); - theCreated.push_back(aConstraint.h); - } else { // update already existent constraint - if (!isFixed || aConstrID == SLVS_E_UNKNOWN) - return; - int aPos = Search(aConstrID, myConstraints); - if (aPos >= 0 && aPos < (int)myConstraints.size()) - myConstraints[aPos].ptA = thePoint.h; - } -} - -void SolveSpaceSolver_Storage::fixLine(const Slvs_Entity& theLine, - std::vector& theCreated) -{ - Slvs_Entity aPoint[2] = { - getEntity(theLine.point[0]), - getEntity(theLine.point[1]) - }; - - Slvs_Constraint anEqual; - if (isAxisParallel(theLine.h)) { - // Fix one point and a line length - Slvs_hConstraint aFixed; - if (!isPointFixed(theLine.point[0], aFixed, true) && - !isPointFixed(theLine.point[1], aFixed, true)) - fixPoint(aPoint[0], theCreated); - if (!isUsedInEqual(theLine.h, anEqual)) { - // Check the distance is not set yet - std::vector::const_iterator aDistIt = myConstraints.begin(); - for (; aDistIt != myConstraints.end(); ++aDistIt) - if ((aDistIt->type == SLVS_C_PT_PT_DISTANCE) && - ((aDistIt->ptA == theLine.point[0] && aDistIt->ptB == theLine.point[1]) || - (aDistIt->ptA == theLine.point[1] && aDistIt->ptB == theLine.point[0]))) - return; - // Calculate distance between points on the line - double aCoords[4]; - for (int i = 0; i < 2; i++) - for (int j = 0; j < 2; j++) { - Slvs_Param aParam = getParameter(aPoint[i].param[j]); - aCoords[2*i+j] = aParam.val; - } - - double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) + - (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1])); - // fix line length - Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group, - SLVS_C_PT_PT_DISTANCE, theLine.wrkpl, aLength, - theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); - aDistance.h = addConstraint(aDistance); - theCreated.push_back(aDistance.h); - } - return; - } - else if (isUsedInEqual(theLine.h, anEqual)) { - // Check another entity of Equal is already fixed - Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA; - if (isEntityFixed(anOtherEntID, true)) { - // Fix start point of the line (if end point is not fixed yet) ... - Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN; - bool isFixed = isPointFixed(theLine.point[1], anEndFixedID, true); - if (isFixed == SLVS_E_UNKNOWN) - fixPoint(aPoint[0], theCreated); - // ... and create fixed point lying on this line - Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0]; - // Firstly, search already fixed point on line - bool isPonLineFixed = false; - Slvs_hEntity aFixedPoint; - std::vector::const_iterator aPLIter = myConstraints.begin(); - for (; aPLIter != myConstraints.end() && !isPonLineFixed; ++aPLIter) - if (aPLIter->type == SLVS_C_PT_ON_LINE && aPLIter->entityA == theLine.h) { - isPonLineFixed = isPointFixed(aPLIter->ptA, anEndFixedID); - aFixedPoint = aPLIter->ptA; - } - - if (isPonLineFixed) { // update existent constraint - copyEntity(aPointToCopy, aFixedPoint); - } else { // create new constraint - Slvs_hEntity aCopied = copyEntity(aPointToCopy); - Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group, SLVS_C_PT_ON_LINE, - theLine.wrkpl, 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN); - aPonLine.h = addConstraint(aPonLine); - theCreated.push_back(aPonLine.h); - fixPoint(getEntity(aCopied), theCreated); - } - return; - } - } - - // Fix both points - for (int i = 0; i < 2; i++) - fixPoint(aPoint[i], theCreated); -} - -void SolveSpaceSolver_Storage::fixCircle(const Slvs_Entity& theCircle, - std::vector& theCreated) -{ - bool isFixRadius = true; - // Verify the arc is under Equal constraint - Slvs_Constraint anEqual; - if (isUsedInEqual(theCircle.h, anEqual)) { - // Check another entity of Equal is already fixed - Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA; - if (isEntityFixed(anOtherEntID, true)) - isFixRadius = false; - } - - fixPoint(getEntity(theCircle.point[0]), theCreated); - - if (isFixRadius) { - // Search the radius is already fixed - std::vector::const_iterator aDiamIter = myConstraints.begin(); - for (; aDiamIter != myConstraints.end(); ++aDiamIter) - if (aDiamIter->type == SLVS_C_DIAMETER && aDiamIter->entityA == theCircle.h) - return; - - // Fix radius of a circle - const Slvs_Entity& aRadEnt = getEntity(theCircle.distance); - double aRadius = getParameter(aRadEnt.param[0]).val; - Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theCircle.group, SLVS_C_DIAMETER, - theCircle.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theCircle.h, SLVS_E_UNKNOWN); - aFixedR.h = addConstraint(aFixedR); - theCreated.push_back(aFixedR.h); - } -} - -void SolveSpaceSolver_Storage::fixArc(const Slvs_Entity& theArc, - std::vector& theCreated) -{ - Slvs_Entity aPoint[3] = { - getEntity(theArc.point[0]), - getEntity(theArc.point[1]), - getEntity(theArc.point[2]) - }; - - bool isFixRadius = true; - std::list aPointsToFix; - aPointsToFix.push_back(aPoint[1]); - aPointsToFix.push_back(aPoint[2]); - - // Verify the arc is under Equal constraint - Slvs_Constraint anEqual; - if (isUsedInEqual(theArc.h, anEqual)) { - // Check another entity of Equal is already fixed - Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA; - if (isEntityFixed(anOtherEntID, true)) { - isFixRadius = false; - Slvs_Entity anOtherEntity = getEntity(anOtherEntID); - if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) { - aPointsToFix.pop_back(); - aPointsToFix.push_back(aPoint[0]); - } - } - } - - Slvs_hConstraint aConstrID; - int aNbPointsToFix = 2; // number of fixed points for the arc - if (isPointFixed(theArc.point[0], aConstrID, true)) - aNbPointsToFix--; - - double anArcPoints[3][2]; - for (int i = 0; i < 3; i++) { - const Slvs_Entity& aPointOnArc = getEntity(theArc.point[i]); - for (int j = 0; j < 2; j++) - anArcPoints[i][j] = getParameter(aPointOnArc.param[j]).val; - } - - // Radius of the arc - std::shared_ptr aCenter(new GeomAPI_Pnt2d(anArcPoints[0][0], anArcPoints[0][1])); - std::shared_ptr aStart(new GeomAPI_Pnt2d(anArcPoints[1][0], anArcPoints[1][1])); - double aRadius = aCenter->distance(aStart); - - // Update end point of the arc to be on a curve - std::shared_ptr anEnd(new GeomAPI_Pnt2d(anArcPoints[2][0], anArcPoints[2][1])); - double aDistance = anEnd->distance(aCenter); - std::shared_ptr aDir = anEnd->xy()->decreased(aCenter->xy()); - if (aDistance < tolerance) - aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0); - else - aDir = aDir->multiplied(aRadius / aDistance); - double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()}; - const Slvs_Entity& aEndPoint = getEntity(theArc.point[2]); - for (int i = 0; i < 2; i++) { - Slvs_Param aParam = getParameter(aEndPoint.param[i]); - aParam.val = xy[i]; - updateParameter(aParam); - } - - std::list::iterator aPtIt = aPointsToFix.begin(); - for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--) - fixPoint(*aPtIt, theCreated); - - if (isFixRadius) { - // Fix radius of the arc - bool isExists = false; - std::vector::iterator anIt = myConstraints.begin(); - for (; anIt != myConstraints.end() && !isExists; ++anIt) - if (anIt->type == SLVS_C_DIAMETER && anIt->entityA == theArc.h) - isExists = true; - if (!isExists) { - Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theArc.group, SLVS_C_DIAMETER, - theArc.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theArc.h, SLVS_E_UNKNOWN); - aFixedR.h = addConstraint(aFixedR); - theCreated.push_back(aFixedR.h); - } - } -} - - -bool SolveSpaceSolver_Storage::isAxisParallel(const Slvs_hEntity& theEntity) const -{ - std::vector::const_iterator anIter = myConstraints.begin(); - for (; anIter != myConstraints.end(); anIter++) - if ((anIter->type == SLVS_C_HORIZONTAL || anIter->type == SLVS_C_VERTICAL) && - anIter->entityA == theEntity) - return true; - return false; -} - -bool SolveSpaceSolver_Storage::isUsedInEqual( - const Slvs_hEntity& theEntity, Slvs_Constraint& theEqual) const -{ - // Check the entity is used in Equal constraint - std::vector::const_iterator anEqIter = myConstraints.begin(); - for (; anEqIter != myConstraints.end(); anEqIter++) - if ((anEqIter->type == SLVS_C_EQUAL_LENGTH_LINES || - anEqIter->type == SLVS_C_EQUAL_LINE_ARC_LEN || - anEqIter->type == SLVS_C_EQUAL_RADIUS) && - (anEqIter->entityA == theEntity || anEqIter->entityB == theEntity)) { - theEqual = *anEqIter; - return true; - } - return false; -} - - -bool SolveSpaceSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint) -{ - std::list aPoints = theConstraint->entities(); - std::list::const_iterator aPIt; - - CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin(); - for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) { - for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt) - if (aPtPtIt->first == *aPIt || - aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end()) - break; - if (aPIt != aPoints.end()) - break; - } - - if (aPtPtIt == myCoincidentPoints.end()) - return true; // already removed - - // Create new copies of coincident points - BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance(); - std::list aNewPoints; - for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt) - aNewPoints.push_back(aBuilder->createAttribute( - (*aPIt)->baseAttribute(), myGroupID, myWorkplaneID)); - - // Find all points fallen out of group of coincident points - std::map aNotCoinc; - aNotCoinc[aPtPtIt->first] = EntityWrapperPtr(); - std::set::const_iterator aTempIt = aPtPtIt->second.begin(); - for (; aTempIt != aPtPtIt->second.end(); ++aTempIt) - aNotCoinc[*aTempIt] = EntityWrapperPtr(); - std::map >::iterator - aConstrIt = myConstraintMap.begin(); - for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) - if (aConstrIt->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { - AttributeRefAttrPtr aRefAttrA = std::dynamic_pointer_cast( - aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast( - aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_B())); - if (!aRefAttrA || !aRefAttrB || aRefAttrA->isObject() || aRefAttrB->isObject()) - continue; - std::map::iterator - aFound = myAttributeMap.find(aRefAttrA->attr()); - if (aFound != myAttributeMap.end()) - aNotCoinc.erase(aFound->second); - aFound = myAttributeMap.find(aRefAttrB->attr()); - if (aFound != myAttributeMap.end()) - aNotCoinc.erase(aFound->second); - } - if (aNotCoinc.empty()) - return false; - std::list::const_iterator aNewPIt; - for (aPIt = aPoints.begin(), aNewPIt = aNewPoints.begin(); - aPIt != aPoints.end(); ++aPIt, ++aNewPIt) { - if (aNotCoinc.find(*aPIt) != aNotCoinc.end()) - aNotCoinc[*aPIt] = *aNewPIt; - } - - // Find all features and constraints uses coincident points - std::map::iterator aNotCIt; - std::set anUpdFeatures; - std::map::iterator aFIt = myFeatureMap.begin(); - for (; aFIt != myFeatureMap.end(); ++aFIt) { - for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) { - if (!aNotCIt->second || !aFIt->second->isUsed(aNotCIt->first->baseAttribute())) - continue; - std::list aSubs = aFIt->second->subEntities(); - std::list::iterator aSIt = aSubs.begin(); - bool isUpd = false; - for (; aSIt != aSubs.end(); ++aSIt) - if (*aSIt == aNotCIt->first) { - *aSIt = aNotCIt->second; - isUpd = true; - } - if (isUpd) { - aFIt->second->setSubEntities(aSubs); - anUpdFeatures.insert(aFIt->second); - } - } - } - // update features - std::set::iterator anUpdIt = anUpdFeatures.begin(); - for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt) - update(EntityWrapperPtr(*anUpdIt)); - - // remove not coincident points - for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) { - if (aPtPtIt->second.size() <= 1) { - myCoincidentPoints.erase(aPtPtIt); - break; - } - if (aPtPtIt->first == aNotCIt->first) { - std::set aSlaves = aPtPtIt->second; - EntityWrapperPtr aNewMaster = *aSlaves.begin(); - aSlaves.erase(aSlaves.begin()); - myCoincidentPoints.erase(aPtPtIt); - myCoincidentPoints[aNewMaster] = aSlaves; - aPtPtIt = myCoincidentPoints.find(aNewMaster); - } else - aPtPtIt->second.erase(aNotCIt->first); - } - return true; -} - bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint) { std::shared_ptr aConstraint = std::dynamic_pointer_cast(theConstraint); // verify whether the constraint has duplicated + bool hasSameID = false; SameConstraintMap::iterator anEqIt = myEqualConstraints.begin(); - for (; anEqIt != myEqualConstraints.end(); ++anEqIt) - if (anEqIt->find(aConstraint) != anEqIt->end()) { + for (; anEqIt != myEqualConstraints.end(); ++anEqIt) { + std::set::const_iterator aFound = anEqIt->find(aConstraint); + if (aFound != anEqIt->end()) { + // verify there is a constraint with same ID + std::set::const_iterator anIt = anEqIt->begin(); + ConstraintID anID = (*aFound)->id(); + for (++anIt; anIt != anEqIt->end() && !hasSameID; ++anIt) + if ((*anIt)->id() == anID && aFound != anIt) + hasSameID = true; + // erase constraint anEqIt->erase(aConstraint); break; } - if (anEqIt != myEqualConstraints.end()) + } + if (anEqIt != myEqualConstraints.end() && hasSameID) return true; bool isFullyRemoved = removeConstraint((Slvs_hConstraint)aConstraint->id()); - // remove point-point coincidence if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT) - isFullyRemoved = removeCoincidence(theConstraint); - + isFullyRemoved = removeCoincidence(theConstraint) && isFullyRemoved; return SketchSolver_Storage::remove(theConstraint) && isFullyRemoved; } @@ -1639,10 +949,33 @@ bool SolveSpaceSolver_Storage::remove(EntityWrapperPtr theEntity) if (!theEntity) return false; - std::shared_ptr anEntity = + // Additional check for entity to be used in point-point coincidence + bool isCoincide = false; + if (theEntity->type() == ENTITY_POINT) { + CoincidentPointsMap::const_iterator anIt = myCoincidentPoints.begin(); + std::set::const_iterator aCIt; + for (; anIt != myCoincidentPoints.end(); ++anIt) { + if (anIt->first == theEntity) + break; + for (aCIt = anIt->second.begin(); aCIt != anIt->second.end(); ++aCIt) + if (*aCIt == theEntity) + break; + if (aCIt != anIt->second.end()) + break; + } + if (anIt != myCoincidentPoints.end()) { + if (anIt->first != theEntity && isUsed(anIt->first->baseAttribute())) + isCoincide = true; + for (aCIt = anIt->second.begin(); !isCoincide && aCIt != anIt->second.end(); ++aCIt) + if (*aCIt != theEntity && isUsed((*aCIt)->baseAttribute())) + isCoincide = true; + } + } + + std::shared_ptr anEntity = std::dynamic_pointer_cast(theEntity); - bool isFullyRemoved = removeEntity((Slvs_hEntity)anEntity->id()); - return SketchSolver_Storage::remove(theEntity) && isFullyRemoved; + bool isFullyRemoved = isCoincide ? true : removeEntity((Slvs_hEntity)anEntity->id()); + return (SketchSolver_Storage::remove(theEntity) || isCoincide) && isFullyRemoved; } bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter) @@ -1661,10 +994,10 @@ void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const for (; anIt != myAttributeMap.end(); ++anIt) { if (!anIt->second) continue; - // the external feature always should keep the up to date values, so, + // the external feature always should keep the up to date values, so, // refresh from the solver is never needed if (anIt->first.get()) { - std::shared_ptr aSketchFeature = + std::shared_ptr aSketchFeature = std::dynamic_pointer_cast(anIt->first->owner()); if (aSketchFeature.get() && aSketchFeature->isExternal()) continue; @@ -1681,7 +1014,7 @@ void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const bool isUpd[3] = {false}; int i = 0; for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) { - std::shared_ptr aWrapper = + std::shared_ptr aWrapper = std::dynamic_pointer_cast(*aParIt); if (!theFixedOnly || aWrapper->group() == GID_OUTOFGROUP || aWrapper->isParametric()) { aWrapper->changeParameter().val = getParameter((Slvs_hParam)aWrapper->id()).val; @@ -1702,7 +1035,7 @@ void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const aPoint2D->setValue(aCoords[0], aCoords[1]); // Find points coincident with this one (probably not in GID_OUTOFGROUP) std::map::const_iterator aLocIt; - if (theFixedOnly) + if (theFixedOnly) aLocIt = myAttributeMap.begin(); else { aLocIt = anIt; @@ -1711,7 +1044,7 @@ void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const for (; aLocIt != myAttributeMap.end(); ++aLocIt) { if (!aLocIt->second) continue; - std::shared_ptr aSketchFeature = + std::shared_ptr aSketchFeature = std::dynamic_pointer_cast(aLocIt->first->owner()); if (aSketchFeature && aSketchFeature->isExternal()) continue; @@ -1752,10 +1085,17 @@ void SolveSpaceSolver_Storage::verifyFixed() for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) { if (!anAttrIt->second) continue; + if (anAttrIt->second->group() == GID_OUTOFGROUP) { + Slvs_Entity anEnt = getEntity((Slvs_hEntity)anAttrIt->second->id()); + if (anEnt.group != (Slvs_hEntity)GID_OUTOFGROUP) + anEnt.group = (Slvs_hEntity)GID_OUTOFGROUP; + updateEntity(anEnt); + } + const std::list& aParameters = anAttrIt->second->parameters(); std::list::const_iterator aParIt = aParameters.begin(); for (; aParIt != aParameters.end(); ++aParIt) - if ((*aParIt)->group() == GID_OUTOFGROUP) { + if (anAttrIt->second->group() == GID_OUTOFGROUP || (*aParIt)->group() == GID_OUTOFGROUP) { Slvs_Param aParam = getParameter((Slvs_hParam)(*aParIt)->id()); if (aParam.group != (Slvs_hParam)GID_OUTOFGROUP) { aParam.group = (Slvs_hParam)GID_OUTOFGROUP; @@ -1779,7 +1119,7 @@ void SolveSpaceSolver_Storage::adjustArc(const Slvs_Entity& theArc) if (i > 0) { anArcPoints[i][0] -= anArcPoints[0][0]; anArcPoints[i][1] -= anArcPoints[0][1]; - aDist[i] = sqrt(anArcPoints[i][0] * anArcPoints[i][0] + + aDist[i] = sqrt(anArcPoints[i][0] * anArcPoints[i][0] + anArcPoints[i][1] * anArcPoints[i][1]); } } @@ -1818,7 +1158,7 @@ template int Search(const uint32_t& theEntityID, const std::vector& theEntities) { int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0; - int aVecSize = theEntities.size(); + int aVecSize = (int)theEntities.size(); if (theEntities.empty()) return 1; while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)