Salome HOME
20707c7199aa084147d489a5edb6cf2098fe5737
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Copy.cpp
1 // Copyright (C) 2017-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 "FeaturesPlugin_Copy.h"
21
22 #include <ModelAPI_AttributeSelectionList.h>
23 #include <ModelAPI_AttributeInteger.h>
24 #include <ModelAPI_Tools.h>
25
26 #include <GeomAlgoAPI_Copy.h>
27 #include <GeomAlgoAPI_Tools.h>
28 #include <GeomAPI_ShapeExplorer.h>
29
30 #include <sstream>
31
32 void FeaturesPlugin_Copy::initAttributes()
33 {
34   data()->addAttribute(OBJECTS(), ModelAPI_AttributeSelectionList::typeId());
35   data()->addAttribute(NUMBER(), ModelAPI_AttributeInteger::typeId());
36 }
37
38 static GeomShapePtr shapeOfSelection(AttributeSelectionPtr theSel) {
39   GeomShapePtr aResult;
40   FeaturePtr aSelFeature = theSel->contextFeature();
41   if (aSelFeature.get()) {
42     if (aSelFeature->results().empty()) // if selected feature has no results, make nothing
43       return aResult;
44     if (aSelFeature->results().size() == 1) { // for one sub-result don't make compound
45       aResult = aSelFeature->firstResult()->shape();
46     }
47   }
48   if (!aResult.get())
49     aResult = theSel->value();
50   if (!aResult.get()) {
51     if (theSel->context().get())
52       aResult = theSel->context()->shape();
53   }
54   return aResult;
55 }
56
57 void FeaturesPlugin_Copy::execute()
58 {
59   int aCopiesNum = integer(NUMBER())->value();
60   AttributeSelectionListPtr aList = selectionList(OBJECTS());
61   int aResultIndex = 0;
62   std::set<std::wstring> anExistingNames; // to avoid names duplication
63   for(int aCopy = 0; aCopy < aCopiesNum; aCopy++) {
64     for (int aSelIndex = 0; aSelIndex < aList->size(); aSelIndex++) {
65       AttributeSelectionPtr aSel = aList->value(aSelIndex);
66       GeomShapePtr aShape = shapeOfSelection(aSel);
67       if (!aShape.get())
68         continue;
69       std::shared_ptr<GeomAlgoAPI_Copy> aCopyBuilder(new GeomAlgoAPI_Copy(aShape, false, false));
70       std::string anError;
71       if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCopyBuilder, getKind(), anError)) {
72         setError(anError);
73         return;
74       }
75       GeomShapePtr aResult = aCopyBuilder->shape();
76
77       std::wstring aBaseName = aSel->context() ? aSel->context()->data()->name() :
78         aSel->contextFeature()->firstResult()->data()->name();
79       std::wstring aName;
80       int anInd = 0;
81       do {
82         anInd++;
83         std::wostringstream aNameStr;
84         aNameStr << aBaseName << "_" << (aCopy + anInd);
85         aName = aNameStr.str();
86       } while (anExistingNames.count(aName));
87       anExistingNames.insert(aName);
88
89       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
90         document()->createBody(data(), aResultIndex);
91       aResultBody->data()->setName(aName);
92       // to make sub-results also names with a similar name temporarily rename the feature
93       std::wstring anOrigName = name();
94       data()->setName(aBaseName);
95       aResultBody->store(aResult);
96       data()->setName(anOrigName);
97       aResultBody->loadFirstLevel(aResult, "Copy");
98       setResult(aResultBody, aResultIndex++);
99     }
100   }
101   removeResults(aResultIndex);
102 }
103
104 void FeaturesPlugin_Copy::getCopies(
105   ObjectPtr theContext, std::shared_ptr<GeomAPI_Shape> theValue,
106   std::list<ObjectPtr>& theCopyContext, std::list<std::shared_ptr<GeomAPI_Shape> >& theCopyVals)
107 {
108   ResultPtr aContextRes = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);
109   GeomShapePtr aGroupValue = theValue.get() ? theValue : aContextRes->shape();
110
111   AttributeSelectionListPtr aList = selectionList(OBJECTS());
112   std::list<ResultPtr>::const_iterator aResIter = results().cbegin();
113   while(aResIter != results().cend()) { // do as long as many iterations
114     for (int aSelIndex = 0; aSelIndex < aList->size(); aSelIndex++) {
115       if (aResIter == results().cend()) // no more results corresponding to the selection
116         return;
117       AttributeSelectionPtr aSel = aList->value(aSelIndex);
118       GeomShapePtr aShape = shapeOfSelection(aSel);
119       if (!aShape.get())
120         continue;
121
122       if (aShape->isSubShape(aGroupValue, false)) { // group value is subshape of copied => copy
123         // search the same result in the copy by the same index of sub-shape in the shape
124         GeomAPI_ShapeExplorer anOrigExp(aShape, aGroupValue->shapeType());
125         GeomAPI_ShapeExplorer aCopyShape((*aResIter)->shape(), aGroupValue->shapeType());
126         for(; anOrigExp.more(); anOrigExp.next(), aCopyShape.next()) {
127           if (anOrigExp.current()->isSame(aGroupValue)) {
128             // searching for sub-result if it is composite result, but context-not
129             ResultPtr aResContext = *aResIter;
130             if (aContextRes->shape()->shapeType() > (*aResIter)->shape()->shapeType()) {
131               ResultBodyPtr aResBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResContext);
132               if (aResBody.get()) {
133                 std::list<ResultPtr> aSubs;
134                 ModelAPI_Tools::allSubs(aResBody, aSubs, true);
135                 std::list<ResultPtr>::iterator aSubIter = aSubs.begin();
136                 for(; aSubIter != aSubs.end(); aSubIter++) {
137                   GeomShapePtr aSubShape = (*aSubIter)->shape();
138                   if (aSubShape.get() && aSubShape->isSubShape(aCopyShape.current(), false)) {
139                     aResContext = *aSubIter;
140                     break;
141                   }
142                 }
143               }
144             }
145             theCopyContext.push_back(aResContext);
146             theCopyVals.push_back(aResContext->shape()->isSame(
147               aCopyShape.current()) ? GeomShapePtr() : aCopyShape.current());
148             break;
149           }
150         }
151       }
152       aResIter++;
153     }
154   }
155 }