X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintGroup.cpp;h=1b1a621c251d6a46d114c6a4baf646aa5b77ade7;hb=7b95df2653284e65f416373ff010af49ee8c68ef;hp=df7b1614ec6fde25b838f82e8c7534618622732e;hpb=48c3e20e2f0d7a3608a92cb36c5965c521db7127;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp index df7b1614e..1b1a621c2 100644 --- a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp @@ -1,3 +1,5 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + // File: SketchSolver_ConstraintGroup.cpp // Created: 27 May 2014 // Author: Artem ZHIDKOV @@ -9,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +24,7 @@ #include #include #include +#include #include #include @@ -34,11 +38,11 @@ /// Tolerance for value of parameters const double tolerance = 1.e-10; -/* +/** * Collects all sketch solver error' codes * as inline static functions - * TODO: Move this class into a separate file */ + // TODO: Move this class into a separate file class SketchSolver_Error { public: @@ -66,7 +70,7 @@ static int Search(const uint32_t& theEntityID, const std::vector& theEntities // ======================================================== SketchSolver_ConstraintGroup::SketchSolver_ConstraintGroup( - boost::shared_ptr theWorkplane) + std::shared_ptr theWorkplane) : myID(++myGroupIndexer), myParamMaxID(0), myEntityMaxID(0), @@ -77,6 +81,7 @@ SketchSolver_ConstraintGroup::SketchSolver_ConstraintGroup( { myParams.clear(); myEntities.clear(); + myEntOfConstr.clear(); myConstraints.clear(); myTempConstraints.clear(); @@ -96,6 +101,7 @@ SketchSolver_ConstraintGroup::~SketchSolver_ConstraintGroup() { myParams.clear(); myEntities.clear(); + myEntOfConstr.clear(); myConstraints.clear(); myConstraintMap.clear(); myTempConstraints.clear(); @@ -112,7 +118,7 @@ SketchSolver_ConstraintGroup::~SketchSolver_ConstraintGroup() // Purpose: verify the group is based on the given workplane // ============================================================================ bool SketchSolver_ConstraintGroup::isBaseWorkplane( - boost::shared_ptr theWorkplane) const + std::shared_ptr theWorkplane) const { return theWorkplane == mySketch; } @@ -123,38 +129,46 @@ bool SketchSolver_ConstraintGroup::isBaseWorkplane( // Purpose: verify are there any entities in the group used by given constraint // ============================================================================ bool SketchSolver_ConstraintGroup::isInteract( - boost::shared_ptr theFeature) const + std::shared_ptr theFeature) const { // Check the group is empty if (isEmpty()) return true; + // Check if the feature is already in the group + if (myEntityFeatMap.find(theFeature) != myEntityFeatMap.end()) + return true; + std::shared_ptr aConstr = + std::dynamic_pointer_cast(theFeature); + if (aConstr && myConstraintMap.find(aConstr) != myConstraintMap.end()) + return true; + // Go through the attributes and verify if some of them already in the group - std::list> + std::list> anAttrList = theFeature->data()->attributes(std::string()); - std::list>::const_iterator + std::list>::const_iterator anAttrIter = anAttrList.begin(); for ( ; anAttrIter != anAttrList.end(); anAttrIter++) { - boost::shared_ptr aCAttrRef = - boost::dynamic_pointer_cast(*anAttrIter); + std::shared_ptr aCAttrRef = + std::dynamic_pointer_cast(*anAttrIter); if (!aCAttrRef || !aCAttrRef->isObject()) { - boost::shared_ptr anAttr = + std::shared_ptr anAttr = aCAttrRef ? aCAttrRef->attr() : *anAttrIter; if (myEntityAttrMap.find(anAttr) != myEntityAttrMap.end()) return true; } else { - ResultConstructionPtr aRC = boost::dynamic_pointer_cast( + ResultConstructionPtr aRC = std::dynamic_pointer_cast( aCAttrRef->object()); if (!aRC) continue; - boost::shared_ptr aDoc = aRC->document(); + std::shared_ptr aDoc = aRC->document(); FeaturePtr aFeature = aDoc->feature(aRC); if (myEntityFeatMap.find(aFeature) != myEntityFeatMap.end()) return true; // search attributes of a feature to be parameters of constraint - std::list > aFeatAttrList = + std::list > aFeatAttrList = aFeature->data()->attributes(std::string()); - std::list >::const_iterator aFAIter = aFeatAttrList + std::list >::const_iterator aFAIter = aFeatAttrList .begin(); for (; aFAIter != aFeatAttrList.end(); aFAIter++) if (myEntityAttrMap.find(*aFAIter) != myEntityAttrMap.end()) @@ -179,18 +193,18 @@ void SketchSolver_ConstraintGroup::checkConstraintConsistence(Slvs_Constraint& t // point coordinates int aPtPos = Search(theConstraint.ptA, myEntities); int aPtParamPos = Search(myEntities[aPtPos].param[0], myParams); - boost::shared_ptr aPoint( + std::shared_ptr aPoint( new GeomAPI_XY(myParams[aPtParamPos].val, myParams[aPtParamPos + 1].val)); // line coordinates int aLnPos = Search(theConstraint.entityA, myEntities); aPtPos = Search(myEntities[aLnPos].point[0], myEntities); aPtParamPos = Search(myEntities[aPtPos].param[0], myParams); - boost::shared_ptr aStart( + std::shared_ptr aStart( new GeomAPI_XY(-myParams[aPtParamPos].val, -myParams[aPtParamPos + 1].val)); aPtPos = Search(myEntities[aLnPos].point[1], myEntities); aPtParamPos = Search(myEntities[aPtPos].param[0], myParams); - boost::shared_ptr aEnd( + std::shared_ptr aEnd( new GeomAPI_XY(myParams[aPtParamPos].val, myParams[aPtParamPos + 1].val)); aEnd = aEnd->added(aStart); @@ -206,18 +220,20 @@ void SketchSolver_ConstraintGroup::checkConstraintConsistence(Slvs_Constraint& t // Purpose: create/update the constraint in the group // ============================================================================ bool SketchSolver_ConstraintGroup::changeConstraint( - boost::shared_ptr theConstraint) + std::shared_ptr theConstraint) { // There is no workplane yet, something wrong if (myWorkplane.h == SLVS_E_UNKNOWN) return false; + if (theConstraint && theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) + return changeRigidConstraint(theConstraint); + // Search this constraint in the current group to update it - std::map, Slvs_hConstraint>::const_iterator aConstrMapIter = - myConstraintMap.find(theConstraint); + ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint); std::vector::iterator aConstrIter; if (aConstrMapIter != myConstraintMap.end()) { - int aConstrPos = Search(aConstrMapIter->second, myConstraints); + int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints); aConstrIter = myConstraints.begin() + aConstrPos; } @@ -231,10 +247,14 @@ bool SketchSolver_ConstraintGroup::changeConstraint( // Create constraint parameters double aDistance = 0.0; // scalar value of the constraint - AttributeDoublePtr aDistAttr = boost::dynamic_pointer_cast( + AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast( theConstraint->data()->attribute(SketchPlugin_Constraint::VALUE())); if (aDistAttr) { aDistance = aDistAttr->value(); + // Issue #196: checking the positivity of the distance constraint + if (aDistance < tolerance && + (aConstrType == SLVS_C_PT_PT_DISTANCE || aConstrType == SLVS_C_PT_LINE_DISTANCE)) + return false; // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter if (aConstrType == SLVS_C_DIAMETER) aDistance *= 2.0; @@ -245,10 +265,11 @@ bool SketchSolver_ConstraintGroup::changeConstraint( } } + size_t aNbTmpConstraints = myTempConstraints.size(); Slvs_hEntity aConstrEnt[CONSTRAINT_ATTR_SIZE]; // parameters of the constraint for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { aConstrEnt[indAttr] = SLVS_E_UNKNOWN; - boost::shared_ptr aConstrAttr = boost::dynamic_pointer_cast< + std::shared_ptr aConstrAttr = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>( theConstraint->data()->attribute(aConstraintAttributes[indAttr])); if (!aConstrAttr) @@ -257,18 +278,18 @@ bool SketchSolver_ConstraintGroup::changeConstraint( // Convert the object of the attribute to the feature FeaturePtr aFeature; if (aConstrAttr->isObject() && aConstrAttr->object()) { - ResultConstructionPtr aRC = boost::dynamic_pointer_cast( + ResultConstructionPtr aRC = std::dynamic_pointer_cast( aConstrAttr->object()); if (!aRC) continue; - boost::shared_ptr aDoc = aRC->document(); + std::shared_ptr aDoc = aRC->document(); aFeature = aDoc->feature(aRC); } // For the length constraint the start and end points of the line should be added to the entities list instead of line if (aConstrType == SLVS_C_PT_PT_DISTANCE && theConstraint->getKind().compare(SketchPlugin_ConstraintLength::ID()) == 0) { - Slvs_hEntity aLineEnt = changeEntity(aFeature); + Slvs_hEntity aLineEnt = changeEntityFeature(aFeature); int aEntPos = Search(aLineEnt, myEntities); aConstrEnt[indAttr++] = myEntities[aEntPos].point[0]; aConstrEnt[indAttr++] = myEntities[aEntPos].point[1]; @@ -276,7 +297,7 @@ bool SketchSolver_ConstraintGroup::changeConstraint( aConstrEnt[indAttr++] = 0; break; // there should be no other entities } else if (aConstrAttr->isObject()) - aConstrEnt[indAttr] = changeEntity(aFeature); + aConstrEnt[indAttr] = changeEntityFeature(aFeature); else aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr()); } @@ -291,6 +312,44 @@ bool SketchSolver_ConstraintGroup::changeConstraint( myExtraCoincidence.insert(theConstraint); // the constraint is stored for further purposes return false; } + if (aNbTmpConstraints < myTempConstraints.size()) { + // There was added temporary constraint. Check that there is no coincident points which already rigid. + + // Get list of already fixed points + std::set anAlreadyFixed; + std::vector::const_iterator aCIter = myConstraints.begin(); + for (; aCIter != myConstraints.end(); aCIter++) + if (aCIter->type == SLVS_C_WHERE_DRAGGED) { + std::list::const_iterator aTmpIt = myTempConstraints.begin(); + for (; aTmpIt != myTempConstraints.end(); aTmpIt++) + if (*aTmpIt == aCIter->h) + break; + if (aTmpIt == myTempConstraints.end()) + anAlreadyFixed.insert(aCIter->ptA); + } + + std::set aTmpConstrToDelete; + std::list::reverse_iterator aTmpIter = myTempConstraints.rbegin(); + size_t aCurSize = myTempConstraints.size(); + for (; aCurSize > aNbTmpConstraints && aTmpIter != myTempConstraints.rend(); + aTmpIter++, aCurSize--) { + int aConstrPos = Search(*aTmpIter, myConstraints); + std::vector >::const_iterator + aCoincIter = myCoincidentPoints.begin(); + for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++) + if (aCoincIter->find(myConstraints[aConstrPos].ptA) != aCoincIter->end()) { + std::set::const_iterator anIt; + for (anIt = aCoincIter->begin(); anIt != aCoincIter->end(); anIt++) + if (anAlreadyFixed.find(*anIt) != anAlreadyFixed.end()) { + aTmpConstrToDelete.insert(*aTmpIter); + break; + } + break; + } + } + if (!aTmpConstrToDelete.empty()) + removeTemporaryConstraints(aTmpConstrToDelete); + } } // Create SolveSpace constraint structure @@ -298,7 +357,7 @@ bool SketchSolver_ConstraintGroup::changeConstraint( myWorkplane.h, aDistance, aConstrEnt[0], aConstrEnt[1], aConstrEnt[2], aConstrEnt[3]); myConstraints.push_back(aConstraint); - myConstraintMap[theConstraint] = aConstraint.h; + myConstraintMap[theConstraint] = std::vector(1, aConstraint.h); int aConstrPos = Search(aConstraint.h, myConstraints); aConstrIter = myConstraints.begin() + aConstrPos; myNeedToSolve = true; @@ -315,91 +374,273 @@ bool SketchSolver_ConstraintGroup::changeConstraint( } } + // Update flags of entities to be used by constraints + for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) + if (aConstrEnt[indAttr] != 0) { + int aPos = Search(aConstrEnt[indAttr], myEntities); + myEntOfConstr[aPos] = true; + // Sub-entities should be used implcitly + Slvs_hEntity* aEntPtr = myEntities[aPos].point; + while (*aEntPtr != 0) { + aPos = Search(*aEntPtr, myEntities); + myEntOfConstr[aPos] = true; + aEntPtr++; + } + } + checkConstraintConsistence(*aConstrIter); return true; } +// ============================================================================ +// Function: changeRigidConstraint +// Class: SketchSolver_ConstraintGroup +// Purpose: create/update the "Rigid" constraint in the group +// ============================================================================ +bool SketchSolver_ConstraintGroup::changeRigidConstraint( + std::shared_ptr theConstraint) +{ + // Search this constraint in the current group to update it + ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint); + std::vector::iterator aConstrIter; + if (aConstrMapIter != myConstraintMap.end()) { + int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints); + aConstrIter = myConstraints.begin() + aConstrPos; + } + + // Get constraint type and verify the constraint parameters are correct + SketchSolver_Constraint aConstraint(theConstraint); + int aConstrType = aConstraint.getType(); + if (aConstrType == SLVS_C_UNKNOWN + || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType)) + return false; + const std::vector& aConstraintAttributes = aConstraint.getAttributes(); + + Slvs_hEntity aConstrEnt = SLVS_E_UNKNOWN; + std::shared_ptr aConstrAttr = std::dynamic_pointer_cast< + ModelAPI_AttributeRefAttr>( + theConstraint->data()->attribute(aConstraintAttributes[0])); + if (!aConstrAttr) + return false; + + // Convert the object of the attribute to the feature + FeaturePtr aFeature; + if (aConstrAttr->isObject() && aConstrAttr->object()) { + ResultConstructionPtr aRC = std::dynamic_pointer_cast( + aConstrAttr->object()); + if (!aRC) + return false; + std::shared_ptr aDoc = aRC->document(); + aFeature = aDoc->feature(aRC); + } + + aConstrEnt = aConstrAttr->isObject() ? changeEntityFeature(aFeature) : changeEntity(aConstrAttr->attr()); + + if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint + // Check the fixed entity is not a point. + std::shared_ptr aConstrAttr = std::dynamic_pointer_cast< + ModelAPI_AttributeRefAttr>(theConstraint->data()->attribute(aConstraintAttributes[0])); + std::shared_ptr aPoint = + std::dynamic_pointer_cast(aConstrAttr->attr()); + std::shared_ptr aPoint2D = + std::dynamic_pointer_cast(aConstrAttr->attr()); + if (aPoint || aPoint2D) { + // Create SolveSpace constraint structure + Slvs_Constraint aConstraint = Slvs_MakeConstraint( + ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, + aConstrEnt, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + myConstraints.push_back(aConstraint); + myConstraintMap[theConstraint] = std::vector(1, aConstraint.h); + int aConstrPos = Search(aConstraint.h, myConstraints); + aConstrIter = myConstraints.begin() + aConstrPos; + myNeedToSolve = true; + } else { + myConstraintMap[theConstraint] = std::vector(); + + // To avoid SolveSpace problems: + // * if the circle is rigid, we will fix its center and radius; + // * if the arc is rigid, we will fix its start and end points and radius. + double aRadius = 0.0; + bool isArc = false; + bool isCircle = false; + if (aFeature) { + if (aFeature->getKind() == SketchPlugin_Arc::ID()) { + std::shared_ptr aCenter = + std::dynamic_pointer_cast( + aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID())); + std::shared_ptr aStart = + std::dynamic_pointer_cast( + aFeature->data()->attribute(SketchPlugin_Arc::START_ID())); + aRadius = aStart->pnt()->distance(aCenter->pnt()); + isArc = true; + } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) { + aRadius = std::dynamic_pointer_cast( + aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()))->value(); + isCircle = true; + } + } + + // Get list of already fixed points + std::set anAlreadyFixed; + std::vector::const_iterator aCIter = myConstraints.begin(); + for (; aCIter != myConstraints.end(); aCIter++) + if (aCIter->type == SLVS_C_WHERE_DRAGGED) + anAlreadyFixed.insert(aCIter->ptA); + + // Create constraints to fix the parameters of the entity + int aEntPos = Search(aConstrEnt, myEntities); + Slvs_hEntity* aPointsPtr = myEntities[aEntPos].point; + if (isArc) aPointsPtr++; // avoid to fix center of arc + while (*aPointsPtr != 0) { + // Avoid to create additional "Rigid" constraints for coincident points + bool isCoincAlreadyFixed = false; + if (!anAlreadyFixed.empty()) { + if (anAlreadyFixed.find(*aPointsPtr) != anAlreadyFixed.end()) + isCoincAlreadyFixed = true; + + std::vector >::const_iterator aCoincIter = + myCoincidentPoints.begin(); + for (; !isCoincAlreadyFixed && aCoincIter != myCoincidentPoints.end(); aCoincIter++) { + if (aCoincIter->find(*aPointsPtr) == aCoincIter->end()) + continue; + std::set::const_iterator anIter = anAlreadyFixed.begin(); + for (; !isCoincAlreadyFixed && anIter != anAlreadyFixed.end(); anIter++) + if (aCoincIter->find(*anIter) != aCoincIter->end()) + isCoincAlreadyFixed = true; + } + } + + if (!isCoincAlreadyFixed) { + Slvs_Constraint aConstraint = Slvs_MakeConstraint( + ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, + *aPointsPtr, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + myConstraints.push_back(aConstraint); + myConstraintMap[theConstraint].push_back(aConstraint.h); + } + aPointsPtr++; + } + + if (isArc || isCircle) { // add radius constraint + Slvs_Constraint aConstraint = Slvs_MakeConstraint( + ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, 2.0 * aRadius, + SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aConstrEnt, SLVS_E_UNKNOWN); + myConstraints.push_back(aConstraint); + myConstraintMap[theConstraint].push_back(aConstraint.h); + } + + // The object is already rigid, so there is no constraints added + if (myConstraintMap[theConstraint].empty()) { + myConstraintMap.erase(theConstraint); + myNeedToSolve = false; + } + else + myNeedToSolve = true; + } + } + return true; +} + // ============================================================================ // Function: changeEntity // Class: SketchSolver_ConstraintGroup // Purpose: create/update the element affected by any constraint // ============================================================================ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( - boost::shared_ptr theEntity) + std::shared_ptr theEntity) { // If the entity is already in the group, try to find it - std::map, Slvs_hEntity>::const_iterator aEntIter = + std::map, Slvs_hEntity>::const_iterator aEntIter = myEntityAttrMap.find(theEntity); + int aEntPos; std::vector::const_iterator aParamIter; // looks at first parameter of already existent entity or at the end of vector otherwise if (aEntIter == myEntityAttrMap.end()) // no such entity => should be created aParamIter = myParams.end(); else { // the entity already exists - int aEntPos = Search(aEntIter->second, myEntities); + aEntPos = Search(aEntIter->second, myEntities); int aParamPos = Search(myEntities[aEntPos].param[0], myParams); aParamIter = myParams.begin() + aParamPos; } const bool isEntExists = (aEntIter != myEntityAttrMap.end()); // defines that the entity already exists + const bool isNeedToSolve = myNeedToSolve; + myNeedToSolve = false; + + if (isEntExists) { + // Verify that the entity is not used by "Rigid" constraint. + // If it is used, the object should not move. + std::vector >::iterator aCoincIter = myCoincidentPoints.begin(); + for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++) + if (aCoincIter->find(aEntIter->second) != aCoincIter->end()) + break; + std::set aCoincident; + if (aCoincIter != myCoincidentPoints.end()) { + aCoincident = *aCoincIter; + aCoincident.erase(aEntIter->second); + + 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()) { + myNeedToSolve = true; + return aEntIter->second; + } + } + } // Look over supported types of entities + Slvs_Entity aNewEntity; + aNewEntity.h = SLVS_E_UNKNOWN; // Point in 3D - boost::shared_ptr aPoint = boost::dynamic_pointer_cast( + std::shared_ptr aPoint = std::dynamic_pointer_cast( theEntity); if (aPoint) { Slvs_hParam aX = changeParameter(aPoint->x(), aParamIter); Slvs_hParam aY = changeParameter(aPoint->y(), aParamIter); Slvs_hParam aZ = changeParameter(aPoint->z(), aParamIter); - - if (isEntExists) - return aEntIter->second; - - // New entity - Slvs_Entity aPtEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ); - myEntities.push_back(aPtEntity); - myEntityAttrMap[theEntity] = aPtEntity.h; - return aPtEntity.h; - } - - // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error - if (myWorkplane.h == SLVS_E_UNKNOWN) - return SLVS_E_UNKNOWN; - - // Point in 2D - boost::shared_ptr aPoint2D = - boost::dynamic_pointer_cast(theEntity); - if (aPoint2D) { - Slvs_hParam aU = changeParameter(aPoint2D->x(), aParamIter); - Slvs_hParam aV = changeParameter(aPoint2D->y(), aParamIter); - - if (isEntExists) - return aEntIter->second; - - // New entity - Slvs_Entity aPt2DEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV); - myEntities.push_back(aPt2DEntity); - myEntityAttrMap[theEntity] = aPt2DEntity.h; - return aPt2DEntity.h; + if (!isEntExists) // New entity + aNewEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ); + } else { + // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error + if (myWorkplane.h == SLVS_E_UNKNOWN) + return SLVS_E_UNKNOWN; + + // Point in 2D + std::shared_ptr aPoint2D = + std::dynamic_pointer_cast(theEntity); + if (aPoint2D) { + Slvs_hParam aU = changeParameter(aPoint2D->x(), aParamIter); + Slvs_hParam aV = changeParameter(aPoint2D->y(), aParamIter); + if (!isEntExists) // New entity + aNewEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV); + } else { + // Scalar value (used for the distance entities) + AttributeDoublePtr aScalar = std::dynamic_pointer_cast(theEntity); + if (aScalar) { + Slvs_hParam aValue = changeParameter(aScalar->value(), aParamIter); + if (!isEntExists) // New entity + aNewEntity = Slvs_MakeDistance(++myEntityMaxID, myID, myWorkplane.h, aValue); + } + } } + /// \todo Other types of entities - // Scalar value (used for the distance entities) - AttributeDoublePtr aScalar = boost::dynamic_pointer_cast(theEntity); - if (aScalar) { - Slvs_hParam aValue = changeParameter(aScalar->value(), aParamIter); - - if (isEntExists) - return aEntIter->second; + Slvs_hEntity aResult = SLVS_E_UNKNOWN; // Unsupported or wrong entity type - // New entity - Slvs_Entity aDistance = Slvs_MakeDistance(++myEntityMaxID, myID, myWorkplane.h, aValue); - myEntities.push_back(aDistance); - myEntityAttrMap[theEntity] = aDistance.h; - return aDistance.h; + if (isEntExists) { + myNeedToSolve = myNeedToSolve || isNeedToSolve; + aResult = aEntIter->second; + } else if (aNewEntity.h != SLVS_E_UNKNOWN) { + myEntities.push_back(aNewEntity); + myEntOfConstr.push_back(false); + myEntityAttrMap[theEntity] = aNewEntity.h; + aResult = aNewEntity.h; } - /// \todo Other types of entities + // If the attribute was changed by the user, we need to fix it before solving + if (myNeedToSolve && theEntity->isImmutable()) + addTemporaryConstraintWhereDragged(theEntity, false); - // Unsupported or wrong entity type - return SLVS_E_UNKNOWN; + return aResult; } // ============================================================================ @@ -407,7 +648,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( // Class: SketchSolver_ConstraintGroup // Purpose: create/update the element defined by the feature affected by any constraint // ============================================================================ -Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity(FeaturePtr theEntity) +Slvs_hEntity SketchSolver_ConstraintGroup::changeEntityFeature(FeaturePtr theEntity) { if (!theEntity->data()->isValid()) return SLVS_E_UNKNOWN; @@ -415,69 +656,67 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity(FeaturePtr theEntity) std::map::const_iterator aEntIter = myEntityFeatMap.find(theEntity); // defines that the entity already exists const bool isEntExists = (myEntityFeatMap.find(theEntity) != myEntityFeatMap.end()); + + Slvs_Entity aNewEntity; + aNewEntity.h = SLVS_E_UNKNOWN; // SketchPlugin features - boost::shared_ptr aFeature = boost::dynamic_pointer_cast< + std::shared_ptr aFeature = std::dynamic_pointer_cast< SketchPlugin_Feature>(theEntity); if (aFeature) { // Verify the feature by its kind const std::string& aFeatureKind = aFeature->getKind(); + AttributePtr anAttribute; // Line if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) { - Slvs_hEntity aStart = changeEntity( - aFeature->data()->attribute(SketchPlugin_Line::START_ID())); - Slvs_hEntity aEnd = changeEntity(aFeature->data()->attribute(SketchPlugin_Line::END_ID())); + anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID()); + if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; + Slvs_hEntity aStart = changeEntity(anAttribute); - if (isEntExists) - return aEntIter->second; + anAttribute = aFeature->data()->attribute(SketchPlugin_Line::END_ID()); + if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; + Slvs_hEntity aEnd = changeEntity(anAttribute); - // New entity - Slvs_Entity aLineEntity = Slvs_MakeLineSegment(++myEntityMaxID, myID, myWorkplane.h, aStart, - aEnd); - myEntities.push_back(aLineEntity); - myEntityFeatMap[theEntity] = aLineEntity.h; - myNeedToSolve = true; - return aLineEntity.h; + if (!isEntExists) // New entity + aNewEntity = Slvs_MakeLineSegment(++myEntityMaxID, myID, myWorkplane.h, aStart, aEnd); } // Circle else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) { - Slvs_hEntity aCenter = changeEntity( - aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID())); - Slvs_hEntity aRadius = changeEntity( - aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID())); + anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()); + if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; + Slvs_hEntity aCenter = changeEntity(anAttribute); - if (isEntExists) - return aEntIter->second; + anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()); + if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; + Slvs_hEntity aRadius = changeEntity(anAttribute); - // New entity - Slvs_Entity aCircleEntity = Slvs_MakeCircle(++myEntityMaxID, myID, myWorkplane.h, aCenter, - myWorkplane.normal, aRadius); - myEntities.push_back(aCircleEntity); - myEntityFeatMap[theEntity] = aCircleEntity.h; - myNeedToSolve = true; - return aCircleEntity.h; + if (!isEntExists) // New entity + aNewEntity = Slvs_MakeCircle(++myEntityMaxID, myID, myWorkplane.h, aCenter, + myWorkplane.normal, aRadius); } // Arc else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) { - Slvs_hEntity aCenter = changeEntity( - aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID())); - Slvs_hEntity aStart = changeEntity(aFeature->data()->attribute(SketchPlugin_Arc::START_ID())); - Slvs_hEntity aEnd = changeEntity(aFeature->data()->attribute(SketchPlugin_Arc::END_ID())); + anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()); + if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; + Slvs_hEntity aCenter = changeEntity(anAttribute); - if (isEntExists) - return aEntIter->second; + anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::START_ID()); + if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; + Slvs_hEntity aStart = changeEntity(anAttribute); - Slvs_Entity anArcEntity = Slvs_MakeArcOfCircle(++myEntityMaxID, myID, myWorkplane.h, - myWorkplane.normal, aCenter, aStart, aEnd); - myEntities.push_back(anArcEntity); - myEntityFeatMap[theEntity] = anArcEntity.h; - myNeedToSolve = true; - return anArcEntity.h; + anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::END_ID()); + if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; + Slvs_hEntity aEnd = changeEntity(anAttribute); + + if (!isEntExists) + aNewEntity = Slvs_MakeArcOfCircle(++myEntityMaxID, myID, myWorkplane.h, + myWorkplane.normal, aCenter, aStart, aEnd); } // Point (it has low probability to be an attribute of constraint, so it is checked at the end) else if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) { - Slvs_hEntity aPoint = changeEntity( - aFeature->data()->attribute(SketchPlugin_Point::COORD_ID())); + anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()); + if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; + Slvs_hEntity aPoint = changeEntity(anAttribute); if (isEntExists) return aEntIter->second; @@ -488,9 +727,19 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity(FeaturePtr theEntity) return aPoint; } } - /// \todo Other types of features + if (isEntExists) + return aEntIter->second; + + if (aNewEntity.h != SLVS_E_UNKNOWN) { + myEntities.push_back(aNewEntity); + myEntOfConstr.push_back(false); + myEntityFeatMap[theEntity] = aNewEntity.h; + myNeedToSolve = true; + return aNewEntity.h; + } + // Unsupported or wrong entity type return SLVS_E_UNKNOWN; } @@ -501,11 +750,11 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity(FeaturePtr theEntity) // Purpose: create/update the normal of workplane // ============================================================================ Slvs_hEntity SketchSolver_ConstraintGroup::changeNormal( - boost::shared_ptr theDirX, boost::shared_ptr theDirY, - boost::shared_ptr theNorm) + std::shared_ptr theDirX, std::shared_ptr theDirY, + std::shared_ptr theNorm) { - boost::shared_ptr aDirX = boost::dynamic_pointer_cast(theDirX); - boost::shared_ptr aDirY = boost::dynamic_pointer_cast(theDirY); + std::shared_ptr aDirX = std::dynamic_pointer_cast(theDirX); + std::shared_ptr aDirY = std::dynamic_pointer_cast(theDirY); if (!aDirX || !aDirY || (fabs(aDirX->x()) + fabs(aDirX->y()) + fabs(aDirX->z()) < tolerance) || (fabs(aDirY->x()) + fabs(aDirY->y()) + fabs(aDirY->z()) < tolerance)) return SLVS_E_UNKNOWN; @@ -517,7 +766,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeNormal( double aNormCoord[4] = { qw, qx, qy, qz }; // Try to find existent normal - std::map, Slvs_hEntity>::const_iterator aEntIter = + std::map, Slvs_hEntity>::const_iterator aEntIter = myEntityAttrMap.find(theNorm); std::vector::const_iterator aParamIter; // looks to the first parameter of already existent entity or to the end of vector otherwise if (aEntIter == myEntityAttrMap.end()) // no such entity => should be created @@ -540,6 +789,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeNormal( Slvs_Entity aNormal = Slvs_MakeNormal3d(++myEntityMaxID, myID, aNormParams[0], aNormParams[1], aNormParams[2], aNormParams[3]); myEntities.push_back(aNormal); + myEntOfConstr.push_back(false); myEntityAttrMap[theNorm] = aNormal.h; return aNormal.h; } @@ -549,7 +799,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeNormal( // Class: SketchSolver_ConstraintGroup // Purpose: create workplane for the group // ============================================================================ -bool SketchSolver_ConstraintGroup::addWorkplane(boost::shared_ptr theSketch) +bool SketchSolver_ConstraintGroup::addWorkplane(std::shared_ptr theSketch) { if (myWorkplane.h || theSketch->getKind().compare(SketchPlugin_Sketch::ID()) != 0) return false; // the workplane already exists or the function parameter is not Sketch @@ -566,14 +816,16 @@ bool SketchSolver_ConstraintGroup::addWorkplane(boost::shared_ptrdata()) + return false; // case sketch is deleted // Get parameters of workplane - boost::shared_ptr aDirX = mySketch->data()->attribute( + std::shared_ptr aDirX = mySketch->data()->attribute( SketchPlugin_Sketch::DIRX_ID()); - boost::shared_ptr aDirY = mySketch->data()->attribute( + std::shared_ptr aDirY = mySketch->data()->attribute( SketchPlugin_Sketch::DIRY_ID()); - boost::shared_ptr aNorm = mySketch->data()->attribute( + std::shared_ptr aNorm = mySketch->data()->attribute( SketchPlugin_Sketch::NORM_ID()); - boost::shared_ptr anOrigin = mySketch->data()->attribute( + std::shared_ptr anOrigin = mySketch->data()->attribute( SketchPlugin_Sketch::ORIGIN_ID()); // Transform them into SolveSpace format Slvs_hEntity aNormalWP = changeNormal(aDirX, aDirY, aNorm); @@ -588,6 +840,7 @@ bool SketchSolver_ConstraintGroup::updateWorkplane() myWorkplane = Slvs_MakeWorkplane(++myEntityMaxID, myID, anOriginWP, aNormalWP); // Workplane should be added to the list of entities myEntities.push_back(myWorkplane); + myEntOfConstr.push_back(false); } return true; } @@ -642,11 +895,19 @@ bool SketchSolver_ConstraintGroup::resolveConstraints() return true; // We should go through the attributes map, because only attributes have valued parameters - std::map, Slvs_hEntity>::iterator anEntIter = + std::map, Slvs_hEntity>::iterator anEntIter = myEntityAttrMap.begin(); - for (; anEntIter != myEntityAttrMap.end(); anEntIter++) + for (; anEntIter != myEntityAttrMap.end(); anEntIter++) { + if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get()) + anEntIter->first->owner()->data()->blockSendAttributeUpdated(true); if (updateAttribute(anEntIter->first, anEntIter->second)) updateRelatedConstraints(anEntIter->first); + } + // unblock all features then + for (; anEntIter != myEntityAttrMap.end(); anEntIter++) { + if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get()) + anEntIter->first->owner()->data()->blockSendAttributeUpdated(false); + } } else if (!myConstraints.empty()) Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this); @@ -670,11 +931,10 @@ void SketchSolver_ConstraintGroup::mergeGroups(const SketchSolver_ConstraintGrou std::map aConstrMap; // Add all constraints from theGroup to the current group - std::map, Slvs_hConstraint>::const_iterator aConstrIter = - theGroup.myConstraintMap.begin(); + ConstraintMap::const_iterator aConstrIter = theGroup.myConstraintMap.begin(); for (; aConstrIter != theGroup.myConstraintMap.end(); aConstrIter++) if (changeConstraint(aConstrIter->first)) - aConstrMap[aConstrIter->second] = myConstrMaxID; // the constraint was added => store its ID + aConstrMap[aConstrIter->second.back()] = myConstrMaxID; // the constraint was added => store its ID // Add temporary constraints from theGroup std::list::const_iterator aTempConstrIter = theGroup.myTempConstraints.begin(); @@ -688,7 +948,7 @@ void SketchSolver_ConstraintGroup::mergeGroups(const SketchSolver_ConstraintGrou if (myTempPointWhereDragged.empty()) myTempPointWhereDragged = theGroup.myTempPointWhereDragged; else if (!theGroup.myTempPointWhereDragged.empty()) { // Need to create additional transient constraint - std::map, Slvs_hEntity>::const_iterator aFeatureIter = + std::map, Slvs_hEntity>::const_iterator aFeatureIter = theGroup.myEntityAttrMap.begin(); for (; aFeatureIter != theGroup.myEntityAttrMap.end(); aFeatureIter++) if (aFeatureIter->second == myTempPointWDrgdID) { @@ -721,8 +981,16 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vectorfind(aConstrEnt[i]) != aGrEntIter->end()); + // Also we need to check sub-entities + int aEntPos = Search(aConstrEnt[i], myEntities); + if (aEntPos != myEntities.size()) { // MPV: to fix the crash on close + Slvs_hEntity* aSub = myEntities[aEntPos].point; + for (int j = 0; *aSub != 0 && j < 4 && !isFound; aSub++, j++) + isFound = (aGrEntIter->find(*aSub) != aGrEntIter->end()); + } + } if (isFound) anIndexes.push_back(aGrEntIter - aGroupsEntities.begin()); } @@ -730,8 +998,15 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vector aNewGrEnt; for (int i = 0; i < 4; i++) - if (aConstrEnt[i] != 0) + if (aConstrEnt[i] != 0) { aNewGrEnt.insert(aConstrEnt[i]); + int aEntPos = Search(aConstrEnt[i], myEntities); + if (aEntPos != myEntities.size()) { // MPV: to fix the crash on close + Slvs_hEntity* aSub = myEntities[aEntPos].point; + for (int j = 0; *aSub != 0 && j < 4; aSub++, j++) + aNewGrEnt.insert(*aSub); + } + } std::set aNewGrConstr; aNewGrConstr.insert(aConstrIter->h); @@ -739,30 +1014,38 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vector aGroupsEntities[aMaxNbEntities].size()) aMaxNbEntities = aGroupsEntities.size() - 1; - } else if (anIndexes.size() == 1) { // Add entities indexes into the found group + } else { // Add entities indexes into the found group aGrEntIter = aGroupsEntities.begin() + anIndexes.front(); for (int i = 0; i < 4; i++) - if (aConstrEnt[i] != 0) + if (aConstrEnt[i] != 0) { aGrEntIter->insert(aConstrEnt[i]); + int aEntPos = Search(aConstrEnt[i], myEntities); + if (aEntPos != myEntities.size()) { // MPV: to fix the crash on close + Slvs_hEntity* aSub = myEntities[aEntPos].point; + for (int j = 0; *aSub != 0 && j < 4; aSub++, j++) + aGrEntIter->insert(*aSub); + } + } aGroupsConstr[anIndexes.front()].insert(aConstrIter->h); if (aGrEntIter->size() > aGroupsEntities[aMaxNbEntities].size()) aMaxNbEntities = aGrEntIter - aGroupsEntities.begin(); - } else { // There are found several connected groups, merge them - std::vector >::iterator aFirstGroup = aGroupsEntities.begin() - + anIndexes.front(); - std::vector >::iterator aFirstConstr = aGroupsConstr.begin() - + anIndexes.front(); - std::vector::iterator anInd = anIndexes.begin(); - for (++anInd; anInd != anIndexes.end(); anInd++) { - aFirstGroup->insert(aGroupsEntities[*anInd].begin(), aGroupsEntities[*anInd].end()); - aFirstConstr->insert(aGroupsConstr[*anInd].begin(), aGroupsConstr[*anInd].end()); - } - if (aFirstGroup->size() > aGroupsEntities[aMaxNbEntities].size()) - aMaxNbEntities = anIndexes.front(); - // Remove merged groups - for (anInd = anIndexes.end() - 1; anInd != anIndexes.begin(); anInd--) { - aGroupsEntities.erase(aGroupsEntities.begin() + (*anInd)); - aGroupsConstr.erase(aGroupsConstr.begin() + (*anInd)); + if (anIndexes.size() > 1) { // There are found several connected groups, merge them + std::vector >::iterator aFirstGroup = aGroupsEntities.begin() + + anIndexes.front(); + std::vector >::iterator aFirstConstr = aGroupsConstr.begin() + + anIndexes.front(); + std::vector::iterator anInd = anIndexes.begin(); + for (++anInd; anInd != anIndexes.end(); anInd++) { + aFirstGroup->insert(aGroupsEntities[*anInd].begin(), aGroupsEntities[*anInd].end()); + aFirstConstr->insert(aGroupsConstr[*anInd].begin(), aGroupsConstr[*anInd].end()); + } + if (aFirstGroup->size() > aGroupsEntities[aMaxNbEntities].size()) + aMaxNbEntities = anIndexes.front(); + // Remove merged groups + for (anInd = anIndexes.end() - 1; anInd != anIndexes.begin(); anInd--) { + aGroupsEntities.erase(aGroupsEntities.begin() + (*anInd)); + aGroupsConstr.erase(aGroupsConstr.begin() + (*anInd)); + } } } } @@ -780,14 +1063,13 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vector, Slvs_hConstraint>::const_iterator aConstrMapIter = - myConstraintMap.begin(); + ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.begin(); int aConstrMapPos = 0; // position of iterator in the map (used to restore iterator after removing constraint) while (aConstrMapIter != myConstraintMap.end()) { std::vector >::const_iterator aGIter = aGroupsConstr.begin(); std::vector::iterator aGroup = aNewGroups.begin(); for (; aGIter != aGroupsConstr.end(); aGIter++, aGroup++) - if (aGIter->find(aConstrMapIter->second) != aGIter->end()) { + if (aGIter->find(aConstrMapIter->second.front()) != aGIter->end()) { (*aGroup)->changeConstraint(aConstrMapIter->first); removeConstraint(aConstrMapIter->first); // restore iterator @@ -812,29 +1094,61 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vector, Slvs_hConstraint>::reverse_iterator aConstrIter = - myConstraintMap.rbegin(); + ConstraintMap::reverse_iterator aConstrIter = myConstraintMap.rbegin(); bool isAllValid = true; bool isCCRemoved = false; // indicates that at least one of coincidence constraints was removed - while (isAllValid && aConstrIter != myConstraintMap.rend()) { + int aConstrIndex = 0; + while (/*isAllValid && */aConstrIter != myConstraintMap.rend()) { if (!aConstrIter->first->data() || !aConstrIter->first->data()->isValid()) { if (aConstrIter->first->getKind().compare(SketchPlugin_ConstraintCoincidence::ID()) == 0) isCCRemoved = true; - std::map, Slvs_hConstraint>::reverse_iterator aCopyIter = - aConstrIter++; - removeConstraint(aCopyIter->first); + removeConstraint(aConstrIter->first); isAllValid = false; - } else + // Get back the correct position of iterator after the "remove" operation + aConstrIter = myConstraintMap.rbegin(); + for (int i = 0; i < aConstrIndex && aConstrIter != myConstraintMap.rend(); i++) + aConstrIter++; + } else { aConstrIter++; + aConstrIndex++; + } + } + + // Check if some entities are invalid too + std::set anEntToRemove; + std::map, Slvs_hEntity>::iterator + anAttrIter = myEntityAttrMap.begin(); + while (anAttrIter != myEntityAttrMap.end()) { + if (!anAttrIter->first->owner() || !anAttrIter->first->owner()->data() || + !anAttrIter->first->owner()->data()->isValid()) { + anEntToRemove.insert(anAttrIter->second); + std::map, Slvs_hEntity>::iterator + aRemovedIter = anAttrIter; + anAttrIter++; + myEntityAttrMap.erase(aRemovedIter); + } else + anAttrIter++; + } + std::map::iterator aFeatIter = myEntityFeatMap.begin(); + while (aFeatIter != myEntityFeatMap.end()) { + if (!aFeatIter->first || !aFeatIter->first->data() || + !aFeatIter->first->data()->isValid()) { + anEntToRemove.insert(aFeatIter->second); + std::map::iterator aRemovedIter = aFeatIter; + aFeatIter++; + myEntityFeatMap.erase(aRemovedIter); + } else + aFeatIter++; } + removeEntitiesById(anEntToRemove); // Probably, need to update coincidence constraints if (isCCRemoved && !myExtraCoincidence.empty()) { // Make a copy, because the new list of unused constrtaints will be generated - std::set > anExtraCopy = myExtraCoincidence; + std::set > anExtraCopy = myExtraCoincidence; myExtraCoincidence.clear(); - std::set >::iterator aCIter = anExtraCopy.begin(); + std::set >::iterator aCIter = anExtraCopy.begin(); for (; aCIter != anExtraCopy.end(); aCIter++) if ((*aCIter)->data() && (*aCIter)->data()->isValid()) changeConstraint(*aCIter); @@ -849,7 +1163,7 @@ bool SketchSolver_ConstraintGroup::updateGroup() // Purpose: update features of sketch after resolving constraints // ============================================================================ bool SketchSolver_ConstraintGroup::updateAttribute( - boost::shared_ptr theAttribute, const Slvs_hEntity& theEntityID) + std::shared_ptr theAttribute, const Slvs_hEntity& theEntityID) { // Search the position of the first parameter of the entity int anEntPos = Search(theEntityID, myEntities); @@ -858,7 +1172,7 @@ bool SketchSolver_ConstraintGroup::updateAttribute( // Look over supported types of entities // Point in 3D - boost::shared_ptr aPoint = boost::dynamic_pointer_cast( + std::shared_ptr aPoint = std::dynamic_pointer_cast( theAttribute); if (aPoint) { if (fabs(aPoint->x() - myParams[aFirstParamPos].val) > tolerance @@ -872,8 +1186,8 @@ bool SketchSolver_ConstraintGroup::updateAttribute( } // Point in 2D - boost::shared_ptr aPoint2D = - boost::dynamic_pointer_cast(theAttribute); + std::shared_ptr aPoint2D = + std::dynamic_pointer_cast(theAttribute); if (aPoint2D) { if (fabs(aPoint2D->x() - myParams[aFirstParamPos].val) > tolerance || fabs(aPoint2D->y() - myParams[aFirstParamPos + 1].val) > tolerance) { @@ -884,7 +1198,7 @@ bool SketchSolver_ConstraintGroup::updateAttribute( } // Scalar value - AttributeDoublePtr aScalar = boost::dynamic_pointer_cast(theAttribute); + AttributeDoublePtr aScalar = std::dynamic_pointer_cast(theAttribute); if (aScalar) { if (fabs(aScalar->value() - myParams[aFirstParamPos].val) > tolerance) { aScalar->setValue(myParams[aFirstParamPos].val); @@ -903,7 +1217,7 @@ bool SketchSolver_ConstraintGroup::updateAttribute( // Purpose: search the entity in this group and update it // ============================================================================ void SketchSolver_ConstraintGroup::updateEntityIfPossible( - boost::shared_ptr theEntity) + std::shared_ptr theEntity) { if (myEntityAttrMap.find(theEntity) != myEntityAttrMap.end()) { // If the attribute is a point and it is changed (the group needs to rebuild), @@ -919,9 +1233,9 @@ void SketchSolver_ConstraintGroup::updateEntityIfPossible( if (myNeedToSolve) // the entity is changed { // Verify the entity is a point and add temporary constraint of permanency - boost::shared_ptr aPoint = boost::dynamic_pointer_cast( + std::shared_ptr aPoint = std::dynamic_pointer_cast( theEntity); - boost::shared_ptr aPoint2D = boost::dynamic_pointer_cast< + std::shared_ptr aPoint2D = std::dynamic_pointer_cast< GeomDataAPI_Point2D>(theEntity); if (aPoint || aPoint2D) addTemporaryConstraintWhereDragged(theEntity); @@ -942,35 +1256,28 @@ void SketchSolver_ConstraintGroup::updateEntityIfPossible( // which was moved by user // ============================================================================ void SketchSolver_ConstraintGroup::addTemporaryConstraintWhereDragged( - boost::shared_ptr theEntity) + std::shared_ptr theEntity, + bool theAllowToFit) { // Find identifier of the entity - std::map, Slvs_hEntity>::const_iterator anEntIter = + std::map, Slvs_hEntity>::const_iterator anEntIter = myEntityAttrMap.find(theEntity); if (anEntIter == myEntityAttrMap.end()) return; - // If this is a first dragged point, its parameters should be placed - // into Slvs_System::dragged field to avoid system inconsistense - if (myTempPointWhereDragged.empty()) { - int anEntPos = Search(anEntIter->second, myEntities); - Slvs_hParam* aDraggedParam = myEntities[anEntPos].param; - for (int i = 0; i < 4; i++, aDraggedParam++) - if (*aDraggedParam != 0) - myTempPointWhereDragged.push_back(*aDraggedParam); - myTempPointWDrgdID = myEntities[anEntPos].h; - return; - } - // Get identifiers of all dragged points std::set aDraggedPntID; aDraggedPntID.insert(myTempPointWDrgdID); - std::list::iterator aTmpCoIter = myTempConstraints.begin(); + std::list::const_iterator aTmpCoIter = myTempConstraints.begin(); for (; aTmpCoIter != myTempConstraints.end(); aTmpCoIter++) { unsigned int aConstrPos = Search(*aTmpCoIter, myConstraints); if (aConstrPos < myConstraints.size()) aDraggedPntID.insert(myConstraints[aConstrPos].ptA); } + std::vector::const_iterator aConstrIter = myConstraints.begin(); + for (; aConstrIter != myConstraints.end(); aConstrIter++) + if (aConstrIter->type == SLVS_C_WHERE_DRAGGED) + aDraggedPntID.insert(aConstrIter->ptA); // Find whether there is a point coincident with theEntity, which already has SLVS_C_WHERE_DRAGGED std::vector >::iterator aCoPtIter = myCoincidentPoints.begin(); for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) { @@ -983,6 +1290,20 @@ void SketchSolver_ConstraintGroup::addTemporaryConstraintWhereDragged( if (aCoPtIter->find(*aDrgIter) != aCoPtIter->end()) return; // the SLVS_C_WHERE_DRAGGED constraint already exists } + if (aDraggedPntID.find(anEntIter->second) != aDraggedPntID.end()) + return; + + // If this is a first dragged point, its parameters should be placed + // into Slvs_System::dragged field to avoid system inconsistense + if (myTempPointWhereDragged.empty() && theAllowToFit) { + int anEntPos = Search(anEntIter->second, myEntities); + Slvs_hParam* aDraggedParam = myEntities[anEntPos].param; + for (int i = 0; i < 4; i++, aDraggedParam++) + if (*aDraggedParam != 0) + myTempPointWhereDragged.push_back(*aDraggedParam); + myTempPointWDrgdID = myEntities[anEntPos].h; + return; + } // Create additional SLVS_C_WHERE_DRAGGED constraint if myTempPointWhereDragged field is not empty Slvs_Constraint aWDConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, @@ -997,11 +1318,14 @@ void SketchSolver_ConstraintGroup::addTemporaryConstraintWhereDragged( // Purpose: remove all transient SLVS_C_WHERE_DRAGGED constraints after // resolving the set of constraints // ============================================================================ -void SketchSolver_ConstraintGroup::removeTemporaryConstraints() +void SketchSolver_ConstraintGroup::removeTemporaryConstraints( + const std::set& theRemoved) { std::list::reverse_iterator aTmpConstrIter; for (aTmpConstrIter = myTempConstraints.rbegin(); aTmpConstrIter != myTempConstraints.rend(); aTmpConstrIter++) { + if (!theRemoved.empty() && theRemoved.find(*aTmpConstrIter) == theRemoved.end()) + continue; unsigned int aConstrPos = Search(*aTmpConstrIter, myConstraints); if (aConstrPos >= myConstraints.size()) continue; @@ -1015,6 +1339,7 @@ void SketchSolver_ConstraintGroup::removeTemporaryConstraints() // Clear basic dragged point myTempPointWhereDragged.clear(); + myTempPointWDrgdID = SLVS_E_UNKNOWN; } // ============================================================================ @@ -1023,28 +1348,31 @@ void SketchSolver_ConstraintGroup::removeTemporaryConstraints() // Purpose: remove constraint and all unused entities // ============================================================================ void SketchSolver_ConstraintGroup::removeConstraint( - boost::shared_ptr theConstraint) + std::shared_ptr theConstraint) { - std::map, Slvs_hConstraint>::iterator anIterToRemove = - myConstraintMap.find(theConstraint); + ConstraintMap::iterator anIterToRemove = myConstraintMap.find(theConstraint); if (anIterToRemove == myConstraintMap.end()) return; - Slvs_hConstraint aCnstrToRemove = anIterToRemove->second; + std::vector aCnstrToRemove = anIterToRemove->second; // Remove constraint from the map myConstraintMap.erase(anIterToRemove); - // Find unused entities - int aConstrPos = Search(aCnstrToRemove, myConstraints); std::set anEntToRemove; - Slvs_hEntity aCnstEnt[] = { myConstraints[aConstrPos].ptA, myConstraints[aConstrPos].ptB, - myConstraints[aConstrPos].entityA, myConstraints[aConstrPos].entityB }; - for (int i = 0; i < 4; i++) - if (aCnstEnt[i] != 0) - anEntToRemove.insert(aCnstEnt[i]); - myConstraints.erase(myConstraints.begin() + aConstrPos); - if (aCnstrToRemove == myConstrMaxID) - myConstrMaxID--; + + // Find unused entities + std::vector::iterator aCnstrToRemoveIter = aCnstrToRemove.begin(); + for (; aCnstrToRemoveIter != aCnstrToRemove.end(); aCnstrToRemoveIter++) { + int aConstrPos = Search(*aCnstrToRemoveIter, myConstraints); + Slvs_hEntity aCnstEnt[] = { myConstraints[aConstrPos].ptA, myConstraints[aConstrPos].ptB, + myConstraints[aConstrPos].entityA, myConstraints[aConstrPos].entityB }; + for (int i = 0; i < 4; i++) + if (aCnstEnt[i] != 0) + anEntToRemove.insert(aCnstEnt[i]); + myConstraints.erase(myConstraints.begin() + aConstrPos); + if (*aCnstrToRemoveIter == myConstrMaxID) + myConstrMaxID--; + } // Find all entities which are based on these unused std::vector::const_iterator anEntIter = myEntities.begin(); @@ -1074,11 +1402,11 @@ void SketchSolver_ConstraintGroup::removeConstraint( return; // Remove unused entities - std::map, Slvs_hEntity>::iterator anEntAttrIter = + std::map, Slvs_hEntity>::iterator anEntAttrIter = myEntityAttrMap.begin(); while (anEntAttrIter != myEntityAttrMap.end()) { if (anEntToRemove.find(anEntAttrIter->second) != anEntToRemove.end()) { - std::map, Slvs_hEntity>::iterator aRemovedIter = + std::map, Slvs_hEntity>::iterator aRemovedIter = anEntAttrIter; anEntAttrIter++; myEntityAttrMap.erase(aRemovedIter); @@ -1094,8 +1422,22 @@ void SketchSolver_ConstraintGroup::removeConstraint( } else anEntFeatIter++; } - std::set::const_reverse_iterator aRemIter = anEntToRemove.rbegin(); - for (; aRemIter != anEntToRemove.rend(); aRemIter++) { + + removeEntitiesById(anEntToRemove); + + if (myCoincidentPoints.size() == 1 && myCoincidentPoints.front().empty()) + myCoincidentPoints.clear(); +} + +// ============================================================================ +// Function: removeEntitiesById +// Class: SketchSolver_ConstraintGroup +// Purpose: Removes specified entities and their parameters +// ============================================================================ +void SketchSolver_ConstraintGroup::removeEntitiesById(const std::set& theEntities) +{ + std::set::const_reverse_iterator aRemIter = theEntities.rbegin(); + for (; aRemIter != theEntities.rend(); aRemIter++) { unsigned int anEntPos = Search(*aRemIter, myEntities); if (anEntPos >= myEntities.size()) continue; @@ -1113,14 +1455,13 @@ void SketchSolver_ConstraintGroup::removeConstraint( myEntityMaxID--; } myEntities.erase(myEntities.begin() + anEntPos); + myEntOfConstr.erase(myEntOfConstr.begin() + anEntPos); // Remove entity's ID from the lists of conincident points std::vector >::iterator aCoPtIter = myCoincidentPoints.begin(); for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) aCoPtIter->erase(*aRemIter); } - if (myCoincidentPoints.size() == 1 && myCoincidentPoints.front().empty()) - myCoincidentPoints.clear(); } // ============================================================================ @@ -1172,18 +1513,17 @@ bool SketchSolver_ConstraintGroup::addCoincidentPoints(const Slvs_hEntity& thePo // Purpose: emit the signal to update constraints // ============================================================================ void SketchSolver_ConstraintGroup::updateRelatedConstraints( - boost::shared_ptr theEntity) const + std::shared_ptr theEntity) const { - std::map, Slvs_hConstraint>::const_iterator aConstrIter = - myConstraintMap.begin(); + ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin(); for (; aConstrIter != myConstraintMap.end(); aConstrIter++) { - std::list > anAttributes = aConstrIter->first->data() + std::list > anAttributes = aConstrIter->first->data() ->attributes(std::string()); - std::list >::iterator anAttrIter = anAttributes.begin(); + std::list >::iterator anAttrIter = anAttributes.begin(); for (; anAttrIter != anAttributes.end(); anAttrIter++) { bool isUpd = (*anAttrIter == theEntity); - boost::shared_ptr aRefAttr = boost::dynamic_pointer_cast< + std::shared_ptr aRefAttr = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(*anAttrIter); if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theEntity) isUpd = true; @@ -1197,18 +1537,17 @@ void SketchSolver_ConstraintGroup::updateRelatedConstraints( } } -void SketchSolver_ConstraintGroup::updateRelatedConstraints( - boost::shared_ptr theFeature) const +void SketchSolver_ConstraintGroup::updateRelatedConstraintsFeature( + std::shared_ptr theFeature) const { - std::map, Slvs_hConstraint>::const_iterator aConstrIter = - myConstraintMap.begin(); + ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin(); for (; aConstrIter != myConstraintMap.end(); aConstrIter++) { - std::list > anAttributes = aConstrIter->first->data() + std::list > anAttributes = aConstrIter->first->data() ->attributes(std::string()); - std::list >::iterator anAttrIter = anAttributes.begin(); + std::list >::iterator anAttrIter = anAttributes.begin(); for (; anAttrIter != anAttributes.end(); anAttrIter++) { - boost::shared_ptr aRefAttr = boost::dynamic_pointer_cast< + std::shared_ptr aRefAttr = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(*anAttrIter); if (aRefAttr && aRefAttr->isObject() && aRefAttr->object() == theFeature) { static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);