Salome HOME
Copyright update 2022
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_OverConstraintsResolver.cpp
1 // Copyright (C) 2014-2022  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include <SketchPlugin_OverConstraintsResolver.h>
21
22 #include <Events_Loop.h>
23
24 #include <ModelAPI_Attribute.h>
25 #include <ModelAPI_AttributeRefAttr.h>
26 #include <ModelAPI_Feature.h>
27 #include <ModelAPI_Events.h>
28 #include <ModelAPI_Tools.h>
29
30 #include <SketchPlugin_Arc.h>
31 #include <SketchPlugin_ConstraintCoincidence.h>
32 #include <SketchPlugin_ConstraintTangent.h>
33 #include <SketchPlugin_ConstraintHorizontal.h>
34 #include <SketchPlugin_ConstraintVertical.h>
35 #include <SketchPlugin_Point.h>
36
37 static SketchPlugin_OverConstraintsResolver* myConstResolver =
38                                                    new SketchPlugin_OverConstraintsResolver;
39
40 SketchPlugin_OverConstraintsResolver::SketchPlugin_OverConstraintsResolver()
41 {
42   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_CHECK_CONSTRAINTS));
43 }
44
45 void SketchPlugin_OverConstraintsResolver::setConstraints(
46                                            const std::set<ObjectPtr>& theConstraints)
47 {
48   myConstraints = theConstraints;
49 }
50
51 bool SketchPlugin_OverConstraintsResolver::perform()
52 {
53   bool hasConflicts = false;
54   hasConflicts |= checkArcsAboutTangentialConflict();
55   hasConflicts |= checkHorizontalOrVerticalConflict();
56   return hasConflicts;
57 }
58
59 bool SketchPlugin_OverConstraintsResolver::checkHorizontalOrVerticalConflict()
60 {
61   std::set<ObjectPtr>::const_iterator
62     anIt = myConstraints.begin(), aLast = myConstraints.end();
63   bool isHVConstraint = false;
64   FeaturePtr aFeature;
65   for (; anIt != aLast; anIt++) {
66     ObjectPtr anObject = *anIt;
67     if (!isHVConstraint) {
68       aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
69       if (aFeature) {
70         std::string aType = aFeature->getKind();
71         if ((aType == SketchPlugin_ConstraintHorizontal::ID()) ||
72             (aType == SketchPlugin_ConstraintVertical::ID()))
73         {
74           myConstraintsToRemove.insert(*anIt);
75           isHVConstraint = true;
76         }
77       }
78     }
79   }
80   return isHVConstraint;
81 }
82
83 bool SketchPlugin_OverConstraintsResolver::checkArcsAboutTangentialConflict()
84 {
85   bool isConflictsFound = false;
86
87   std::set<ObjectPtr>::const_iterator
88     anIt = myConstraints.begin(), aLast = myConstraints.end();
89   for (; anIt != aLast; anIt++) {
90     ObjectPtr anObject = *anIt;
91     ConstraintPtr aConstain =
92       std::dynamic_pointer_cast<SketchPlugin_Constraint>(anObject);
93     if (aConstain.get()) {
94       std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttrA = aConstain->refattr(
95                                                              aConstain->ENTITY_A());
96       std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttrB = aConstain->refattr(
97                                                              aConstain->ENTITY_B());
98       if (!aRefAttrA || !aRefAttrB)
99         continue;
100
101       FeaturePtr aFeatureA = ModelAPI_Feature::feature(aRefAttrA->object());
102       FeaturePtr aFeatureB = ModelAPI_Feature::feature(aRefAttrB->object());
103
104       if (aFeatureA && aFeatureA->getKind() == SketchPlugin_Arc::ID() &&
105           aFeatureB && aFeatureB->getKind() == SketchPlugin_Arc::ID()) {
106
107         std::shared_ptr<ModelAPI_Attribute> anAttrStrA = aFeatureA->attribute(
108                                                          SketchPlugin_Arc::START_ID());
109         std::shared_ptr<ModelAPI_Attribute> anAttrEndA = aFeatureA->attribute(
110                                                          SketchPlugin_Arc::END_ID());
111         std::shared_ptr<ModelAPI_Attribute> anAttrStrB = aFeatureB->attribute(
112                                                          SketchPlugin_Arc::START_ID());
113         std::shared_ptr<ModelAPI_Attribute> anAttrEndB = aFeatureB->attribute(
114                                                          SketchPlugin_Arc::END_ID());
115         std::shared_ptr<ModelAPI_Attribute> anAttrCenA = aFeatureA->attribute(
116                                                          SketchPlugin_Arc::CENTER_ID());
117         std::shared_ptr<ModelAPI_Attribute> anAttrCenB = aFeatureB->attribute(
118                                                          SketchPlugin_Arc::CENTER_ID());
119
120         bool isCoincident = false;
121         bool isCoincidentAtCenter = false;
122         std::set<FeaturePtr> aTangentConstraints;
123
124         std::set<FeaturePtr> aFeatures;
125         std::map<FeaturePtr, std::set<FeaturePtr> > aFeaturesMap;
126         aFeatures.insert(aFeatureA);
127         aFeatures.insert(aFeatureB);
128         ModelAPI_Tools::findAllReferences(aFeatures, aFeaturesMap);
129
130         std::set<FeaturePtr> aFeaturesA = aFeaturesMap[aFeatureA];
131         std::set<FeaturePtr> aFeaturesB = aFeaturesMap[aFeatureB];
132
133         for (auto aFeatIter = aFeaturesA.begin(); aFeatIter != aFeaturesA.end(); ++aFeatIter) {
134           if (aFeaturesB.find(aFeatIter.operator*()) != aFeaturesB.end()){
135             const std::string& aType = (*aFeatIter)->getKind();
136             if (aType == SketchPlugin_ConstraintCoincidence::ID()) {
137               ConstraintPtr aCoincidence =
138                   std::dynamic_pointer_cast<SketchPlugin_ConstraintCoincidence>(*aFeatIter);
139               std::set<AttributePtr> anAttrSet;
140               anAttrSet.insert(aCoincidence->refattr(aCoincidence->ENTITY_A())->attr());
141               anAttrSet.insert(aCoincidence->refattr(aCoincidence->ENTITY_B())->attr());
142               isCoincident |= ((anAttrSet.find(anAttrStrA) != anAttrSet.end() ||
143                                 anAttrSet.find(anAttrEndA) != anAttrSet.end()) &&
144                                (anAttrSet.find(anAttrStrB) != anAttrSet.end() ||
145                                 anAttrSet.find(anAttrEndB) != anAttrSet.end()));
146               isCoincidentAtCenter |= (anAttrSet.find(anAttrCenA) != anAttrSet.end() &&
147                                        anAttrSet.find(anAttrCenB) != anAttrSet.end());
148             }
149             else if (aType == SketchPlugin_ConstraintTangent::ID()) {
150               aTangentConstraints.insert(*aFeatIter);
151             }
152           }
153         }
154
155         if (isCoincident && isCoincidentAtCenter && !aTangentConstraints.empty()) {
156           isConflictsFound = true;
157           myConstraintsToRemove.insert(aTangentConstraints.begin(), aTangentConstraints.end());
158         }
159       }
160     }
161   }
162
163   return isConflictsFound;
164 }
165
166 void SketchPlugin_OverConstraintsResolver::processEvent(
167                                            const std::shared_ptr<Events_Message>& theMessage)
168 {
169   Events_ID anEventID = theMessage->eventID();
170   if (anEventID == Events_Loop::eventByName(EVENT_CHECK_CONSTRAINTS)) {
171     std::shared_ptr<ModelAPI_CheckConstraintsMessage> aConstraintsMsg =
172       std::dynamic_pointer_cast<ModelAPI_CheckConstraintsMessage>(theMessage);
173     if (aConstraintsMsg.get()) {
174       myConstraintsToRemove.clear();
175       myConstraints = aConstraintsMsg->constraints();
176       if (perform())
177       {
178         std::shared_ptr<ModelAPI_CheckConstraintsMessage> aMessage =
179           std::shared_ptr<ModelAPI_CheckConstraintsMessage>(
180             new ModelAPI_CheckConstraintsMessage(
181               Events_Loop::eventByName(EVENT_REMOVE_CONSTRAINTS)));
182         aMessage->setConstraints(myConstraintsToRemove);
183         Events_Loop::loop()->send(aMessage);
184       }
185     }
186   }
187 }