Salome HOME
Copyright update 2021
[modules/shaper.git] / src / Model / Model_FiltersFactory.cpp
1 // Copyright (C) 2014-2021  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 "Model_FiltersFactory.h"
21
22 #include "ModelAPI_AttributeBoolean.h"
23 #include "ModelAPI_AttributeSelectionList.h"
24 #include <Events_InfoMessage.h>
25
26
27 void Model_FiltersFactory::registerFilter(const std::string& theID, ModelAPI_Filter* theFilter)
28 {
29   if (myFilters.find(theID) != myFilters.end()) {
30     Events_InfoMessage("Model_FiltersFactory", "Filter %1 is already registered").arg(theID).send();
31   }
32   else {
33     myFilters[theID] = FilterPtr(theFilter);
34   }
35 }
36
37 struct FilterArgs {
38   FilterPtr myFilter;
39   bool myReverse;
40   std::string myFilterID;
41 };
42
43 /// Returns the filter ID without the filter index
44 static std::string pureFilterID(const std::string& theID)
45 {
46   // remove from aPure "_" + number + "_" starting part
47   if (theID.size() > 3 && theID[0] == '_') {
48     int aNumDigits = 0;
49     while(theID[aNumDigits + 1] < '9' && theID[aNumDigits + 1] > '0')
50       aNumDigits++;
51     if (aNumDigits && theID[aNumDigits + 1] == '_') {
52       return theID.substr(aNumDigits + 2);
53     }
54   }
55   return theID;
56 }
57
58 bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature,
59                                    ResultPtr theResult,
60                                    GeomShapePtr theShape)
61 {
62   // check that the shape type corresponds to the attribute list type
63   AttributePtr aBase =
64     std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theFiltersFeature)->baseAttribute();
65   if (aBase.get()) {
66     std::shared_ptr<ModelAPI_AttributeSelectionList> aList =
67       std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aBase);
68     std::string aStrType = aList->selectionType();
69     GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::shapeTypeByStr(aStrType);
70     if (theShape->shapeType() != aType)
71       return false;
72   }
73   // prepare all filters args
74   ModelAPI_FiltersArgs anArgs;
75   std::list<FilterArgs> aFilters; /// all filters and the reverse values
76
77   std::list<std::string> aGroups;
78   theFiltersFeature->data()->allGroups(aGroups);
79   for(std::list<std::string>::iterator aGIter = aGroups.begin(); aGIter != aGroups.end(); aGIter++)
80   {
81     std::string aPureID = pureFilterID(*aGIter);
82     if (myFilters.find(aPureID) == myFilters.end())
83       continue;
84     std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
85     theFiltersFeature->data()->attributesOfGroup(*aGIter, anAttrs);
86     std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
87     for(; anAttrIter != anAttrs.end(); anAttrIter++) {
88       std::string anArgID = (*anAttrIter)->id().substr((*aGIter).length() + 2);
89       if (anArgID.empty()) { // reverse flag
90         std::shared_ptr<ModelAPI_AttributeBoolean> aReverse =
91           std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(*anAttrIter);
92         FilterArgs aFArgs = { myFilters[aPureID] , aReverse->value() , *aGIter };
93         aFilters.push_back(aFArgs);
94
95       } else {
96         anArgs.add(*anAttrIter);
97       }
98     }
99   }
100
101   // iterate filters and check shape for validity for all of them
102   std::list<FilterArgs>::iterator aFilter = aFilters.begin();
103   for(; aFilter != aFilters.end(); aFilter++) {
104     anArgs.setFilter(aFilter->myFilterID);
105     bool aResult = aFilter->myFilter->isOk(theShape, theResult, anArgs);
106     if (aFilter->myReverse)
107       aResult = !aResult;
108     if (!aResult) // one filter is failed => exit immediately
109       return false;
110   }
111   // all filters are passed
112   return true;
113 }
114
115 /// Returns list of filters for the given shape type
116 /// \param theType a shape type
117 std::list<FilterPtr> Model_FiltersFactory::filters(GeomAPI_Shape::ShapeType theType)
118 {
119   std::list<FilterPtr> aResult;
120   std::map<std::string, FilterPtr>::const_iterator anIt;
121   std::list<int> aTypes;
122   std::list<int>::const_iterator aTIt;
123   for (anIt = myFilters.cbegin(); anIt != myFilters.cend(); anIt++) {
124     if (anIt->second->isSupported(theType))
125       aResult.push_back(anIt->second);
126   }
127   return aResult;
128 }
129
130 FilterPtr Model_FiltersFactory::filter(std::string theID)
131 {
132   std::string aPureID = pureFilterID(theID);
133   std::map<std::string, FilterPtr>::iterator aFound = myFilters.find(aPureID);
134   return aFound == myFilters.end() ? FilterPtr() : aFound->second;
135 }
136
137 std::string Model_FiltersFactory::id(FilterPtr theFilter)
138 {
139   std::map<std::string, FilterPtr>::iterator anIter = myFilters.begin();
140   for(; anIter != myFilters.end(); anIter++) {
141     if (anIter->second == theFilter)
142       return anIter->first;
143   }
144   return ""; // unknown case
145 }