Salome HOME
Fix incorrect processing of the copied entities after the "Multi" constraint has...
[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   : myEquationSystem(new GCS::System),
13     myDiagnoseBeforeSolve(false),
14     myInitilized(false),
15     myConfCollected(false),
16     myDOF(0)
17 {
18 }
19
20 PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
21 {
22   clear();
23 }
24
25 void PlaneGCSSolver_Solver::clear()
26 {
27   myEquationSystem->clear();
28   myParameters.clear();
29   myConstraints.clear();
30   myConflictingIDs.clear();
31   myDOF = 0;
32 }
33
34 void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
35 {
36   myEquationSystem->addConstraint(theConstraint.get());
37   myConstraints[theConstraint->getTag()].insert(theConstraint);
38   if (theConstraint->getTag() >= 0)
39     myDOF = -1;
40 }
41
42 void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID)
43 {
44   myConstraints.erase(theID);
45   if (myConstraints.empty()) {
46     myEquationSystem->clear();
47     myDOF = (int)myParameters.size();
48   } else {
49     myEquationSystem->clearByTag(theID);
50     if (theID >= 0)
51       myDOF = -1;
52   }
53 }
54
55 double* PlaneGCSSolver_Solver::createParameter()
56 {
57   double* aResult = new double(0);
58   myParameters.push_back(aResult);
59   if (myConstraints.empty() && myDOF >= 0)
60     ++myDOF; // calculate DoF by hand if and only if there is no constraints yet
61   else
62     myDiagnoseBeforeSolve = true;
63   return aResult;
64 }
65
66 void PlaneGCSSolver_Solver::addParameters(const GCS::SET_pD& theParams)
67 {
68   GCS::SET_pD aParams(theParams);
69   // leave new parameters only
70   GCS::VEC_pD::iterator anIt = myParameters.begin();
71   for (; anIt != myParameters.end(); ++anIt)
72     if (aParams.find(*anIt) != aParams.end())
73       aParams.erase(*anIt);
74
75   myParameters.insert(myParameters.end(), aParams.begin(), aParams.end());
76   if (myConstraints.empty() && myDOF >=0)
77     myDOF += (int)aParams.size(); // calculate DoF by hand if and only if there is no constraints yet
78   else
79     myDiagnoseBeforeSolve = true;
80 }
81
82 void PlaneGCSSolver_Solver::removeParameters(const GCS::SET_pD& theParams)
83 {
84   for (int i = (int)myParameters.size() - 1; i >= 0; --i)
85     if (theParams.find(myParameters[i]) != theParams.end()) {
86       myParameters.erase(myParameters.begin() + i);
87       --myDOF;
88     }
89   if (!myConstraints.empty())
90     myDiagnoseBeforeSolve = true;
91 }
92
93 void PlaneGCSSolver_Solver::initialize()
94 {
95   Events_LongOp::start(this);
96   if (myDiagnoseBeforeSolve)
97     diagnose();
98   myEquationSystem->declareUnknowns(myParameters);
99   myEquationSystem->initSolution();
100   Events_LongOp::end(this);
101
102   myInitilized = true;
103 }
104
105 PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
106 {
107   // clear list of conflicting constraints
108   if (myConfCollected) {
109     myConflictingIDs.clear();
110     myConfCollected = false;
111   }
112
113   if (myParameters.empty())
114     return STATUS_INCONSISTENT;
115
116   GCS::SolveStatus aResult = GCS::Success;
117   Events_LongOp::start(this);
118   if (myInitilized) {
119     aResult = (GCS::SolveStatus)myEquationSystem->solve();
120   } else {
121     if (myDiagnoseBeforeSolve)
122       diagnose();
123     aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
124   }
125   Events_LongOp::end(this);
126
127   // collect information about conflicting constraints every time,
128   // sometimes solver reports about succeeded recalculation but has conflicting constraints
129   // (for example, apply horizontal constraint for a copied feature)
130   collectConflicting();
131   if (!myConflictingIDs.empty())
132     aResult = GCS::Failed;
133
134   SolveStatus aStatus;
135   if (aResult == GCS::Failed)
136     aStatus = STATUS_FAILED;
137   else {
138     myEquationSystem->applySolution();
139     if (myDOF < 0)
140       myDOF = myEquationSystem->dofsNumber();
141     aStatus = STATUS_OK;
142   }
143
144   myInitilized = false;
145   return aStatus;
146 }
147
148 void PlaneGCSSolver_Solver::undo()
149 {
150   myEquationSystem->undoSolution();
151 }
152
153 bool PlaneGCSSolver_Solver::isConflicting(const ConstraintID& theConstraint) const
154 {
155   if (!myConfCollected)
156     const_cast<PlaneGCSSolver_Solver*>(this)->collectConflicting();
157   return myConflictingIDs.find((int)theConstraint) != myConflictingIDs.end();
158 }
159
160 void PlaneGCSSolver_Solver::collectConflicting()
161 {
162   GCS::VEC_I aConflict;
163   myEquationSystem->getConflicting(aConflict);
164   myConflictingIDs.insert(aConflict.begin(), aConflict.end());
165
166   myEquationSystem->getRedundant(aConflict);
167   myConflictingIDs.insert(aConflict.begin(), aConflict.end());
168
169   myConfCollected = true;
170 }
171
172 int PlaneGCSSolver_Solver::dof()
173 {
174   if (myDOF < 0 && !myConstraints.empty())
175     diagnose();
176   return myDOF;
177 }
178
179 void PlaneGCSSolver_Solver::diagnose()
180 {
181   myEquationSystem->declareUnknowns(myParameters);
182   myDOF = myEquationSystem->diagnose();
183   myDiagnoseBeforeSolve = false;
184 }