Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_Solver.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <PlaneGCSSolver_Solver.h>
22 #include <Events_LongOp.h>
23
24
25 PlaneGCSSolver_Solver::PlaneGCSSolver_Solver()
26   : myEquationSystem(new GCS::System),
27     myDiagnoseBeforeSolve(false),
28     myInitilized(false),
29     myConfCollected(false),
30     myDOF(0)
31 {
32 }
33
34 PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
35 {
36   clear();
37 }
38
39 void PlaneGCSSolver_Solver::clear()
40 {
41   myEquationSystem->clear();
42   myParameters.clear();
43   myConstraints.clear();
44   myConflictingIDs.clear();
45   myDOF = 0;
46 }
47
48 void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
49 {
50   myEquationSystem->addConstraint(theConstraint.get());
51   myConstraints[theConstraint->getTag()].insert(theConstraint);
52   if (theConstraint->getTag() >= 0)
53     myDOF = -1;
54   myInitilized = false;
55 }
56
57 void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID)
58 {
59   myConstraints.erase(theID);
60   if (myConstraints.empty()) {
61     myEquationSystem->clear();
62     myDOF = (int)myParameters.size();
63   } else {
64     myEquationSystem->clearByTag(theID);
65     if (theID >= 0)
66       myDOF = -1;
67   }
68   myInitilized = false;
69 }
70
71 double* PlaneGCSSolver_Solver::createParameter()
72 {
73   double* aResult = new double(0);
74   myParameters.push_back(aResult);
75   if (myConstraints.empty() && myDOF >= 0)
76     ++myDOF; // calculate DoF by hand if and only if there is no constraints yet
77   else
78     myDiagnoseBeforeSolve = true;
79   return aResult;
80 }
81
82 void PlaneGCSSolver_Solver::addParameters(const GCS::SET_pD& theParams)
83 {
84   GCS::SET_pD aParams(theParams);
85   // leave new parameters only
86   GCS::VEC_pD::iterator anIt = myParameters.begin();
87   for (; anIt != myParameters.end(); ++anIt)
88     if (aParams.find(*anIt) != aParams.end())
89       aParams.erase(*anIt);
90
91   myParameters.insert(myParameters.end(), aParams.begin(), aParams.end());
92   if (myConstraints.empty() && myDOF >=0)
93     myDOF += (int)aParams.size(); // calculate DoF by hand only if there is no constraints yet
94   else
95     myDiagnoseBeforeSolve = true;
96 }
97
98 void PlaneGCSSolver_Solver::removeParameters(const GCS::SET_pD& theParams)
99 {
100   for (int i = (int)myParameters.size() - 1; i >= 0; --i)
101     if (theParams.find(myParameters[i]) != theParams.end()) {
102       myParameters.erase(myParameters.begin() + i);
103       --myDOF;
104     }
105   if (!myConstraints.empty())
106     myDiagnoseBeforeSolve = true;
107 }
108
109 void PlaneGCSSolver_Solver::initialize()
110 {
111   Events_LongOp::start(this);
112   if (myDiagnoseBeforeSolve)
113     diagnose();
114   myEquationSystem->declareUnknowns(myParameters);
115   myEquationSystem->initSolution();
116   Events_LongOp::end(this);
117
118   myInitilized = true;
119 }
120
121 PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
122 {
123   // clear list of conflicting constraints
124   if (myConfCollected) {
125     myConflictingIDs.clear();
126     myConfCollected = false;
127   }
128
129   if (myParameters.empty())
130     return STATUS_INCONSISTENT;
131
132   GCS::SolveStatus aResult = GCS::Success;
133   Events_LongOp::start(this);
134   if (myInitilized) {
135     aResult = (GCS::SolveStatus)myEquationSystem->solve();
136   } else {
137     if (myDiagnoseBeforeSolve)
138       diagnose();
139     aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
140   }
141   Events_LongOp::end(this);
142
143   // collect information about conflicting constraints every time,
144   // sometimes solver reports about succeeded recalculation but has conflicting constraints
145   // (for example, apply horizontal constraint for a copied feature)
146   collectConflicting();
147   if (!myConflictingIDs.empty())
148     aResult = GCS::Failed;
149
150   SolveStatus aStatus;
151   if (aResult == GCS::Failed)
152     aStatus = STATUS_FAILED;
153   else {
154     myEquationSystem->applySolution();
155     if (myDOF < 0)
156       myDOF = myEquationSystem->dofsNumber();
157     aStatus = STATUS_OK;
158   }
159
160   myInitilized = false;
161   return aStatus;
162 }
163
164 void PlaneGCSSolver_Solver::undo()
165 {
166   myEquationSystem->undoSolution();
167 }
168
169 bool PlaneGCSSolver_Solver::isConflicting(const ConstraintID& theConstraint) const
170 {
171   if (!myConfCollected)
172     const_cast<PlaneGCSSolver_Solver*>(this)->collectConflicting();
173   return myConflictingIDs.find((int)theConstraint) != myConflictingIDs.end();
174 }
175
176 void PlaneGCSSolver_Solver::collectConflicting()
177 {
178   GCS::VEC_I aConflict;
179   myEquationSystem->getConflicting(aConflict);
180   myConflictingIDs.insert(aConflict.begin(), aConflict.end());
181
182   myEquationSystem->getRedundant(aConflict);
183   myConflictingIDs.insert(aConflict.begin(), aConflict.end());
184
185   myConfCollected = true;
186 }
187
188 int PlaneGCSSolver_Solver::dof()
189 {
190   if (myDOF < 0 && !myConstraints.empty())
191     diagnose();
192   return myDOF;
193 }
194
195 void PlaneGCSSolver_Solver::diagnose()
196 {
197   myEquationSystem->declareUnknowns(myParameters);
198   myDOF = myEquationSystem->diagnose();
199   myDiagnoseBeforeSolve = false;
200 }