X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintGroup.cpp;h=954c6c5963fb779fba5116bbe9132eab4e6cba89;hb=d34bc15bf8fafedd9188f47ff5962b5a1661d5b0;hp=df5111e6d81cdf8701e12d63fadd89074f72e620;hpb=234ea0df12d84e2329124a465ec2ce07813fbedc;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp index df5111e6d..954c6c596 100644 --- a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp @@ -6,15 +6,18 @@ #include +#include #include #include #include #include #include #include -#include +#include #include +#include +#include #include #include @@ -28,6 +31,8 @@ /// Tolerance for value of parameters const double tolerance = 1.e-10; +const std::string ERROR_SOLVE_CONSTRAINTS = "Conflicting constraints"; + /// This value is used to give unique index to the groups static Slvs_hGroup myGroupIndexer = 0; @@ -116,7 +121,12 @@ bool SketchSolver_ConstraintGroup::isInteract( theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[i]) ); if (!aCAttrRef) continue; - if (myEntityMap.find(aCAttrRef->attr()) != myEntityMap.end()) + if (!aCAttrRef->isObject() && + myEntityAttrMap.find(aCAttrRef->attr()) != myEntityAttrMap.end()) + return true; + if (aCAttrRef->isObject() && + myEntityFeatMap.find(boost::dynamic_pointer_cast(aCAttrRef->object())) + != myEntityFeatMap.end()) return true; } @@ -156,11 +166,14 @@ bool SketchSolver_ConstraintGroup::changeConstraint( // Create constraint parameters double aDistance = 0.0; // scalar value of the constraint - boost::shared_ptr aDistAttr = + AttributeDoublePtr aDistAttr = boost::dynamic_pointer_cast(theConstraint->data()->attribute(CONSTRAINT_ATTR_VALUE)); if (aDistAttr) { aDistance = aDistAttr->value(); + // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter + if (aConstrType == SLVS_C_DIAMETER) + aDistance *= 2.0; if (aConstrMapIter != myConstraintMap.end() && fabs(aConstrIter->valA - aDistance) > tolerance) { myNeedToSolve = true; @@ -177,7 +190,21 @@ bool SketchSolver_ConstraintGroup::changeConstraint( theConstraint->data()->attribute(aConstraintAttributes[indAttr]) ); if (!aConstrAttr) continue; - aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr()); + + // 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(SKETCH_CONSTRAINT_LENGTH_KIND) == 0) + { + boost::shared_ptr aData = aConstrAttr->object()->data(); + aConstrEnt[indAttr] = changeEntity(aData->attribute(LINE_ATTR_START)); + aConstrEnt[indAttr+1] = changeEntity(aData->attribute(LINE_ATTR_END)); + // measured object is added into the map of objects to avoid problems with interaction betwee constraint and group + myEntityFeatMap[boost::dynamic_pointer_cast(aConstrAttr->object())] = 0; + break; // there should be no other entities + } + else if (aConstrAttr->isObject()) + aConstrEnt[indAttr] = changeEntity(boost::dynamic_pointer_cast(aConstrAttr->object())); + else + aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr()); } if (aConstrMapIter == myConstraintMap.end()) @@ -186,41 +213,14 @@ bool SketchSolver_ConstraintGroup::changeConstraint( // Try to find sequence of coincident points which connects the points of new constraint if (aConstrType == SLVS_C_POINTS_COINCIDENT) { - std::vector< std::set >::iterator aCoPtIter = myCoincidentPoints.begin(); - std::vector< std::set >::iterator aFirstFound = myCoincidentPoints.end(); - for ( ; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) + if (aConstrEnt[0] == aConstrEnt[1]) // no need to add self coincidence { - bool isFound[2] = { // indicate which point ID was already in coincidence constraint - aCoPtIter->find(aConstrEnt[0]) != aCoPtIter->end(), - aCoPtIter->find(aConstrEnt[1]) != aCoPtIter->end(), - }; - if (isFound[0] && isFound[1]) // points are already connected by coincidence constraints => no need to additional one - return false; - if ((isFound[0] && !isFound[1]) || (!isFound[0] && isFound[1])) - { - if (aFirstFound != myCoincidentPoints.end()) - { // there are two groups of coincident points connected by created constraint => merge them - int aFirstFoundShift = aFirstFound - myCoincidentPoints.begin(); - int aCurrentShift = aCoPtIter - myCoincidentPoints.begin(); - aFirstFound->insert(aCoPtIter->begin(), aCoPtIter->end()); - myCoincidentPoints.erase(aCoPtIter); - aFirstFound = myCoincidentPoints.begin() + aFirstFoundShift; - aCoPtIter = myCoincidentPoints.begin() + aCurrentShift; - } - else - { - aCoPtIter->insert(aConstrEnt[isFound[0] ? 1 : 0]); - aFirstFound = aCoPtIter; - } - } + return false; } - // No points were found, need to create new set - if (aFirstFound == myCoincidentPoints.end()) + if (!addCoincidentPoints(aConstrEnt[0], aConstrEnt[1])) { - std::set aNewSet; - aNewSet.insert(aConstrEnt[0]); - aNewSet.insert(aConstrEnt[1]); - myCoincidentPoints.push_back(aNewSet); + myExtraCoincidence.insert(theConstraint); // the constraint is stored for further purposes + return false; } } @@ -244,9 +244,9 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( { // If the entity is already in the group, try to find it std::map, Slvs_hEntity>::const_iterator - aEntIter = myEntityMap.find(theEntity); + aEntIter = myEntityAttrMap.find(theEntity); std::vector::const_iterator aParamIter; // looks at first parameter of already existent entity or at the end of vector otherwise - if (aEntIter == myEntityMap.end()) // no such entity => should be created + if (aEntIter == myEntityAttrMap.end()) // no such entity => should be created aParamIter = myParams.end(); else { // the entity already exists @@ -254,6 +254,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( int aParamPos = Search(myEntities[aEntPos].param[0], myParams); aParamIter = myParams.begin() + aParamPos; } + const bool isEntExists = (aEntIter != myEntityAttrMap.end()); // defines that the entity already exists // Look over supported types of entities @@ -266,13 +267,13 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( Slvs_hParam aY = changeParameter(aPoint->y(), aParamIter); Slvs_hParam aZ = changeParameter(aPoint->z(), aParamIter); - if (aEntIter != myEntityMap.end()) // the entity already exists + if (isEntExists) return aEntIter->second; // New entity Slvs_Entity aPtEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ); myEntities.push_back(aPtEntity); - myEntityMap[theEntity] = aPtEntity.h; + myEntityAttrMap[theEntity] = aPtEntity.h; return aPtEntity.h; } @@ -288,33 +289,54 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( Slvs_hParam aU = changeParameter(aPoint2D->x(), aParamIter); Slvs_hParam aV = changeParameter(aPoint2D->y(), aParamIter); - if (aEntIter != myEntityMap.end()) // the entity already exists + if (isEntExists) return aEntIter->second; // New entity Slvs_Entity aPt2DEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV); myEntities.push_back(aPt2DEntity); - myEntityMap[theEntity] = aPt2DEntity.h; + myEntityAttrMap[theEntity] = aPt2DEntity.h; return aPt2DEntity.h; } // Scalar value (used for the distance entities) - boost::shared_ptr aScalar = + AttributeDoublePtr aScalar = boost::dynamic_pointer_cast(theEntity); if (aScalar) { Slvs_hParam aValue = changeParameter(aScalar->value(), aParamIter); - if (aEntIter != myEntityMap.end()) // the entity already exists + if (isEntExists) return aEntIter->second; // New entity Slvs_Entity aDistance = Slvs_MakeDistance(++myEntityMaxID, myID, myWorkplane.h, aValue); myEntities.push_back(aDistance); - myEntityMap[theEntity] = aDistance.h; + myEntityAttrMap[theEntity] = aDistance.h; return aDistance.h; } + /// \todo Other types of entities + + // Unsupported or wrong entity type + return SLVS_E_UNKNOWN; +} + + +// ============================================================================ +// Function: changeEntity +// Class: SketchSolver_ConstraintGroup +// Purpose: create/update the element defined by the feature affected by any constraint +// ============================================================================ +Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( + FeaturePtr theEntity) +{ + // If the entity is already in the group, try to find it + std::map::const_iterator + aEntIter = myEntityFeatMap.find(theEntity); + // defines that the entity already exists + const bool isEntExists = (myEntityFeatMap.find(theEntity) != myEntityFeatMap.end()); + // SketchPlugin features boost::shared_ptr aFeature = boost::dynamic_pointer_cast(theEntity); @@ -323,67 +345,67 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeEntity( const std::string& aFeatureKind = aFeature->getKind(); // Line - if (aFeatureKind.compare("SketchLine") == 0) + if (aFeatureKind.compare(SKETCH_LINE_KIND) == 0) { Slvs_hEntity aStart = changeEntity(aFeature->data()->attribute(LINE_ATTR_START)); Slvs_hEntity aEnd = changeEntity(aFeature->data()->attribute(LINE_ATTR_END)); - if (aEntIter != myEntityMap.end()) // the entity already exists + if (isEntExists) return aEntIter->second; // New entity Slvs_Entity aLineEntity = Slvs_MakeLineSegment(++myEntityMaxID, myID, myWorkplane.h, aStart, aEnd); myEntities.push_back(aLineEntity); - myEntityMap[theEntity] = aLineEntity.h; + myEntityFeatMap[theEntity] = aLineEntity.h; return aLineEntity.h; } // Circle - else if (aFeatureKind.compare("SketchCircle") == 0) + else if (aFeatureKind.compare(SKETCH_CIRCLE_KIND) == 0) { Slvs_hEntity aCenter = changeEntity(aFeature->data()->attribute(CIRCLE_ATTR_CENTER)); Slvs_hEntity aRadius = changeEntity(aFeature->data()->attribute(CIRCLE_ATTR_RADIUS)); - if (aEntIter != myEntityMap.end()) // the entity already exists + if (isEntExists) return aEntIter->second; // New entity Slvs_Entity aCircleEntity = Slvs_MakeCircle(++myEntityMaxID, myID, myWorkplane.h, aCenter, myWorkplane.normal, aRadius); myEntities.push_back(aCircleEntity); - myEntityMap[theEntity] = aCircleEntity.h; + myEntityFeatMap[theEntity] = aCircleEntity.h; return aCircleEntity.h; } // Arc - else if (aFeatureKind.compare("SketchArc") == 0) + else if (aFeatureKind.compare(SKETCH_ARC_KIND) == 0) { Slvs_hEntity aCenter = changeEntity(aFeature->data()->attribute(ARC_ATTR_CENTER)); Slvs_hEntity aStart = changeEntity(aFeature->data()->attribute(ARC_ATTR_START)); Slvs_hEntity aEnd = changeEntity(aFeature->data()->attribute(ARC_ATTR_END)); - if (aEntIter != myEntityMap.end()) // the entity already exists + if (isEntExists) return aEntIter->second; Slvs_Entity anArcEntity = Slvs_MakeArcOfCircle(++myEntityMaxID, myID, myWorkplane.h, myWorkplane.normal, aCenter, aStart, aEnd); myEntities.push_back(anArcEntity); - myEntityMap[theEntity] = anArcEntity.h; + myEntityFeatMap[theEntity] = anArcEntity.h; return anArcEntity.h; } // Point (it has low probability to be an attribute of constraint, so it is checked at the end) - else if (aFeatureKind.compare("SketchPoint") == 0) + else if (aFeatureKind.compare(SKETCH_POINT_KIND) == 0) { Slvs_hEntity aPoint = changeEntity(aFeature->data()->attribute(POINT_ATTR_COORD)); - if (aEntIter != myEntityMap.end()) // the entity already exists + if (isEntExists) return aEntIter->second; // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier - myEntityMap[theEntity] = aPoint; + myEntityFeatMap[theEntity] = aPoint; return aPoint; } } - /// \todo Other types of entities + /// \todo Other types of features // Unsupported or wrong entity type return SLVS_E_UNKNOWN; @@ -417,9 +439,9 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeNormal( // Try to find existent normal std::map, Slvs_hEntity>::const_iterator - aEntIter = myEntityMap.find(theNorm); + 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 == myEntityMap.end()) // no such entity => should be created + if (aEntIter == myEntityAttrMap.end()) // no such entity => should be created aParamIter = myParams.end(); else { // the entity already exists, update it @@ -433,14 +455,14 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeNormal( for (int i = 0; i < 4; i++) aNormParams[i] = changeParameter(aNormCoord[i], aParamIter); - if (aEntIter != myEntityMap.end()) // the entity already exists + if (aEntIter != myEntityAttrMap.end()) // the entity already exists return aEntIter->second; // Create a normal Slvs_Entity aNormal = Slvs_MakeNormal3d(++myEntityMaxID, myID, aNormParams[0], aNormParams[1], aNormParams[2], aNormParams[3]); myEntities.push_back(aNormal); - myEntityMap[theNorm] = aNormal.h; + myEntityAttrMap[theNorm] = aNormal.h; return aNormal.h; } @@ -453,7 +475,7 @@ Slvs_hEntity SketchSolver_ConstraintGroup::changeNormal( bool SketchSolver_ConstraintGroup::addWorkplane( boost::shared_ptr theSketch) { - if (myWorkplane.h || theSketch->getKind().compare("Sketch") != 0) + if (myWorkplane.h || theSketch->getKind().compare(SKETCH_KIND) != 0) return false; // the workplane already exists or the function parameter is not Sketch mySketch = theSketch; @@ -542,12 +564,15 @@ void SketchSolver_ConstraintGroup::resolveConstraints() if (!myConstrSolver.getResult(myParams)) return; + // We should go through the attributes map, because only attributes have valued parameters std::map, Slvs_hEntity>::iterator - anEntIter = myEntityMap.begin(); - for ( ; anEntIter != myEntityMap.end(); anEntIter++) - updateAttribute(anEntIter->first, anEntIter->second); + anEntIter = myEntityAttrMap.begin(); + for ( ; anEntIter != myEntityAttrMap.end(); anEntIter++) + if (updateAttribute(anEntIter->first, anEntIter->second)) + updateRelatedConstraints(anEntIter->first); } - /// \todo Implement error handling + else if (!myConstraints.empty()) + Events_Error::send(ERROR_SOLVE_CONSTRAINTS, this); removeTemporaryConstraints(); myNeedToSolve = false; @@ -589,8 +614,8 @@ void SketchSolver_ConstraintGroup::mergeGroups( else if (!theGroup.myTempPointWhereDragged.empty()) { // Need to create additional transient constraint std::map, Slvs_hEntity>::const_iterator - aFeatureIter = theGroup.myEntityMap.begin(); - for (; aFeatureIter != theGroup.myEntityMap.end(); aFeatureIter++) + aFeatureIter = theGroup.myEntityAttrMap.begin(); + for (; aFeatureIter != theGroup.myEntityAttrMap.end(); aFeatureIter++) if (aFeatureIter->second == myTempPointWDrgdID) { addTemporaryConstraintWhereDragged(aFeatureIter->first); @@ -618,6 +643,7 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vectorptA, aConstrIter->ptB, aConstrIter->entityA, aConstrIter->entityB}; + std::vector anIndexes; // Go through the groupped entities and find even one of entities of current constraint std::vector< std::set >::iterator aGrEntIter; for (aGrEntIter = aGroupsEntities.begin(); aGrEntIter != aGroupsEntities.end(); aGrEntIter++) @@ -627,18 +653,10 @@ void SketchSolver_ConstraintGroup::splitGroup(std::vectorfind(aConstrEnt[i]) != aGrEntIter->end()); if (isFound) - { - for (int i = 0; i < 4; i++) - if (aConstrEnt[i] != 0) - aGrEntIter->insert(aConstrEnt[i]); - aGroupsConstr[aGrEntIter - aGroupsEntities.begin()].insert(aConstrIter->h); - if (aGrEntIter->size() > aGroupsEntities[aMaxNbEntities].size()) - aMaxNbEntities = aGrEntIter - aGroupsEntities.begin(); - break; - } + anIndexes.push_back(aGrEntIter - aGroupsEntities.begin()); } - // Add new group is no one is found - if (aGrEntIter == aGroupsEntities.end()) + // Add new group if no one is found + if (anIndexes.empty()) { std::set aNewGrEnt; for (int i = 0; i < 4; i++) @@ -652,6 +670,37 @@ 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 + aGrEntIter = aGroupsEntities.begin() + anIndexes.front(); + for (int i = 0; i < 4; i++) + if (aConstrEnt[i] != 0) + aGrEntIter->insert(aConstrEnt[i]); + 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< std::set >::iterator aFirstGroup = + aGroupsEntities.begin() + anIndexes.front(); + std::vector< std::set >::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 (aGroupsEntities.size() <= 1) @@ -706,12 +755,35 @@ bool SketchSolver_ConstraintGroup::updateGroup() std::map, Slvs_hConstraint>::reverse_iterator aConstrIter = myConstraintMap.rbegin(); bool isAllValid = true; - for ( ; isAllValid && aConstrIter != myConstraintMap.rend(); aConstrIter++) + bool isCCRemoved = false; // indicates that at least one of coincidence constraints was removed + while (isAllValid && aConstrIter != myConstraintMap.rend()) + { if (!aConstrIter->first->data()->isValid()) { - removeConstraint(aConstrIter->first); + if (aConstrIter->first->getKind().compare(SKETCH_CONSTRAINT_COINCIDENCE_KIND) == 0) + isCCRemoved = true; + std::map, Slvs_hConstraint>::reverse_iterator + aCopyIter = aConstrIter++; + removeConstraint(aCopyIter->first); isAllValid = false; } + else aConstrIter++; + } + + // 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< boost::shared_ptr > anExtraCopy = myExtraCoincidence; + myExtraCoincidence.clear(); + + std::set< boost::shared_ptr >::iterator + aCIter = anExtraCopy.begin(); + for ( ; aCIter != anExtraCopy.end(); aCIter++) + if ((*aCIter)->data()->isValid()) + changeConstraint(*aCIter); + } + return !isAllValid; } @@ -720,7 +792,7 @@ bool SketchSolver_ConstraintGroup::updateGroup() // Class: SketchSolver_ConstraintGroup // Purpose: update features of sketch after resolving constraints // ============================================================================ -void SketchSolver_ConstraintGroup::updateAttribute( +bool SketchSolver_ConstraintGroup::updateAttribute( boost::shared_ptr theAttribute, const Slvs_hEntity& theEntityID) { @@ -735,10 +807,16 @@ void SketchSolver_ConstraintGroup::updateAttribute( boost::dynamic_pointer_cast(theAttribute); if (aPoint) { - aPoint->setValue(myParams[aFirstParamPos].val, - myParams[aFirstParamPos+1].val, - myParams[aFirstParamPos+2].val); - return ; + if (fabs(aPoint->x() - myParams[aFirstParamPos].val) > tolerance || + fabs(aPoint->y() - myParams[aFirstParamPos+1].val) > tolerance || + fabs(aPoint->z() - myParams[aFirstParamPos+2].val) > tolerance) + { + aPoint->setValue(myParams[aFirstParamPos].val, + myParams[aFirstParamPos+1].val, + myParams[aFirstParamPos+2].val); + return true; + } + return false; } // Point in 2D @@ -746,21 +824,31 @@ void SketchSolver_ConstraintGroup::updateAttribute( boost::dynamic_pointer_cast(theAttribute); if (aPoint2D) { - aPoint2D->setValue(myParams[aFirstParamPos].val, - myParams[aFirstParamPos+1].val); - return ; + if (fabs(aPoint2D->x() - myParams[aFirstParamPos].val) > tolerance || + fabs(aPoint2D->y() - myParams[aFirstParamPos+1].val) > tolerance) + { + aPoint2D->setValue(myParams[aFirstParamPos].val, + myParams[aFirstParamPos+1].val); + return true; + } + return false; } // Scalar value - boost::shared_ptr aScalar = + AttributeDoublePtr aScalar = boost::dynamic_pointer_cast(theAttribute); if (aScalar) { - aScalar->setValue(myParams[aFirstParamPos].val); - return ; + if (fabs(aScalar->value() - myParams[aFirstParamPos].val) > tolerance) + { + aScalar->setValue(myParams[aFirstParamPos].val); + return true; + } + return false; } /// \todo Support other types of entities + return false; } // ============================================================================ @@ -771,7 +859,7 @@ void SketchSolver_ConstraintGroup::updateAttribute( void SketchSolver_ConstraintGroup::updateEntityIfPossible( boost::shared_ptr theEntity) { - if (myEntityMap.find(theEntity) != myEntityMap.end()) + if (myEntityAttrMap.find(theEntity) != myEntityAttrMap.end()) { // If the attribute is a point and it is changed (the group needs to rebuild), // probably user has dragged this point into this position, @@ -796,6 +884,9 @@ void SketchSolver_ConstraintGroup::updateEntityIfPossible( // Restore flag of changes myNeedToSolve = myNeedToSolve || aNeedToSolveCopy; + + if (myNeedToSolve) + updateRelatedConstraints(theEntity); } } @@ -810,8 +901,8 @@ void SketchSolver_ConstraintGroup::addTemporaryConstraintWhereDragged( { // Find identifier of the entity std::map, Slvs_hEntity>::const_iterator - anEntIter = myEntityMap.find(theEntity); - if (anEntIter == myEntityMap.end()) + anEntIter = myEntityAttrMap.find(theEntity); + if (anEntIter == myEntityAttrMap.end()) return ; // If this is a first dragged point, its parameters should be placed @@ -926,17 +1017,30 @@ void SketchSolver_ConstraintGroup::removeConstraint(boost::shared_ptr, Slvs_hEntity>::iterator - anEntMapIter = myEntityMap.begin(); - while (anEntMapIter != myEntityMap.end()) + anEntAttrIter = myEntityAttrMap.begin(); + while (anEntAttrIter != myEntityAttrMap.end()) { - if (anEntToRemove.find(anEntMapIter->second) != anEntToRemove.end()) + if (anEntToRemove.find(anEntAttrIter->second) != anEntToRemove.end()) { std::map, Slvs_hEntity>::iterator - aRemovedIter = anEntMapIter; - anEntMapIter++; - myEntityMap.erase(aRemovedIter); + aRemovedIter = anEntAttrIter; + anEntAttrIter++; + myEntityAttrMap.erase(aRemovedIter); } - else anEntMapIter++; + else anEntAttrIter++; + } + std::map::iterator + anEntFeatIter = myEntityFeatMap.begin(); + while (anEntFeatIter != myEntityFeatMap.end()) + { + if (anEntToRemove.find(anEntFeatIter->second) != anEntToRemove.end()) + { + std::map::iterator + aRemovedIter = anEntFeatIter; + anEntFeatIter++; + myEntityFeatMap.erase(aRemovedIter); + } + else anEntFeatIter++; } std::set::const_reverse_iterator aRemIter = anEntToRemove.rbegin(); for ( ; aRemIter != anEntToRemove.rend(); aRemIter++) @@ -962,6 +1066,121 @@ void SketchSolver_ConstraintGroup::removeConstraint(boost::shared_ptrerase(*aRemIter); } + if (myCoincidentPoints.size() == 1 && myCoincidentPoints.front().empty()) + myCoincidentPoints.clear(); +} + + +// ============================================================================ +// Function: addCoincidentPoints +// Class: SketchSolver_ConstraintGroup +// Purpose: add coincident point the appropriate list of such points +// ============================================================================ +bool SketchSolver_ConstraintGroup::addCoincidentPoints( + const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) +{ + std::vector< std::set >::iterator aCoPtIter = myCoincidentPoints.begin(); + std::vector< std::set >::iterator aFirstFound = myCoincidentPoints.end(); + while (aCoPtIter != myCoincidentPoints.end()) + { + bool isFound[2] = { // indicate which point ID was already in coincidence constraint + aCoPtIter->find(thePoint1) != aCoPtIter->end(), + aCoPtIter->find(thePoint2) != aCoPtIter->end(), + }; + if (isFound[0] && isFound[1]) // points are already connected by coincidence constraints => no need additional one + return false; + if ((isFound[0] && !isFound[1]) || (!isFound[0] && isFound[1])) + { + if (aFirstFound != myCoincidentPoints.end()) + { // there are two groups of coincident points connected by created constraint => merge them + int aFirstFoundShift = aFirstFound - myCoincidentPoints.begin(); + int aCurrentShift = aCoPtIter - myCoincidentPoints.begin(); + aFirstFound->insert(aCoPtIter->begin(), aCoPtIter->end()); + myCoincidentPoints.erase(aCoPtIter); + aFirstFound = myCoincidentPoints.begin() + aFirstFoundShift; + aCoPtIter = myCoincidentPoints.begin() + aCurrentShift; + continue; + } + else + { + aCoPtIter->insert(isFound[0] ? thePoint2 : thePoint1); + aFirstFound = aCoPtIter; + } + } + aCoPtIter++; + } + // No points were found, need to create new set + if (aFirstFound == myCoincidentPoints.end()) + { + std::set aNewSet; + aNewSet.insert(thePoint1); + aNewSet.insert(thePoint2); + myCoincidentPoints.push_back(aNewSet); + } + + return true; +} + + +// ============================================================================ +// Function: updateRelatedConstraints +// Class: SketchSolver_ConstraintGroup +// Purpose: emit the signal to update constraints +// ============================================================================ +void SketchSolver_ConstraintGroup::updateRelatedConstraints( + boost::shared_ptr theEntity) const +{ + std::map, Slvs_hConstraint>::const_iterator + aConstrIter = myConstraintMap.begin(); + for ( ; aConstrIter != myConstraintMap.end(); aConstrIter++) + { + std::list< boost::shared_ptr > anAttributes = + aConstrIter->first->data()->attributes(std::string()); + + std::list< boost::shared_ptr >::iterator + anAttrIter = anAttributes.begin(); + for ( ; anAttrIter != anAttributes.end(); anAttrIter++) + { + bool isUpd = (*anAttrIter == theEntity); + boost::shared_ptr aRefAttr = + boost::dynamic_pointer_cast(*anAttrIter); + if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theEntity) + isUpd = true; + + if (isUpd) + { + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent); + break; + } + } + } +} + +void SketchSolver_ConstraintGroup::updateRelatedConstraints( + boost::shared_ptr theFeature) const +{ + std::map, Slvs_hConstraint>::const_iterator + aConstrIter = myConstraintMap.begin(); + for ( ; aConstrIter != myConstraintMap.end(); aConstrIter++) + { + std::list< boost::shared_ptr > anAttributes = + aConstrIter->first->data()->attributes(std::string()); + + std::list< boost::shared_ptr >::iterator + anAttrIter = anAttributes.begin(); + for ( ; anAttrIter != anAttributes.end(); anAttrIter++) + { + boost::shared_ptr aRefAttr = + boost::dynamic_pointer_cast(*anAttrIter); + if (aRefAttr && aRefAttr->isObject() && aRefAttr->object() == theFeature) + { + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent); + break; + } + } + } } @@ -977,7 +1196,7 @@ int Search(const uint32_t& theEntityID, const std::vector& theEntities) int aVecSize = theEntities.size(); while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID) aResIndex--; - while (aResIndex < aVecSize && theEntities[aResIndex].h < theEntityID) + while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID) aResIndex++; if (aResIndex == -1) aResIndex = aVecSize;