Salome HOME
Adjust processing of Coincidence constraint by PlaneGCSSolver
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_UpdateCoincidence.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    PlaneGCSSolver_UpdateCoincidence.cpp
4 // Created: 17 Feb 2017
5 // Author:  Artem ZHIDKOV
6
7 #include <PlaneGCSSolver_UpdateCoincidence.h>
8 #include <SketchSolver_Constraint.h>
9
10 #include <SketchPlugin_ConstraintCoincidence.h>
11 #include <SketchPlugin_ConstraintMiddle.h>
12
13 void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserver,
14                                               const std::string& theType)
15 {
16   if (theType == GROUP()) {
17     std::list<SketchSolver_Constraint*>::iterator aPlaceToAdd = myObservers.end();
18     // point-point coincidence is placed first
19     if (theObserver->getType() == CONSTRAINT_PT_PT_COINCIDENT) {
20       for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd)
21         if ((*aPlaceToAdd)->getType() != CONSTRAINT_PT_PT_COINCIDENT)
22           break;
23     }
24     myObservers.insert(aPlaceToAdd, theObserver);
25   } else
26     myNext->attach(theObserver, theType);
27 }
28
29 void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature)
30 {
31   if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
32       theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
33     myCoincident.clear();
34     // notify listeners and stop procesing
35     std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
36     for (; anIt != myObservers.end(); ++anIt)
37       (*anIt)->notify(theFeature, this);
38   } else
39     myNext->update(theFeature);
40 }
41
42 static bool hasAnotherExternalPoint(const std::set<EntityWrapperPtr>& theCoincidences,
43                                     const EntityWrapperPtr& thePoint)
44 {
45   std::set<EntityWrapperPtr>::const_iterator anIt = theCoincidences.begin();
46   for (; anIt != theCoincidences.end(); ++anIt)
47     if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal() && *anIt != thePoint)
48       return true;
49   return false;
50 }
51
52 bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence(
53     const EntityWrapperPtr& theEntity1,
54     const EntityWrapperPtr& theEntity2)
55 {
56   bool isAccepted = true;
57
58   std::list<std::set<EntityWrapperPtr> >::iterator anIt = myCoincident.begin();
59   std::list<std::set<EntityWrapperPtr> >::iterator
60       aFound[2] = {myCoincident.end(), myCoincident.end()};
61
62   for (; anIt != myCoincident.end(); ++anIt) {
63     if (aFound[0] == myCoincident.end() && anIt->find(theEntity1) != anIt->end())
64       aFound[0] = anIt;
65     if (aFound[1] == myCoincident.end() && anIt->find(theEntity2) != anIt->end())
66       aFound[1] = anIt;
67     if (aFound[0] != myCoincident.end() && aFound[1] != myCoincident.end())
68       break;
69   }
70
71   if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) {
72     // new group of coincidence
73     std::set<EntityWrapperPtr> aNewCoinc;
74     aNewCoinc.insert(theEntity1);
75     aNewCoinc.insert(theEntity2);
76     myCoincident.push_back(aNewCoinc);
77   } else if (aFound[0] == aFound[1]) // same group => already coincident
78     isAccepted = false;
79   else {
80     if (theEntity1->type() == ENTITY_POINT && theEntity2->type() == ENTITY_POINT &&
81        (theEntity1->isExternal() || theEntity2->isExternal())) {
82       bool hasExternal = false;
83       for (int i = 0; i < 2 && !hasExternal; ++i) {
84         if (aFound[i] != myCoincident.end()) {
85           if (theEntity1->isExternal())
86             hasExternal = hasAnotherExternalPoint(*aFound[i], theEntity1);
87           if (!hasExternal && theEntity2->isExternal())
88             hasExternal = hasAnotherExternalPoint(*aFound[i], theEntity2);
89         }
90       }
91       if (hasExternal)
92         isAccepted = false;
93     }
94
95     if (aFound[0] == myCoincident.end())
96       aFound[1]->insert(theEntity1);
97     else if (aFound[1] == myCoincident.end())
98       aFound[0]->insert(theEntity2);
99     else { // merge two groups
100       aFound[0]->insert(aFound[1]->begin(), aFound[1]->end());
101       myCoincident.erase(aFound[1]);
102     }
103   }
104
105   return isAccepted;
106 }