1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <Selector_Selector.h>
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>
30 #include <TDataStd_Integer.hxx>
31 #include <TDataStd_ReferenceArray.hxx>
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");
41 Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
45 TDF_Label Selector_Selector::label()
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)
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))
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);
80 bool Selector_Selector::Select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
82 if (theValue.IsNull() || theContext.IsNull())
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
97 myType = SELTYPE_CONTAINER;
98 myShapeType = aSelectionType;
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());
116 //TODO: check if intersectors produce several subs, try to remove one of the intersector
118 // name the intersectors
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())
127 TNaming_Evolution anEvolution = aNewShapes.NamedShape()->Evolution();
128 if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as primitive => PRIMITIVE
129 aPrimitiveNS = aNewShapes.NamedShape();
131 } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
132 aModifList.Append(aNewShapes.NamedShape());
136 if (!aPrimitiveNS.IsNull()) {
137 myType = SELTYPE_PRIMITIVE;
138 myFinal = aPrimitiveNS->Label();
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
158 // take the best candidate, or the last in the iteration
160 aModifList.Append(aCandidate);
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();
171 // not found a good result
175 void Selector_Selector::Store()
177 TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
179 case SELTYPE_CONTAINER: {
183 case SELTYPE_INTERSECT: {
187 case SELTYPE_PRIMITIVE: {
188 Handle(TDataStd_ReferenceArray) anArray = TDataStd_ReferenceArray::Set(myLab, 0, 0);
189 anArray->SetValue(0, myBases.First());
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());
201 default: { // unknown case