Salome HOME
Revert "First phase of SketchSolver refactoring"
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintMovement.cpp
1 #include <SketchSolver_ConstraintMovement.h>
2 #include <SketchSolver_Error.h>
3 #include <SketchSolver_Group.h>
4
5 #include <SketchPlugin_Arc.h>
6 #include <SketchPlugin_Circle.h>
7 #include <SketchPlugin_Line.h>
8 #include <SketchPlugin_Point.h>
9
10 SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature)
11   : SketchSolver_ConstraintRigid(theFeature)
12 {
13   process();
14 }
15
16 void SketchSolver_ConstraintMovement::process()
17 {
18   cleanErrorMsg();
19   if (!myBaseFeature || !myStorage || myGroup == 0) {
20     /// TODO: Put error message here
21     return;
22   }
23   if (!mySlvsConstraints.empty()) // some data is changed, update constraint
24     update(myBaseConstraint);
25
26   double aValue;
27   std::vector<Slvs_hEntity> anEntities;
28   bool isFullyMoved;
29   getAttributes(aValue, anEntities, isFullyMoved);
30   if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
31     return;
32
33   if (isFullyMoved)
34     fixFeature();
35   else {
36     std::vector<Slvs_hEntity>::iterator anEntIt = anEntities.begin();
37     for (; anEntIt != anEntities.end(); ++anEntIt)
38       fixPoint(*anEntIt);
39   }
40 }
41
42
43 void SketchSolver_ConstraintMovement::getAttributes(
44     double& theValue,
45     std::vector<Slvs_hEntity>& theAttributes,
46     bool& theIsFullyMoved)
47 {
48   bool isComplexFeature = false;
49   theValue = 0.0;
50   theIsFullyMoved = true;
51   int aType = SLVS_E_UNKNOWN; // type of created entity
52   Slvs_hEntity anEntityID = SLVS_E_UNKNOWN;
53   Slvs_hEntity anEntMaxID = myStorage->entityMaxID();
54   anEntityID = myGroup->getFeatureId(myBaseFeature);
55   if (anEntityID == SLVS_E_UNKNOWN) {
56     anEntityID = changeEntity(myBaseFeature, aType);
57     if (anEntityID == SLVS_E_UNKNOWN) {
58       myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
59       return;
60     }
61
62     // Check the entity is complex
63     Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
64     if (anEntity.point[0] != SLVS_E_UNKNOWN)
65       isComplexFeature = true;
66     else // simple entity
67       theAttributes.push_back(anEntityID);
68   }
69   else {
70      myFeatureMap[myBaseFeature] = anEntityID;
71      isComplexFeature = true;
72   }
73
74   int aNbOutOfGroup = 0;
75   if (isComplexFeature) {
76      std::list<AttributePtr> aPoints =
77         myBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
78      std::list<AttributePtr>::iterator anIt = aPoints.begin();
79      for (; anIt != aPoints.end(); ++anIt) {
80        std::map<AttributePtr, Slvs_hEntity>::const_iterator aFound = myAttributeMap.find(*anIt);
81        Slvs_hEntity anAttr = aFound != myAttributeMap.end() ?
82                              aFound->second : myGroup->getAttributeId(*anIt);
83        Slvs_Entity anAttrEnt = myStorage->getEntity(anAttr);
84
85        // Check the attribute changes coordinates
86        std::shared_ptr<GeomDataAPI_Point2D> aPt =
87           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
88        // Check the entity is not lying in the current group or it is not moved
89        if (anAttr == SLVS_E_UNKNOWN || anAttrEnt.group != myGroup->getId() ||
90            (anAttr <= anEntMaxID && !isMoved(aPt, anAttrEnt))) {
91          if (anAttrEnt.group == SLVS_G_OUTOFGROUP)
92            ++aNbOutOfGroup;
93          theIsFullyMoved = false;
94        }
95        else {
96          theAttributes.push_back(anAttr);
97          // update point coordinates
98          Slvs_Entity anAttrEnt = myStorage->getEntity(anAttr);
99          double aNewPos[2] = {aPt->x(), aPt->y()};
100          for (int i = 0; i < 2; i++) {
101            Slvs_Param aParam = myStorage->getParameter(anAttrEnt.param[i]);
102            aParam.val = aNewPos[i];
103            myStorage->updateParameter(aParam);
104          }
105        }
106      }
107   }
108
109   // Additional checking, which leads to fix whole feature, if it has fixed points
110   if (!theIsFullyMoved) {
111     Slvs_Entity aFeature = myStorage->getEntity(anEntityID);
112     int aNbPoints = 4;
113     while (aNbPoints > 0 && aFeature.point[aNbPoints-1] == SLVS_E_UNKNOWN)
114       --aNbPoints;
115     if (aNbPoints == aNbOutOfGroup + (int)theAttributes.size()) {
116       theIsFullyMoved = true;
117       return;
118     }
119   }
120
121   // Leave only points which are used in constraints
122   if (myStorage->isUsedByConstraints(anEntityID))
123     return;
124   std::vector<Slvs_hEntity>::iterator anIt = theAttributes.begin();
125   while (anIt != theAttributes.end()) {
126     if (myStorage->isUsedByConstraints(*anIt))
127       ++anIt;
128     else {
129       int aShift = anIt - theAttributes.begin();
130       theAttributes.erase(anIt);
131       anIt = theAttributes.begin() + aShift;
132     }
133   }
134 }
135
136 bool SketchSolver_ConstraintMovement::isMoved(
137     std::shared_ptr<GeomDataAPI_Point2D> thePoint, const Slvs_Entity& theEntity)
138 {
139   double aDeltaX = myStorage->getParameter(theEntity.param[0]).val;
140   double aDeltaY = myStorage->getParameter(theEntity.param[1]).val;
141   aDeltaX -= thePoint->x();
142   aDeltaY -= thePoint->y();
143   return aDeltaX * aDeltaX + aDeltaY * aDeltaY >= tolerance * tolerance;
144 }
145
146 void SketchSolver_ConstraintMovement::fixFeature()
147 {
148   Slvs_hEntity anEntID = fixedEntity();
149
150   std::string aKind;
151   std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFIt = myFeatureMap.begin();
152   for (; aFIt != myFeatureMap.end() && aKind.empty(); ++aFIt)
153     if (aFIt->second == anEntID)
154       aKind = aFIt->first->getKind();
155   std::map<AttributePtr, Slvs_hEntity>::const_iterator anAtIt = myAttributeMap.begin();
156   for (; anAtIt != myAttributeMap.end() && aKind.empty(); ++anAtIt)
157     if (anAtIt->second == anEntID)
158       aKind = anAtIt->first->attributeType();
159
160   if (aKind == SketchPlugin_Line::ID()) {
161     Slvs_Entity aLine = myStorage->getEntity(anEntID);
162     fixLine(aLine);
163   }
164   else if (aKind == SketchPlugin_Arc::ID()) {
165     Slvs_Entity anArc = myStorage->getEntity(anEntID);
166     fixArc(anArc);
167   }
168   else if (aKind == SketchPlugin_Circle::ID()) {
169     Slvs_Entity aCirc = myStorage->getEntity(anEntID);
170     fixCircle(aCirc);
171   }
172   else if (aKind == SketchPlugin_Point::ID() || aKind == GeomDataAPI_Point2D::typeId()) {
173     fixPoint(anEntID);
174   }
175 }
176