myDOF = 0;
}
-void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
+void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint,
+ const SketchSolver_ConstraintType theType)
{
myEquationSystem->addConstraint(theConstraint.get());
myConstraints[theConstraint->getTag()].insert(theConstraint);
myDOF = -1;
+
+ // Workaround: avoid tangent constraint in the list of redundant
+ if (theType == CONSTRAINT_TANGENT_CIRCLE_LINE ||
+ theType == CONSTRAINT_TANGENT_CIRCLE_CIRCLE)
+ myTangentIDs.insert(theConstraint->getTag());
}
void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID)
{
myConstraints.erase(theID);
+ myTangentIDs.erase(theID);
if (myConstraints.empty()) {
myEquationSystem->clear();
myDOF = (int)myParameters.size();
GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
Events_LongOp::end(this);
+ GCS::VEC_I aRedundant;
+ myEquationSystem->getRedundant(aRedundant);
+ if (!aRedundant.empty())
+ aResult = GCS::Failed;
+
SolveStatus aStatus;
if (aResult == GCS::Success) {
myEquationSystem->applySolution();
myConflictingIDs.insert(aConflict.begin(), aConflict.end());
myEquationSystem->getRedundant(aConflict);
+ // Workaround: avoid conflicting tangent constraints
+ GCS::VEC_I aTemp = aConflict;
+ aConflict.clear();
+ for (GCS::VEC_I::iterator anIt = aTemp.begin(); anIt != aTemp.end(); ++anIt)
+ if (myTangentIDs.find(*anIt) == myTangentIDs.end())
+ aConflict.push_back(*anIt);
myConflictingIDs.insert(aConflict.begin(), aConflict.end());
myConfCollected = true;
void clear();
/// \brief Add constraint to the system of equations
- void addConstraint(GCSConstraintPtr theConstraint);
+ void addConstraint(GCSConstraintPtr theConstraint, const SketchSolver_ConstraintType theType);
/// \brief Remove constraint from the system of equations
void removeConstraint(ConstraintID theID);
GCS::VEC_pD myParameters; ///< list of unknowns
ConstraintMap myConstraints; ///< list of constraints
+ GCS::SET_I myTangentIDs; ///< IDs of tangent constraints
std::shared_ptr<GCS::System> myEquationSystem; ///< set of equations for solving in FreeGCS
static void constraintsToSolver(const ConstraintWrapperPtr& theConstraint,
const SolverPtr& theSolver)
{
- std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
- std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
- if (!aSolver)
- return;
-
const std::list<GCSConstraintPtr>& aConstraints =
std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint)->constraints();
std::list<GCSConstraintPtr>::const_iterator anIt = aConstraints.begin();
for (; anIt != aConstraints.end(); ++anIt)
- aSolver->addConstraint(*anIt);
+ theSolver->addConstraint(*anIt, theConstraint->type());
}
// Remove constraint
myConstraintMap.erase(aFound);
+ if (anID != CID_MOVEMENT)
+ myNeedToResolve = true;
+
// notify subscibers
notify(theConstraint);
}
myNext->update(theFeature);
}
+static bool hasExternalPoint(const std::set<EntityWrapperPtr>& theCoincidences)
+{
+ std::set<EntityWrapperPtr>::const_iterator anIt = theCoincidences.begin();
+ for (; anIt != theCoincidences.end(); ++anIt)
+ if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal())
+ return true;
+ return false;
+}
+
bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence(
const EntityWrapperPtr& theEntity1,
const EntityWrapperPtr& theEntity2)
myCoincident.push_back(aNewCoinc);
} else if (aFound1 == aFound2) // same group => already coincident
isAccepted = false;
- else if (aFound1 == myCoincident.end())
- aFound2->insert(theEntity1);
- else if (aFound2 == myCoincident.end())
- aFound1->insert(theEntity2);
- else { // merge two groups
- aFound1->insert(aFound2->begin(), aFound2->end());
- myCoincident.erase(aFound2);
+ else {
+ if (theEntity1->type() == ENTITY_POINT && theEntity2->type() == ENTITY_POINT &&
+ (theEntity1->isExternal() || theEntity2->isExternal())) {
+ bool hasExternal = aFound1 != myCoincident.end() && hasExternalPoint(*aFound1);
+ hasExternal = hasExternal || (aFound2 != myCoincident.end() && hasExternalPoint(*aFound2));
+ if (hasExternal)
+ isAccepted = false;
+ }
+
+ if (aFound1 == myCoincident.end())
+ aFound2->insert(theEntity1);
+ else if (aFound2 == myCoincident.end())
+ aFound1->insert(theEntity2);
+ else { // merge two groups
+ aFound1->insert(aFound2->begin(), aFound2->end());
+ myCoincident.erase(aFound2);
+ }
}
return isAccepted;
void SketchSolver_Group::removeTemporaryConstraints()
{
if (!myTempConstraints.empty()) {
- std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(
- mySketchSolver)->removeConstraint(CID_MOVEMENT);
+ mySketchSolver->removeConstraint(CID_MOVEMENT);
std::set<SolverConstraintPtr>::iterator aTmpIt = myTempConstraints.begin();
for (; aTmpIt != myTempConstraints.end(); ++aTmpIt)
std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
aConstrIt = myConstraintMap.begin();
for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
- if (theSolver->isConflicting(aConstrIt->second->id())) {
+ if (theSolver->isConflicting(aConstrIt->second->id()))
aConflicting.insert(aConstrIt->first);
- break;
- }
}
return aConflicting;
}