]> SALOME platform Git repositories - modules/shaper.git/blob - src/Selector/Selector_Selector.cpp
Salome HOME
45880cab08e24decdc3397901b311dcc94450ea5
[modules/shaper.git] / src / Selector / Selector_Selector.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 <Selector_Selector.h>
22
23 #include <TopoDS_Iterator.hxx>
24 #include <TopExp_Explorer.hxx>
25 #include <TNaming_Tool.hxx>
26 #include <TNaming_NewShapeIterator.hxx>
27 #include <TNaming_Iterator.hxx>
28 #include <TopTools_MapOfShape.hxx>
29
30 #include <TDataStd_Integer.hxx>
31 #include <TDataStd_ReferenceArray.hxx>
32
33 #include <list>
34
35 /// type of the selection, integerm keeps the Selector_Type value
36 static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
37 //  reference attribute that contains the reference to labels where the "from" or "base" shapes
38 // of selection are located
39 static const Standard_GUID kBASE_LIST("7c515b1a-9549-493d-9946-a4933a22f45f");
40
41 Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
42 {
43 }
44
45 TDF_Label Selector_Selector::label()
46 {
47   return myLab;
48 }
49
50 // adds to theResult all labels that contain initial shapes for theValue located in theFinal
51 static void findBases(Handle(TNaming_NamedShape) theFinal, const TopoDS_Shape& theValue,
52   TDF_LabelList& theResult)
53 {
54   for(TNaming_Iterator aThisIter(theFinal); aThisIter.More(); aThisIter.Next()) {
55     if (aThisIter.NewShape().IsSame(theValue)) {
56       const TopoDS_Shape& anOldShape = aThisIter.OldShape();
57       // searching for all old shapes in this sequence of modification
58       TNaming_NewShapeIterator aNSIter(anOldShape, theFinal->Label());
59       for(; aNSIter.More(); aNSIter.Next()) {
60         TNaming_Evolution anEvolution = aNSIter.NamedShape()->Evolution();
61         if (anEvolution == TNaming_PRIMITIVE) { // found a good candidate, a base shape
62           // check that this is not in the results already
63           const TDF_Label aResult = aNSIter.NamedShape()->Label();
64           TDF_LabelList::Iterator aResIter(theResult);
65           for(; aResIter.More(); aResIter.Next()) {
66             if (aResIter.Value().IsEqual(aResult))
67               break;
68           }
69           if (!aResIter.More()) // not found, so add this new
70             theResult.Append(aResult);
71         } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
72           // continue recursively
73           findBases(aNSIter.NamedShape(), anOldShape, theResult);
74         }
75       }
76     }
77   }
78 }
79
80 bool Selector_Selector::Select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
81 {
82   if (theValue.IsNull() || theContext.IsNull())
83     return false;
84   // check the value shape can be named as it is, or it is needed to construct it from the
85   // higher level shapes (like a box vertex by faces that form this vertex)
86   if (!TNaming_Tool::HasLabel(myLab, theValue)) {
87     TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
88     if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
89         aSelectionType == TopAbs_SOLID) { // iterate all sub-shapes and select them on sublabels
90       std::list<Selector_Selector> aSubSelList;
91       for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) {
92         aSubSelList.push_back(Selector_Selector(myLab.FindChild(aSubSelList.size() + 1)));
93         if (!aSubSelList.back().Select(theContext, aSubIter.Value())) {
94           return false; // if some selector is failed, everything is failed
95         }
96       }
97       myType = SELTYPE_CONTAINER;
98       myShapeType = aSelectionType;
99       return true;
100     }
101
102     // try to find the shape of the higher level type in the context shape
103     while(aSelectionType != TopAbs_FACE) {
104       if (aSelectionType == TopAbs_VERTEX) aSelectionType = TopAbs_EDGE;
105       else if (aSelectionType == TopAbs_EDGE) aSelectionType = TopAbs_FACE;
106       TopTools_MapOfShape anIntersectors; // shapes of aSelectionType that contain theValue
107       for(TopExp_Explorer aSelExp(theContext, aSelectionType); aSelExp.More(); aSelExp.Next()) {
108         TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType());
109         for(; aSubExp.More(); aSubExp.Next()) {
110           if (aSubExp.Current().IsSame(theValue)) {
111             anIntersectors.Add(aSelExp.Current());
112             break;
113           }
114         }
115       }
116       //TODO: check if intersectors produce several subs, try to remove one of the intersector
117
118       // name the intersectors
119
120     }
121   }
122   // searching for the base shapes of the value
123   Handle(TNaming_NamedShape) aPrimitiveNS;
124   NCollection_List<Handle(TNaming_NamedShape)> aModifList;
125   for(TNaming_NewShapeIterator aNewShapes(theValue, myLab); aNewShapes.More(); aNewShapes.Next())
126   {
127     TNaming_Evolution anEvolution = aNewShapes.NamedShape()->Evolution();
128     if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as primitive => PRIMITIVE
129       aPrimitiveNS = aNewShapes.NamedShape();
130       break;
131     } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
132       aModifList.Append(aNewShapes.NamedShape());
133     }
134   }
135
136   if (!aPrimitiveNS.IsNull()) {
137     myType = SELTYPE_PRIMITIVE;
138     myFinal = aPrimitiveNS->Label();
139     return true;
140   }
141
142   if (aModifList.Extent() > 1) { // searching for the best modification result: by context
143     Handle(TNaming_NamedShape) aCandidate;
144     NCollection_List<Handle(TNaming_NamedShape)>::Iterator aModIter(aModifList);
145     for(; !aModifList.IsEmpty() && aModIter.More(); aModIter.Next()) {
146        aCandidate = aModIter.Value();
147       TDF_Label aFatherLab = aCandidate->Label().Father();
148       Handle(TNaming_NamedShape) aFatherNS;
149       if (aFatherLab.FindAttribute(TNaming_NamedShape::GetID(), aFatherNS)) {
150         for(TNaming_Iterator anIter(aFatherNS); anIter.More(); anIter.Next()) {
151           if (theContext.IsSame(anIter.NewShape())) { // found the best modification
152             aModifList.Clear();
153             break;
154           }
155         }
156       }
157     }
158     // take the best candidate, or the last in the iteration
159     aModifList.Clear();
160     aModifList.Append(aCandidate);
161   }
162
163   if (!aModifList.IsEmpty()) {
164     // searching for all the base shapes of this modification
165     findBases(aModifList.First(), theValue, myBases);
166     myFinal = aModifList.First()->Label();
167     myType = SELTYPE_MODIFICATION;
168     return !myBases.IsEmpty();
169   }
170
171   // not found a good result
172   return false;
173 }
174
175 void Selector_Selector::Store()
176 {
177   TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
178   switch(myType) {
179   case SELTYPE_CONTAINER: {
180     /// TODO
181     break;
182   }
183   case SELTYPE_INTERSECT: {
184     /// TODO
185     break;
186   }
187   case SELTYPE_PRIMITIVE: {
188     Handle(TDataStd_ReferenceArray) anArray = TDataStd_ReferenceArray::Set(myLab, 0, 0);
189     anArray->SetValue(0, myBases.First());
190     break;
191   }
192   case SELTYPE_MODIFICATION: {
193     Handle(TDataStd_ReferenceArray) anArray =
194       TDataStd_ReferenceArray::Set(myLab, 0, myBases.Extent() - 1);
195     TDF_LabelList::Iterator aBIter(myBases);
196     for(int anIndex = 0; aBIter.More(); aBIter.Next(), anIndex++) {
197       anArray->SetValue(anIndex, aBIter.Value());
198     }
199     break;
200   }
201   default: { // unknown case
202     break;
203   }
204   }
205 }