]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
Salome HOME
Fix coincidence between rotated/translated entity and any other (issue #1607)
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_Solver.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    PlaneGCSSolver_Solver.cpp
4 // Created: 14 Dec 2014
5 // Author:  Artem ZHIDKOV
6
7 #include "PlaneGCSSolver_Solver.h"
8 #include <Events_LongOp.h>
9
10
11 PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
12 {
13   clear();
14 }
15
16 void PlaneGCSSolver_Solver::clear()
17 {
18   myEquationSystem.clear();
19   myConstraints.clear();
20   myParameters.clear();
21 }
22
23 void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
24 {
25   GCS::Constraint* aConstraint = theConstraint.get();
26   if (myConstraints.find(aConstraint) != myConstraints.end())
27     return; // constraint already exists, no need to add it again
28
29   myEquationSystem.addConstraint(aConstraint);
30   myConstraints.insert(aConstraint);
31 }
32
33 void PlaneGCSSolver_Solver::removeConstraint(GCSConstraintPtr theConstraint)
34 {
35   GCS::Constraint* aConstraint = theConstraint.get();
36   removeConstraint(aConstraint);
37 }
38
39 void PlaneGCSSolver_Solver::removeConstraint(GCS::Constraint* theConstraint)
40 {
41   if (myConstraints.find(theConstraint) == myConstraints.end())
42     return; // no constraint, no need to remove it
43
44   myEquationSystem.removeConstraint(theConstraint);
45   myConstraints.erase(theConstraint);
46 }
47
48 SketchSolver_SolveStatus PlaneGCSSolver_Solver::solve()
49 {
50   // clear list of conflicting constraints
51   if (myConfCollected) {
52     myConflictingIDs.clear();
53     myConfCollected = false;
54   }
55
56   if (myConstraints.empty())
57     return STATUS_EMPTYSET;
58   if (myParameters.empty())
59     return STATUS_INCONSISTENT;
60
61   Events_LongOp::start(this);
62   GCS::SolveStatus aResult = GCS::Success;
63   // if there is a constraint with all attributes constant, set fail status
64   GCS::SET_pD aParameters;
65   aParameters.insert(myParameters.begin(), myParameters.end());
66   std::set<GCS::Constraint*>::const_iterator aConstrIt = myConstraints.begin();
67   for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
68     GCS::VEC_pD aParams = (*aConstrIt)->params();
69     GCS::VEC_pD::const_iterator aPIt = aParams.begin();
70     for (; aPIt != aParams.end(); ++aPIt)
71       if (aParameters.find(*aPIt) != aParameters.end())
72         break;
73     if (aPIt == aParams.end() && (*aConstrIt)->getTag() > 0) {
74       myConflictingIDs.push_back((*aConstrIt)->getTag());
75       myConfCollected = true;
76       aResult = GCS::Failed;
77     }
78   }
79   // solve equations
80   if (aResult == GCS::Success)
81     aResult = (GCS::SolveStatus)myEquationSystem.solve(myParameters);
82   if (aResult == GCS::Success || aResult == GCS::Converged) {
83     // additionally check redundant constraints
84     GCS::VEC_I aRedundantID;
85     myEquationSystem.getRedundant(aRedundantID);
86     // Workaround: remove all constraints "Equal"
87     if (!aRedundantID.empty()) {
88       std::set<GCS::Constraint*>::const_iterator aCIt = myConstraints.begin();
89       for (; aCIt != myConstraints.end(); ++aCIt) {
90         if ((*aCIt)->getTypeId() != GCS::Equal)
91           continue;
92         GCS::VEC_I::iterator aRIt = aRedundantID.begin();
93         for (; aRIt != aRedundantID.end(); ++aRIt)
94           if ((*aCIt)->getTag() == *aRIt) {
95             aRedundantID.erase(aRIt);
96             break;
97           }
98       }
99     }
100     // The system with tangent constraints may show redundant constraints if the entities are coupled smoothly.
101     // Sometimes tangent constraints are fall to both conflicting and redundant constraints.
102     // Need to check if there are redundant constraints without these tangencies.
103     if (!aRedundantID.empty())
104       aResult = myTangent.empty() ? GCS::Failed : (GCS::SolveStatus)solveWithoutTangent();
105     else
106       aResult = GCS::Success;
107   }
108   Events_LongOp::end(this);
109
110   SketchSolver_SolveStatus aStatus;
111   if (aResult == GCS::Success) {
112     myEquationSystem.applySolution();
113     aStatus = STATUS_OK;
114   } else
115     aStatus = STATUS_FAILED;
116
117   return aStatus;
118 }
119
120 SketchSolver_SolveStatus PlaneGCSSolver_Solver::solveWithoutTangent()
121 {
122   // Remove tangency which leads to redundant or conflicting constraints
123   GCS::VEC_I aConflicting, aRedundant;
124   myEquationSystem.getRedundant(aRedundant);
125   size_t aNbRemove = myTangent.size(); // number of tangent constraints which can be removed
126   myEquationSystem.getConflicting(aConflicting);
127   aRedundant.insert(aRedundant.end(), aConflicting.begin(), aConflicting.end());
128
129   GCS::SET_I aTangentToRemove;
130   GCS::VEC_I::iterator aCIt = aRedundant.begin();
131   for (; aCIt != aRedundant.end() && aNbRemove > 0; ++aCIt)
132     if (myTangent.find(*aCIt) != myTangent.end()) {
133       aTangentToRemove.insert(*aCIt);
134       --aNbRemove;
135     }
136
137   std::set<GCS::Constraint*>::const_iterator aConstrIt = myConstraints.begin();
138   while (aConstrIt != myConstraints.end()) {
139     GCS::Constraint* aConstraint = *aConstrIt;
140     int anID = aConstraint->getTag();
141     ++aConstrIt;
142     if (aTangentToRemove.find(anID) != aTangentToRemove.end())
143       removeConstraint(aConstraint);
144   }
145
146   myTangent.clear();
147   return solve();
148 }
149
150 void PlaneGCSSolver_Solver::undo()
151 {
152   myEquationSystem.undoSolution();
153 }
154
155 bool PlaneGCSSolver_Solver::isConflicting(const ConstraintID& theConstraint) const
156 {
157   if (!myConfCollected)
158     const_cast<PlaneGCSSolver_Solver*>(this)->collectConflicting();
159
160   GCS::VEC_I::const_iterator anIt = myConflictingIDs.begin();
161   for (; anIt != myConflictingIDs.end(); ++anIt)
162     if (*anIt == (int)theConstraint)
163       return true;
164   return false;
165 }
166
167 void PlaneGCSSolver_Solver::collectConflicting()
168 {
169   GCS::VEC_I aConflict;
170   myEquationSystem.getConflicting(myConflictingIDs);
171   myConflictingIDs.insert(myConflictingIDs.end(), aConflict.begin(), aConflict.end());
172
173   myEquationSystem.getRedundant(aConflict);
174   myConflictingIDs.insert(myConflictingIDs.end(), aConflict.begin(), aConflict.end());
175
176   myConfCollected = true;
177 }
178
179 int PlaneGCSSolver_Solver::dof() const
180 {
181   return const_cast<PlaneGCSSolver_Solver*>(this)->myEquationSystem.dofsNumber();
182 }