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