Salome HOME
Update copyrights
[modules/shaper.git] / src / SketchSolver / SolveSpaceSolver / SolveSpaceSolver_Solver.cpp
1 // Copyright (C) 2014-2019  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "SolveSpaceSolver_Solver.h"
21 #include <Events_LongOp.h>
22
23 SolveSpaceSolver_Solver::SolveSpaceSolver_Solver()
24 {
25   // Nullify all elements of the set of equations
26   myEquationsSystem.param = 0;
27   myEquationsSystem.params = 0;
28   myEquationsSystem.entity = 0;
29   myEquationsSystem.entities = 0;
30   myEquationsSystem.constraint = 0;
31   myEquationsSystem.constraints = 0;
32   myEquationsSystem.failed = 0;
33   myEquationsSystem.faileds = 0;
34
35   myEquationsSystem.dragged[0] = 0;
36   myEquationsSystem.dragged[1] = 0;
37   myEquationsSystem.dragged[2] = 0;
38   myEquationsSystem.dragged[3] = 0;
39
40   // If the set of constraints is inconsistent,
41   // the failed field will contain wrong constraints
42   myEquationsSystem.calculateFaileds = 0;
43
44   myParamsCopy = 0;
45 }
46
47 SolveSpaceSolver_Solver::~SolveSpaceSolver_Solver()
48 {
49   if (myEquationsSystem.constraint)
50     delete[] myEquationsSystem.constraint;
51   myEquationsSystem.constraint = 0;
52   if (myEquationsSystem.failed)
53     delete[] myEquationsSystem.failed;
54   myEquationsSystem.failed = 0;
55   if (myParamsCopy)
56     delete [] myParamsCopy;
57   myParamsCopy = 0;
58 }
59
60 void SolveSpaceSolver_Solver::setParameters(Slvs_Param* theParameters, int theSize)
61 {
62   myEquationsSystem.param = theParameters;
63   myEquationsSystem.params = theSize;
64 }
65
66
67 void SolveSpaceSolver_Solver::setDraggedParameters(const Slvs_hParam* theDragged)
68 {
69   for (unsigned int i = 0; i < 4; i++)
70     myEquationsSystem.dragged[i] = theDragged[i];
71 }
72
73 void SolveSpaceSolver_Solver::setEntities(Slvs_Entity* theEntities, int theSize)
74 {
75   myEquationsSystem.entity = theEntities;
76   myEquationsSystem.entities = theSize;
77 }
78
79 void SolveSpaceSolver_Solver::setConstraints(Slvs_Constraint* theConstraints, int theSize)
80 {
81   if (!myEquationsSystem.constraint) {
82     myEquationsSystem.constraint = new Slvs_Constraint[theSize];
83     myEquationsSystem.constraints = theSize;
84     myEquationsSystem.failed = new Slvs_hConstraint[theSize];
85   }
86   else if (myEquationsSystem.constraints != theSize) {
87     if (theSize > myEquationsSystem.constraints) {
88       delete[] myEquationsSystem.constraint;
89       myEquationsSystem.constraint = new Slvs_Constraint[theSize];
90       if (myEquationsSystem.failed)
91         delete[] myEquationsSystem.failed;
92       myEquationsSystem.failed = new Slvs_hConstraint[theSize];
93     }
94     myEquationsSystem.constraints = theSize;
95   }
96   memcpy(myEquationsSystem.constraint, theConstraints, theSize * sizeof(Slvs_Constraint));
97   memset(myEquationsSystem.failed, SLVS_C_UNKNOWN, theSize * sizeof(Slvs_hConstraint));
98 }
99
100
101 SketchSolver_SolveStatus SolveSpaceSolver_Solver::solve()
102 {
103   //if (myEquationsSystem.constraints <= 0)
104   //  return STATUS_EMPTYSET;
105
106   myEquationsSystem.calculateFaileds = 0;
107   if (myFindFaileds) {
108     myEquationsSystem.calculateFaileds = 1;
109     myEquationsSystem.faileds = myEquationsSystem.constraints;
110   }
111
112   Events_LongOp::start(this);
113   Slvs_Solve(&myEquationsSystem, (Slvs_hGroup)myGroup);
114   Events_LongOp::end(this);
115
116   SketchSolver_SolveStatus aStatus;
117   switch (myEquationsSystem.result) {
118   case SLVS_RESULT_OKAY:
119     aStatus = STATUS_OK;
120     break;
121   case SLVS_RESULT_INCONSISTENT:
122   case SLVS_RESULT_DIDNT_CONVERGE:
123   case SLVS_RESULT_TOO_MANY_UNKNOWNS:
124     aStatus = STATUS_INCONSISTENT;
125     break;
126   default:
127     aStatus = STATUS_FAILED;
128   }
129
130   if (aStatus == STATUS_OK) {
131     // additional verification of arcs to be non-degenerated
132     if (hasDegeneratedArcs()) {
133       undo();
134       aStatus = STATUS_INCONSISTENT;
135     }
136   }
137
138   return aStatus;
139 }
140
141 void SolveSpaceSolver_Solver::prepare()
142 {
143   // make a copy of parameters to be able to make undo
144   if (myParamsCopy)
145     delete [] myParamsCopy;
146   myParamsCopy = new Slvs_Param[myEquationsSystem.params];
147   memcpy(myParamsCopy, myEquationsSystem.param, myEquationsSystem.params * sizeof(Slvs_Param));
148 }
149
150 void SolveSpaceSolver_Solver::undo()
151 {
152   if (myParamsCopy) {
153     memcpy(myEquationsSystem.param, myParamsCopy, myEquationsSystem.params * sizeof(Slvs_Param));
154     delete [] myParamsCopy;
155   }
156   myParamsCopy = 0;
157 }
158
159
160 bool SolveSpaceSolver_Solver::hasDegeneratedArcs() const
161 {
162   const double aTol2 = tolerance * tolerance;
163   double anArcPoints[3][2];
164
165   for (int anEnt = 0; anEnt < myEquationsSystem.entities; ++anEnt) {
166     const Slvs_Entity& anEntity = myEquationsSystem.entity[anEnt];
167     if (anEntity.type != SLVS_E_ARC_OF_CIRCLE)
168       continue;
169
170     for (int aPnt = 0; aPnt < 3; ++aPnt) {
171       // search point of arc
172       const int aShift = anEntity.point[aPnt] - anEntity.h;
173       int aPntInd = anEnt + aShift;
174       int aStep = 1;
175       if (aPntInd < 0)
176         aPntInd = 0;
177       else if (aPntInd >= myEquationsSystem.entities)
178         aPntInd = myEquationsSystem.entities - 1;
179       if (myEquationsSystem.entity[aPntInd].h > anEntity.point[aPnt])
180         aStep = -1;
181       for (; aPntInd >=0 && aPntInd < myEquationsSystem.entities; aPntInd += aStep)
182         if (myEquationsSystem.entity[aPntInd].h == anEntity.point[aPnt])
183           break;
184
185       // search coordinates of the point
186       int aParamInd = myEquationsSystem.entity[aPntInd].param[0];
187       if (aParamInd >= myEquationsSystem.params) {
188         aParamInd = myEquationsSystem.params - 1;
189         aStep = -1;
190       }
191       else if ((int)myEquationsSystem.param[aParamInd].h > aParamInd)
192         aStep = -1;
193       else aStep = 1;
194
195       for (; aParamInd >=0 && aParamInd < myEquationsSystem.params; aParamInd += aStep)
196         if (myEquationsSystem.param[aParamInd].h == myEquationsSystem.entity[aPntInd].param[0])
197           break;
198       anArcPoints[aPnt][0] = myEquationsSystem.param[aParamInd].val;
199       anArcPoints[aPnt][1] = myEquationsSystem.param[aParamInd+1].val;
200     }
201
202     // check radius of arc
203     anArcPoints[1][0] -= anArcPoints[0][0];
204     anArcPoints[1][1] -= anArcPoints[0][1];
205     anArcPoints[2][0] -= anArcPoints[0][0];
206     anArcPoints[2][1] -= anArcPoints[0][1];
207     if (anArcPoints[1][0] * anArcPoints[1][0] + anArcPoints[1][1] * anArcPoints[1][1] < aTol2 ||
208         anArcPoints[2][0] * anArcPoints[2][0] + anArcPoints[2][1] * anArcPoints[2][1] < aTol2)
209       return true;
210   }
211   return false;
212 }
213
214 bool SolveSpaceSolver_Solver::isConflicting(const ConstraintID& theConstraint) const
215 {
216   for (int i = 0; i < myEquationsSystem.faileds; ++i)
217     if (myEquationsSystem.failed[i] == (Slvs_hConstraint)theConstraint)
218       return true;
219   return false;
220 }
221
222 int SolveSpaceSolver_Solver::dof() const
223 {
224   return myEquationsSystem.dof;
225 }