Salome HOME
Merge branch 'V9_11_BR'
[modules/shaper.git] / src / Selector / Selector_Container.cpp
1 // Copyright (C) 2014-2023  CEA, EDF
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 <Selector_Container.h>
21
22 #include <Selector_NameGenerator.h>
23 #include <Selector_NExplode.h>
24
25 #include <TNaming_NamedShape.hxx>
26 #include <TDataStd_Name.hxx>
27 #include <TDataStd_Integer.hxx>
28 #include <TDF_ChildIterator.hxx>
29 #include <TopTools_MapOfShape.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <BRep_Tool.hxx>
32 #include <TopoDS.hxx>
33 #include <TopoDS_Builder.hxx>
34 #include <TopoDS_Compound.hxx>
35
36 Selector_Container::Selector_Container() : Selector_AlgoWithSubs()
37 {}
38
39 bool Selector_Container::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
40 {
41   myShapeType = theValue.ShapeType();
42
43   // iterate all sub-shapes and select them on sublabels
44   for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) {
45     Selector_Algo* aSubAlgo = Selector_Algo::select(theContext, aSubIter.Value(),
46       newSubLabel(), baseDocument(),
47       false, useNeighbors(), useIntersections()); //for subs no geometrical naming allowed
48     if (!append(aSubAlgo))
49       return false;
50   }
51   return true;
52 }
53
54 void Selector_Container::store()
55 {
56   storeType(Selector_Algo::SELTYPE_CONTAINER);
57   // store all sub-selectors
58   TDataStd_Integer::Set(label(), shapeTypeID(), (int)myShapeType);
59   std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
60   for(; aSubSel != list().cend(); aSubSel++) {
61     (*aSubSel)->store();
62   }
63   TDataStd_Integer::Set(label(), shapeTypeID(), (int)myShapeType);
64 }
65
66 bool Selector_Container::restore()
67 {
68   Handle(TDataStd_Integer) aShapeTypeAttr;
69   if (!label().FindAttribute(shapeTypeID(), aShapeTypeAttr))
70     return false;
71   myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
72   // restore sub-selectors
73   for(TDF_ChildIterator aSub(label(), false); aSub.More(); aSub.Next()) {
74     Selector_Algo* aSubSel = restoreByLab(aSub.Value(), baseDocument());
75     if (!append(aSubSel, false)) {
76       break; // some empty label left in the end
77     }
78   }
79   return true;
80 }
81
82 TDF_Label Selector_Container::restoreByName(std::wstring theName,
83   const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator)
84 {
85   myShapeType = theShapeType;
86   TDF_Label aContext;
87   for(size_t aStart = 0; aStart != std::wstring::npos; aStart = theName.find('[', aStart + 1)) {
88     size_t anEndPos = theName.find(L']', aStart + 1);
89     if (anEndPos != std::wstring::npos) {
90       // there could be sub-intersections, so, [[...]] case; searching for other open-bracket
91       size_t aNextStart = theName.find(L'[', aStart + 1);
92       while(aNextStart != std::wstring::npos && aNextStart < anEndPos) {
93         anEndPos = theName.find(L']', anEndPos + 1);
94         if (anEndPos == std::wstring::npos) {
95           return TDF_Label(); // invalid parentheses
96         }
97         aNextStart = theName.find(L'[', aNextStart + 1);
98       }
99       if (anEndPos == std::wstring::npos)
100         return TDF_Label(); // invalid parentheses
101       std::wstring aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
102       TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE;
103       switch (myShapeType) {
104       case TopAbs_COMPSOLID: aSubShapeType = TopAbs_SOLID; break;
105       case TopAbs_WIRE: aSubShapeType = TopAbs_EDGE; break;
106       default:;
107       }
108       TDF_Label aSubContext;
109       Selector_Algo* aSubSel =
110         Selector_Algo::restoreByName(newSubLabel(), baseDocument(), aSubStr, aSubShapeType,
111           geometricalNaming(), theNameGenerator, aSubContext);
112       if (!append(aSubSel))
113         return TDF_Label();
114
115       if (aSubContext.IsNull()) {
116         delete aSubSel;
117         clearSubAlgos();
118         return TDF_Label();
119       }
120       if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
121         if (!theNameGenerator->isLater(aContext, aSubContext))
122           aContext = aSubContext;
123       } else {
124         aContext = aSubContext;
125       }
126     } else
127       return TDF_Label(); // invalid parentheses
128     aStart = anEndPos; // for recursive parenthesis set start on the current end
129   }
130   return aContext;
131 }
132
133 bool Selector_Container::solve(const TopoDS_Shape& theContext)
134 {
135   TopoDS_Shape aResult;
136
137   TopoDS_Builder aBuilder;
138   switch(myShapeType) {
139   case TopAbs_COMPOUND: {
140     TopoDS_Compound aComp;
141     aBuilder.MakeCompound(aComp);
142     aResult = aComp;
143     break;
144   }
145   case TopAbs_COMPSOLID: {
146     TopoDS_CompSolid aComp;
147     aBuilder.MakeCompSolid(aComp);
148     aResult = aComp;
149     break;
150   }
151   case TopAbs_SHELL: {
152     TopoDS_Shell aShell;
153     aBuilder.MakeShell(aShell);
154     aResult = aShell;
155     break;
156   }
157   case TopAbs_WIRE: {
158     TopoDS_Wire aWire;
159     aBuilder.MakeWire(aWire);
160     aResult = aWire;
161     break;
162   }
163   default:
164     break;
165   }
166   TopoDS_ListOfShape aSubSelectorShapes;
167   std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
168   for(; aSubSel != list().cend(); aSubSel++) {
169     if (!(*aSubSel)->solve(theContext)) {
170       return false;
171     }
172     aBuilder.Add(aResult, (*aSubSel)->value());
173   }
174   if (!aResult.IsNull()) {
175     Selector_Algo::store(aResult);
176     return true;
177   }
178   return false;
179 }
180
181 std::wstring Selector_Container::name(Selector_NameGenerator* theNameGenerator)
182 {
183   std::wstring aResult;
184   // add names of sub-components one by one in "[]"
185   std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
186   for(; aSubSel != list().cend(); aSubSel++) {
187     aResult += '[';
188     aResult += (*aSubSel)->name(theNameGenerator);
189     aResult += ']';
190   }
191   return aResult;
192 }