Salome HOME
Fix compilation error on Linux
[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 #ifdef DEBUG_TRIM
36 #include <iostream>
37 #endif
38
39 namespace SketchPlugin_Tools {
40
41 void clearExpressions(AttributeDoublePtr theAttribute)
42 {
43   theAttribute->setText(std::string());
44 }
45
46 void clearExpressions(AttributePointPtr theAttribute)
47 {
48   theAttribute->setText(std::string(), std::string(), std::string());
49 }
50
51 void clearExpressions(AttributePoint2DPtr theAttribute)
52 {
53   theAttribute->setText(std::string(), std::string());
54 }
55
56 void clearExpressions(AttributePtr theAttribute)
57 {
58   // Double
59   AttributeDoublePtr anAttributeDouble =
60       std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
61   if (anAttributeDouble.get())
62     clearExpressions(anAttributeDouble);
63   // Point
64   AttributePointPtr anAttributePoint =
65       std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
66   if (anAttributePoint.get())
67     clearExpressions(anAttributePoint);
68   // Point2D
69   AttributePoint2DPtr anAttributePoint2D =
70       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
71   if (anAttributePoint2D.get())
72     clearExpressions(anAttributePoint2D);
73 }
74
75 void clearExpressions(FeaturePtr theFeature)
76 {
77   if (!theFeature.get())
78     return;
79
80   std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
81   std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
82   for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
83     clearExpressions(*anAttributeIt);
84   }
85 }
86
87 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
88 {
89   std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
90                                                           SketchPlugin_Constraint::ENTITY_A());
91   if (aPnt.get() == NULL)
92     aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
93   return aPnt;
94 }
95
96 std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
97 {
98   std::set<FeaturePtr> aCoincident;
99   const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
100   std::set<AttributePtr>::const_iterator aIt;
101   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
102     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
103     if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
104       aCoincident.insert(aConstrFeature);
105   }
106   return aCoincident;
107 }
108
109 void findCoincidences(const FeaturePtr theStartCoin,
110                       const std::string& theAttr,
111                       std::set<FeaturePtr>& theList,
112                       const bool theIsAttrOnly)
113 {
114   AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
115   if(!aPnt) {
116     return;
117   }
118   FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
119   if(theList.find(aObj) == theList.end()) {
120     std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
121     if(aOrig.get() == NULL) {
122       return;
123     }
124     if(!theIsAttrOnly || !aPnt->isObject()) {
125       theList.insert(aObj);
126     }
127     std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
128     std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
129     for (; aCIt != aCoincidences.end(); ++aCIt) {
130       FeaturePtr aConstrFeature = *aCIt;
131       std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
132       if(aPnt.get() && aOrig->isEqual(aPnt)) {
133         findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
134                          theList, theIsAttrOnly);
135         findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
136                          theList, theIsAttrOnly);
137       }
138     }
139   }
140 }
141
142 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
143 {
144   std::set<FeaturePtr> aCoincidentFeatures;
145
146   FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
147   aCoincidentFeatures.insert(anOwner);
148
149   std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
150   std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
151   for (; aCIt != aCoincidences.end(); ++aCIt) {
152     bool isPointUsedInCoincidence = false;
153     AttributeRefAttrPtr anOtherCoincidentAttr;
154     for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
155       AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
156       if (!aRefAttr)
157         continue;
158       if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
159         isPointUsedInCoincidence = true;
160       else
161         anOtherCoincidentAttr = aRefAttr;
162     }
163
164     if (isPointUsedInCoincidence) {
165       ObjectPtr anObj;
166       if (anOtherCoincidentAttr->isObject())
167         anObj = anOtherCoincidentAttr->object();
168       else
169         anObj = anOtherCoincidentAttr->attr()->owner();
170       aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
171     }
172   }
173
174   return aCoincidentFeatures;
175 }
176
177 // Container for point-point coincidences.
178 // Useful to find points coincident to a given point.
179 class CoincidentPoints
180 {
181 public:
182   void addCoincidence(const AttributePoint2DPtr& thePoint1,
183                       const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
184   {
185     std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
186     std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
187     if (aFound1 == myCoincidentPoints.end()) {
188       std::set<AttributePoint2DPtr> aNewSet;
189       aNewSet.insert(thePoint1);
190       if (thePoint2)
191         aNewSet.insert(thePoint2);
192       myCoincidentPoints.push_back(aNewSet);
193     } else if (aFound2 == myCoincidentPoints.end()) {
194       if (thePoint2)
195         aFound1->insert(thePoint2);
196     } else {
197       aFound1->insert(aFound2->begin(), aFound2->end());
198       myCoincidentPoints.erase(aFound2);
199     }
200   }
201
202   std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
203   {
204     std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
205     if (aFound == myCoincidentPoints.end())
206       return std::set<AttributePoint2DPtr>();
207     return *aFound;
208   }
209
210 private:
211   std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
212   {
213     std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
214     for (; aSeek != myCoincidentPoints.end(); ++aSeek)
215       if (aSeek->find(thePoint) != aSeek->end())
216         return aSeek;
217     return myCoincidentPoints.end();
218   }
219
220 private:
221   std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
222 };
223
224 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
225 {
226   CoincidentPoints aCoincidentPoints;
227   AttributePoint2DPtr aPoints[2];
228
229   FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
230   std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
231   std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
232   for (; aCIt != aCoincidences.end(); ++aCIt) {
233     aPoints[0] = AttributePoint2DPtr();
234     aPoints[1] = AttributePoint2DPtr();
235     for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
236       AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
237       if (!aRefAttr)
238         continue;
239       if (!aRefAttr->isObject())
240         aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
241     }
242
243     if (aPoints[0])
244       aCoincidentPoints.addCoincidence(aPoints[0], aPoints[1]);
245   }
246
247   return aCoincidentPoints.coincidentPoints(thePoint);
248 }
249
250 void resetAttribute(SketchPlugin_Feature* theFeature,
251                     const std::string& theId)
252 {
253   AttributePtr anAttr = theFeature->attribute(theId);
254   if(anAttr.get()) {
255     anAttr->reset();
256   }
257 }
258
259 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
260                                  const std::string& theId,
261                                  const AttributePtr theAttr,
262                                  const ObjectPtr theObject,
263                                  const bool theIsCanBeTangent)
264 {
265   AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
266   if(aRefAttr.get() && aRefAttr->isInitialized()) {
267     FeaturePtr aConstraint;
268     if(!theIsCanBeTangent) {
269       aConstraint = theFeature->sketch()
270                               ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
271     } else {
272       if(aRefAttr->isObject()) {
273         ObjectPtr anObject = aRefAttr->object();
274         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
275         if(aFeature->getKind() == SketchPlugin_Point::ID()) {
276           aConstraint = theFeature->sketch()
277                                   ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
278         } else {
279           aConstraint = theFeature->sketch()
280                                   ->addFeature(SketchPlugin_ConstraintTangent::ID());
281         }
282       } else {
283         aConstraint = theFeature->sketch()
284                                 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
285       }
286     }
287     AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
288     aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
289                          : aRefAttrA->setAttr(aRefAttr->attr());
290     AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
291     if(theObject.get()) {
292       aRefAttrB->setObject(theObject);
293     } else if(theAttr.get()) {
294       aRefAttrB->setAttr(theAttr);
295     }
296   }
297 }
298
299 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr&      theRefAttr,
300                                          const AttributePtr&             theDefaultAttr,
301                                          std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
302                                          std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
303 {
304   AttributePtr anAttr = theDefaultAttr;
305   if (theRefAttr->isObject()) {
306     FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
307     if (aTgFeature) {
308       if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
309         theTangentCurve = aTgFeature->lastResult()->shape();
310         return;
311       }
312       anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
313     }
314   } else
315     anAttr = theRefAttr->attr();
316
317   thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
318 }
319
320
321 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
322                                     const std::string& theConstraintId,
323                                     const AttributePtr& theFirstAttribute,
324                                     const AttributePtr& theSecondAttribute)
325 {
326   FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
327   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
328                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
329   aRefAttr->setAttr(theFirstAttribute);
330
331   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
332                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
333   aRefAttr->setAttr(theSecondAttribute);
334
335 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
336   std::cout << "<createConstraint to attribute> :"
337             << " first attribute - " << theFirstAttribute->id()
338             << " second attribute - " << theSecondAttribute->id()
339             << std::endl;
340 #endif
341
342   return aConstraint;
343 }
344
345 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
346                                       const std::string& theConstraintId,
347                                       const AttributePtr& theFirstAttribute,
348                                       const ObjectPtr& theSecondObject)
349 {
350   FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
351   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
352                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
353   aRefAttr->setAttr(theFirstAttribute);
354
355   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
356                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
357   aRefAttr->setObject(theSecondObject);
358
359 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
360   std::cout << "<createConstraint to attribute> :"
361             << " first attribute - " << theFirstAttribute->id()
362             << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
363             << std::endl;
364 #endif
365
366   return aConstraint;
367 }
368
369 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
370                                         const std::string& theConstraintId,
371                                         const ObjectPtr& theFirstObject,
372                                         const ObjectPtr& theSecondObject)
373 {
374   FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
375   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
376                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
377   aRefAttr->setObject(theFirstObject);
378
379   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
380                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
381   aRefAttr->setObject(theSecondObject);
382
383 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
384   std::cout << "<createConstraint to attribute> :"
385             << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
386             << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
387             << std::endl;
388 #endif
389
390   return aConstraint;
391 }
392
393 } // namespace SketchPlugin_Tools