#include <SketchSolver_Constraint.h>
+#include <Events_Error.h>
#include <Events_Loop.h>
#include <GeomDataAPI_Dir.h>
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeRefList.h>
-#include <Model_Events.h>
+#include <ModelAPI_Events.h>
#include <SketchPlugin_Constraint.h>
+#include <SketchPlugin_ConstraintLength.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
/// 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;
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<ModelAPI_Feature>(aCAttrRef->object()))
+ != myEntityFeatMap.end())
return true;
}
// Create constraint parameters
double aDistance = 0.0; // scalar value of the constraint
- boost::shared_ptr<ModelAPI_AttributeDouble> aDistAttr =
+ AttributeDoublePtr aDistAttr =
boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(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;
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<ModelAPI_Data> 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<ModelAPI_Feature>(aConstrAttr->object())] = 0;
+ break; // there should be no other entities
+ }
+ else if (aConstrAttr->isObject())
+ aConstrEnt[indAttr] = changeEntity(boost::dynamic_pointer_cast<ModelAPI_Feature>(aConstrAttr->object()));
+ else
+ aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr());
}
if (aConstrMapIter == myConstraintMap.end())
// Try to find sequence of coincident points which connects the points of new constraint
if (aConstrType == SLVS_C_POINTS_COINCIDENT)
{
- std::vector< std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
- std::vector< std::set<Slvs_hEntity> >::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<Slvs_hEntity> 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;
}
}
{
// If the entity is already in the group, try to find it
std::map<boost::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator
- aEntIter = myEntityMap.find(theEntity);
+ aEntIter = myEntityAttrMap.find(theEntity);
std::vector<Slvs_Param>::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
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
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;
}
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<ModelAPI_AttributeDouble> aScalar =
+ AttributeDoublePtr aScalar =
boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(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<FeaturePtr, Slvs_hEntity>::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<SketchPlugin_Feature> aFeature =
boost::dynamic_pointer_cast<SketchPlugin_Feature>(theEntity);
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;
// Try to find existent normal
std::map<boost::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator
- aEntIter = myEntityMap.find(theNorm);
+ aEntIter = myEntityAttrMap.find(theNorm);
std::vector<Slvs_Param>::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
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;
}
bool SketchSolver_ConstraintGroup::addWorkplane(
boost::shared_ptr<SketchPlugin_Feature> 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;
if (!myConstrSolver.getResult(myParams))
return;
+ // We should go through the attributes map, because only attributes have valued parameters
std::map<boost::shared_ptr<ModelAPI_Attribute>, 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;
else if (!theGroup.myTempPointWhereDragged.empty())
{ // Need to create additional transient constraint
std::map<boost::shared_ptr<ModelAPI_Attribute>, 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);
Slvs_hEntity aConstrEnt[] = {
aConstrIter->ptA, aConstrIter->ptB,
aConstrIter->entityA, aConstrIter->entityB};
+ std::vector<int> anIndexes;
// Go through the groupped entities and find even one of entities of current constraint
std::vector< std::set<Slvs_hEntity> >::iterator aGrEntIter;
for (aGrEntIter = aGroupsEntities.begin(); aGrEntIter != aGroupsEntities.end(); aGrEntIter++)
if (aConstrEnt[i] != 0)
isFound = (aGrEntIter->find(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<Slvs_hEntity> aNewGrEnt;
for (int i = 0; i < 4; i++)
if (aNewGrEnt.size() > 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<Slvs_hEntity> >::iterator aFirstGroup =
+ aGroupsEntities.begin() + anIndexes.front();
+ std::vector< std::set<Slvs_hConstraint> >::iterator aFirstConstr =
+ aGroupsConstr.begin() + anIndexes.front();
+ std::vector<int>::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)
std::map<boost::shared_ptr<SketchPlugin_Constraint>, 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<boost::shared_ptr<SketchPlugin_Constraint>, 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<SketchPlugin_Constraint> > anExtraCopy = myExtraCoincidence;
+ myExtraCoincidence.clear();
+
+ std::set< boost::shared_ptr<SketchPlugin_Constraint> >::iterator
+ aCIter = anExtraCopy.begin();
+ for ( ; aCIter != anExtraCopy.end(); aCIter++)
+ if ((*aCIter)->data()->isValid())
+ changeConstraint(*aCIter);
+ }
+
return !isAllValid;
}
// Class: SketchSolver_ConstraintGroup
// Purpose: update features of sketch after resolving constraints
// ============================================================================
-void SketchSolver_ConstraintGroup::updateAttribute(
+bool SketchSolver_ConstraintGroup::updateAttribute(
boost::shared_ptr<ModelAPI_Attribute> theAttribute,
const Slvs_hEntity& theEntityID)
{
boost::dynamic_pointer_cast<GeomDataAPI_Point>(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
boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(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<ModelAPI_AttributeDouble> aScalar =
+ AttributeDoublePtr aScalar =
boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(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;
}
// ============================================================================
void SketchSolver_ConstraintGroup::updateEntityIfPossible(
boost::shared_ptr<ModelAPI_Attribute> 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,
// Restore flag of changes
myNeedToSolve = myNeedToSolve || aNeedToSolveCopy;
+
+ if (myNeedToSolve)
+ updateRelatedConstraints(theEntity);
}
}
{
// Find identifier of the entity
std::map<boost::shared_ptr<ModelAPI_Attribute>, 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
// Remove unused entities
std::map<boost::shared_ptr<ModelAPI_Attribute>, 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<boost::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::iterator
- aRemovedIter = anEntMapIter;
- anEntMapIter++;
- myEntityMap.erase(aRemovedIter);
+ aRemovedIter = anEntAttrIter;
+ anEntAttrIter++;
+ myEntityAttrMap.erase(aRemovedIter);
}
- else anEntMapIter++;
+ else anEntAttrIter++;
+ }
+ std::map<FeaturePtr, Slvs_hEntity>::iterator
+ anEntFeatIter = myEntityFeatMap.begin();
+ while (anEntFeatIter != myEntityFeatMap.end())
+ {
+ if (anEntToRemove.find(anEntFeatIter->second) != anEntToRemove.end())
+ {
+ std::map<FeaturePtr, Slvs_hEntity>::iterator
+ aRemovedIter = anEntFeatIter;
+ anEntFeatIter++;
+ myEntityFeatMap.erase(aRemovedIter);
+ }
+ else anEntFeatIter++;
}
std::set<Slvs_hEntity>::const_reverse_iterator aRemIter = anEntToRemove.rbegin();
for ( ; aRemIter != anEntToRemove.rend(); aRemIter++)
for ( ; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++)
aCoPtIter->erase(*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<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
+ std::vector< std::set<Slvs_hEntity> >::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<Slvs_hEntity> 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<ModelAPI_Attribute> theEntity) const
+{
+ std::map<boost::shared_ptr<SketchPlugin_Constraint>, Slvs_hConstraint>::const_iterator
+ aConstrIter = myConstraintMap.begin();
+ for ( ; aConstrIter != myConstraintMap.end(); aConstrIter++)
+ {
+ std::list< boost::shared_ptr<ModelAPI_Attribute> > anAttributes =
+ aConstrIter->first->data()->attributes(std::string());
+
+ std::list< boost::shared_ptr<ModelAPI_Attribute> >::iterator
+ anAttrIter = anAttributes.begin();
+ for ( ; anAttrIter != anAttributes.end(); anAttrIter++)
+ {
+ bool isUpd = (*anAttrIter == theEntity);
+ boost::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*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<ModelAPI_Feature> theFeature) const
+{
+ std::map<boost::shared_ptr<SketchPlugin_Constraint>, Slvs_hConstraint>::const_iterator
+ aConstrIter = myConstraintMap.begin();
+ for ( ; aConstrIter != myConstraintMap.end(); aConstrIter++)
+ {
+ std::list< boost::shared_ptr<ModelAPI_Attribute> > anAttributes =
+ aConstrIter->first->data()->attributes(std::string());
+
+ std::list< boost::shared_ptr<ModelAPI_Attribute> >::iterator
+ anAttrIter = anAttributes.begin();
+ for ( ; anAttrIter != anAttributes.end(); anAttrIter++)
+ {
+ boost::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*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;
+ }
+ }
+ }
}
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;