Salome HOME
Revert "First phase of SketchSolver refactoring"
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintFillet.cpp
1 #include <SketchSolver_ConstraintFillet.h>
2 #include <SketchSolver_Group.h>
3 #include <SketchSolver_Error.h>
4
5 #include <ModelAPI_AttributeDouble.h>
6 #include <ModelAPI_AttributeRefAttr.h>
7 #include <ModelAPI_AttributeRefList.h>
8 #include <ModelAPI_ResultConstruction.h>
9
10
11 void SketchSolver_ConstraintFillet::getAttributes(
12     double& theValue, std::vector<Slvs_hEntity>& theAttributes)
13 {
14   theAttributes.clear();
15
16   DataPtr aData = myBaseConstraint->data();
17   AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
18     aData->attribute(SketchPlugin_Constraint::VALUE()));
19   theValue = aValueAttr ? aValueAttr->value() : 0.0;
20
21   std::list<AttributePtr> aBaseAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId());
22   std::list<AttributePtr>::iterator anIter = aBaseAttrs.begin();
23   for (; anIter != aBaseAttrs.end(); anIter++) {
24     AttributeRefAttrPtr aRefAttr =
25         std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
26     if (!aRefAttr || !aRefAttr->isInitialized()) {
27       myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
28       return;
29     }
30
31     int aType = SLVS_E_UNKNOWN; // type of created entity
32     Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr);
33     if (anEntity == SLVS_E_UNKNOWN)
34       anEntity = changeEntity(aRefAttr, aType);
35
36     if (aType == SLVS_E_UNKNOWN)
37       continue;
38     theAttributes.push_back(anEntity);
39   }
40
41   // Fillet objects
42   AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
43     aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
44   if (!aFilletRefList || !aFilletRefList->isInitialized()) {
45     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
46     return;
47   }
48   std::list<ObjectPtr> aFilletList = aFilletRefList->list();
49   if (aFilletList.size() < theAttributes.size() + 1) {
50     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
51     return;
52   }
53   FeaturePtr aFilletFeature;
54   ResultConstructionPtr aRC;
55   int aType;
56   std::list<ObjectPtr>::iterator aFilIter = aFilletList.begin();
57   for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) {
58     aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aFilIter);
59     aFilletFeature = aRC ? aRC->document()->feature(aRC) :
60         std::dynamic_pointer_cast<ModelAPI_Feature>(*aFilIter);
61     if (!aFilletFeature) {
62       myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
63       return;
64     }
65     Slvs_hEntity anEntity = changeEntity(aFilletFeature, aType);
66     theAttributes.push_back(anEntity);
67   }
68 }
69
70 void SketchSolver_ConstraintFillet::process()
71 {
72   cleanErrorMsg();
73   if (!myBaseConstraint || !myStorage || myGroup == 0) {
74     /// TODO: Put error message here
75     return;
76   }
77   if (!mySlvsConstraints.empty()) // some data is changed, update constraint
78     update(myBaseConstraint);
79
80   double aValue;
81   std::vector<Slvs_hEntity> anEntID;
82   getAttributes(aValue, anEntID);
83   if (!myErrorMsg.empty())
84     return;
85
86   // Obtain the entities itself:
87   // First two are base entities
88   // Second two are trimmed them
89   // Last one is a fillet arc
90   std::vector<Slvs_Entity> anEntities;
91   std::vector<Slvs_hEntity>::iterator anIt = anEntID.begin();
92   for (; anIt != anEntID.end(); anIt++)
93     anEntities.push_back(myStorage->getEntity(*anIt));
94
95   // Check the base entities have a coincident point
96   Slvs_hEntity aPointsToFind[4];
97   for (int i = 0; i < 2; i++) {
98     int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
99     aPointsToFind[2*i]  = anEntities[i].point[aShift];
100     aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
101   }
102   // Search coincident points
103   int aCoincInd[2]; // indices of coincident points on each entity (0 - first, 1 - last)
104   bool isPointFound = false;
105   for (int i = 0; i < 2 && !isPointFound; i++)
106     for (int j = 2; j < 4 && !isPointFound; j++)
107       if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) {
108         aCoincInd[0] = i;
109         aCoincInd[1] = j - 2;
110         isPointFound = true;
111       }
112   if (!isPointFound) {
113     // There is no coincident points between tangential objects. Generate error message
114     myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
115     return;
116   }
117
118   // For correct result, move floating points of fillet on the middle points of base objects
119   Slvs_Entity aPoint;
120   Slvs_Param aParam;
121   double anArcPoints[3][2];
122   for (int i = 0; i < 2; i++) {
123     calculateMiddlePoint(anEntities[i], 0.1 + 0.8 * aCoincInd[i], anArcPoints[i+1][0], anArcPoints[i+1][1]);
124     aPoint = myStorage->getEntity(anEntities[i+2].point[aCoincInd[i]]);
125     for (int j = 0; j < 2; j++) {
126       aParam = myStorage->getParameter(aPoint.param[j]);
127       aParam.val = anArcPoints[i+1][j];
128       aPoint.param[j] = myStorage->updateParameter(aParam);
129     }
130   }
131   anArcPoints[0][0] = 0.5 * (anArcPoints[1][0] + anArcPoints[2][0]);
132   anArcPoints[0][1] = 0.5 * (anArcPoints[1][1] + anArcPoints[2][1]);
133   // Check the arc is need to be reversed
134   double aSharedPoint[2];
135   aPoint = myStorage->getEntity(aPointsToFind[aCoincInd[0]]);
136   for (int j = 0; j < 2; j++)
137     aSharedPoint[j] = myStorage->getParameter(aPoint.param[j]).val;
138   double aCross = (anArcPoints[1][0] - anArcPoints[0][0]) * (aSharedPoint[1] - anArcPoints[0][1]) -
139                   (anArcPoints[1][1] - anArcPoints[0][1]) * (aSharedPoint[0] - anArcPoints[0][0]);
140   if (aCross < 0.0) { // reverse fillet arc
141     double aTmp;
142     for (int j = 0; j < 2; j++) {
143       aTmp = anArcPoints[1][j];
144       anArcPoints[1][j] = anArcPoints[2][j];
145       anArcPoints[2][j] = aTmp;
146     }
147   }
148   // update fillet arc coordinates
149   for (int indArcPt = 0; indArcPt < 3; indArcPt++) {
150     aPoint = myStorage->getEntity(anEntities.back().point[indArcPt]);
151     for (int j = 0; j < 2; j++) {
152       aParam = myStorage->getParameter(aPoint.param[j]);
153       aParam.val = anArcPoints[indArcPt][j];
154       aPoint.param[j] = myStorage->updateParameter(aParam);
155     }
156   }
157
158   for (int indEnt = 0; indEnt < 2; indEnt++) {
159     int aShift = anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
160     // one point of fillet object should be coincident with the point on base, non-coincident with another base object
161     Slvs_hEntity aBaseID = anEntities[indEnt].point[1 - aCoincInd[indEnt] + aShift];
162     Slvs_hEntity aFilletID = anEntities[2 + indEnt].point[1 - aCoincInd[indEnt] + aShift];
163     Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
164         SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
165         0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
166     aCoincConstr.h = myStorage->addConstraint(aCoincConstr);
167     mySlvsConstraints.push_back(aCoincConstr.h);
168
169     // another point of fillet object should be placed on the base object
170     Slvs_Constraint aPonCurveConstr;
171     if (anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE) {
172       // centers of arcs should be coincident
173       aBaseID = anEntities[indEnt].point[0];
174       aFilletID = anEntities[2 + indEnt].point[0];
175       aPonCurveConstr = Slvs_MakeConstraint(
176           SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
177           0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
178     } else {
179       aFilletID = anEntities[2 + indEnt].point[aCoincInd[indEnt]];
180       aPonCurveConstr = Slvs_MakeConstraint(
181           SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(),
182           0.0, aFilletID, SLVS_E_UNKNOWN, anEntities[indEnt].h, SLVS_E_UNKNOWN);
183     }
184     aPonCurveConstr.h = myStorage->addConstraint(aPonCurveConstr);
185     mySlvsConstraints.push_back(aPonCurveConstr.h);
186   }
187 }
188
189 bool SketchSolver_ConstraintFillet::remove(ConstraintPtr theConstraint)
190 {
191   cleanErrorMsg();
192   if (theConstraint && theConstraint != myBaseConstraint)
193     return false;
194   bool isFullyRemoved = true;
195   std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
196   for (; aCIter != mySlvsConstraints.end(); aCIter++)
197    isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
198   mySlvsConstraints.clear();
199
200   if (isFullyRemoved) {
201     myFeatureMap.clear();
202     myAttributeMap.clear();
203     myValueMap.clear();
204   } else
205     cleanRemovedEntities();
206   return true;
207 }
208