Salome HOME
Issue #2167: error when create circle
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Tools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        SketchPlugin_Tools.cpp
4 // Created:     07 July 2015
5 // Author:      Sergey POKHODENKO
6
7 #include "SketchPlugin_Tools.h"
8
9 #include "SketchPlugin_ConstraintCoincidence.h"
10 #include "SketchPlugin_ConstraintTangent.h"
11 #include "SketchPlugin_Point.h"
12 #include "SketchPlugin_SketchEntity.h"
13
14 #include <SketcherPrs_Tools.h>
15
16 #include <ModelAPI_AttributeDouble.h>
17
18 #include <GeomDataAPI_Point.h>
19 #include <GeomDataAPI_Point2D.h>
20
21 namespace SketchPlugin_Tools {
22
23 void clearExpressions(AttributeDoublePtr theAttribute)
24 {
25   theAttribute->setText(std::string());
26 }
27
28 void clearExpressions(AttributePointPtr theAttribute)
29 {
30   theAttribute->setText(std::string(), std::string(), std::string());
31 }
32
33 void clearExpressions(AttributePoint2DPtr theAttribute)
34 {
35   theAttribute->setText(std::string(), std::string());
36 }
37
38 void clearExpressions(AttributePtr theAttribute)
39 {
40   // Double
41   AttributeDoublePtr anAttributeDouble =
42       std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
43   if (anAttributeDouble.get())
44     clearExpressions(anAttributeDouble);
45   // Point
46   AttributePointPtr anAttributePoint =
47       std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
48   if (anAttributePoint.get())
49     clearExpressions(anAttributePoint);
50   // Point2D
51   AttributePoint2DPtr anAttributePoint2D =
52       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
53   if (anAttributePoint2D.get())
54     clearExpressions(anAttributePoint2D);
55 }
56
57 void clearExpressions(FeaturePtr theFeature)
58 {
59   if (!theFeature.get())
60     return;
61
62   std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
63   std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
64   for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
65     clearExpressions(*anAttributeIt);
66   }
67 }
68
69 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
70 {
71   std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
72                                                           SketchPlugin_Constraint::ENTITY_A());
73   if (aPnt.get() == NULL)
74     aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
75   return aPnt;
76 }
77
78 std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
79 {
80   std::set<FeaturePtr> aCoincident;
81   const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
82   std::set<AttributePtr>::const_iterator aIt;
83   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
84     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
85     if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
86       aCoincident.insert(aConstrFeature);
87   }
88   return aCoincident;
89 }
90
91 void findCoincidences(const FeaturePtr theStartCoin,
92                       const std::string& theAttr,
93                       std::set<FeaturePtr>& theList)
94 {
95   AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
96   if(!aPnt) {
97     return;
98   }
99   FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
100   if(theList.find(aObj) == theList.end()) {
101     std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
102     if(aOrig.get() == NULL) {
103       return;
104     }
105     theList.insert(aObj);
106     std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
107     std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
108     for (; aCIt != aCoincidences.end(); ++aCIt) {
109       FeaturePtr aConstrFeature = *aCIt;
110       std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
111       if(aPnt.get() && aOrig->isEqual(aPnt)) {
112         findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(), theList);
113         findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(), theList);
114       }
115     }
116   }
117 }
118
119 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
120 {
121   std::set<FeaturePtr> aCoincidentFeatures;
122
123   FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
124   aCoincidentFeatures.insert(anOwner);
125
126   std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
127   std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
128   for (; aCIt != aCoincidences.end(); ++aCIt) {
129     bool isPointUsedInCoincidence = false;
130     AttributeRefAttrPtr anOtherCoincidentAttr;
131     for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
132       AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
133       if (!aRefAttr)
134         continue;
135       if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
136         isPointUsedInCoincidence = true;
137       else
138         anOtherCoincidentAttr = aRefAttr;
139     }
140
141     if (isPointUsedInCoincidence) {
142       ObjectPtr anObj;
143       if (anOtherCoincidentAttr->isObject())
144         anObj = anOtherCoincidentAttr->object();
145       else
146         anObj = anOtherCoincidentAttr->attr()->owner();
147       aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
148     }
149   }
150
151   return aCoincidentFeatures;
152 }
153
154 // Container for point-point coincidences.
155 // Useful to find points coincident to a given point.
156 class CoincidentPoints
157 {
158 public:
159   void addCoincidence(const AttributePoint2DPtr& thePoint1,
160                       const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
161   {
162     std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
163     std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
164     if (aFound1 == myCoincidentPoints.end()) {
165       std::set<AttributePoint2DPtr> aNewSet;
166       aNewSet.insert(thePoint1);
167       if (thePoint2)
168         aNewSet.insert(thePoint2);
169       myCoincidentPoints.push_back(aNewSet);
170     } else if (aFound2 == myCoincidentPoints.end()) {
171       if (thePoint2)
172         aFound1->insert(thePoint2);
173     } else {
174       aFound1->insert(aFound2->begin(), aFound2->end());
175       myCoincidentPoints.erase(aFound2);
176     }
177   }
178
179   std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
180   {
181     std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
182     if (aFound == myCoincidentPoints.end())
183       return std::set<AttributePoint2DPtr>();
184     return *aFound;
185   }
186
187 private:
188   std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
189   {
190     std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
191     for (; aSeek != myCoincidentPoints.end(); ++aSeek)
192       if (aSeek->find(thePoint) != aSeek->end())
193         return aSeek;
194     return myCoincidentPoints.end();
195   }
196
197 private:
198   std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
199 };
200
201 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
202 {
203   CoincidentPoints aCoincidentPoints;
204   AttributePoint2DPtr aPoints[2];
205
206   FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
207   std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
208   std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
209   for (; aCIt != aCoincidences.end(); ++aCIt) {
210     aPoints[0] = AttributePoint2DPtr();
211     aPoints[1] = AttributePoint2DPtr();
212     for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
213       AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
214       if (!aRefAttr)
215         continue;
216       if (!aRefAttr->isObject())
217         aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
218     }
219
220     if (aPoints[0])
221       aCoincidentPoints.addCoincidence(aPoints[0], aPoints[1]);
222   }
223
224   return aCoincidentPoints.coincidentPoints(thePoint);
225 }
226
227 void resetAttribute(SketchPlugin_Feature* theFeature,
228                     const std::string& theId)
229 {
230   AttributePtr anAttr = theFeature->attribute(theId);
231   if(anAttr.get()) {
232     anAttr->reset();
233   }
234 }
235
236 void createConstraint(SketchPlugin_Feature* theFeature,
237                       const std::string& theId,
238                       const AttributePtr theAttr,
239                       const ObjectPtr theObject,
240                       const bool theIsCanBeTangent)
241 {
242   AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
243   if(aRefAttr.get() && aRefAttr->isInitialized()) {
244     FeaturePtr aConstraint;
245     if(!theIsCanBeTangent) {
246       aConstraint = theFeature->sketch()
247                               ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
248     } else {
249       if(aRefAttr->isObject()) {
250         ObjectPtr anObject = aRefAttr->object();
251         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
252         if(aFeature->getKind() == SketchPlugin_Point::ID()) {
253           aConstraint = theFeature->sketch()
254                                   ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
255         } else {
256           aConstraint = theFeature->sketch()
257                                   ->addFeature(SketchPlugin_ConstraintTangent::ID());
258         }
259       } else {
260         aConstraint = theFeature->sketch()
261                                 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
262       }
263     }
264     AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
265     aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
266                          : aRefAttrA->setAttr(aRefAttr->attr());
267     AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
268     if(theObject.get()) {
269       aRefAttrB->setObject(theObject);
270     } else if(theAttr.get()) {
271       aRefAttrB->setAttr(theAttr);
272     }
273   }
274 }
275
276 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr&      theRefAttr,
277                                          const AttributePtr&             theDefaultAttr,
278                                          std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
279                                          std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
280 {
281   AttributePtr anAttr = theDefaultAttr;
282   if (theRefAttr->isObject()) {
283     FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
284     if (aTgFeature) {
285       if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
286         theTangentCurve = aTgFeature->lastResult()->shape();
287         return;
288       }
289       anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
290     }
291   } else
292     anAttr = theRefAttr->attr();
293
294   thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
295 }
296
297 } // namespace SketchPlugin_Tools