Salome HOME
Meet the coding style (split too long lines)
[modules/shaper.git] / src / BuildPlugin / BuildPlugin_Vertex.cpp
1 // Copyright (C) 2014-2019  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 "BuildPlugin_Vertex.h"
21
22 #include <ModelAPI_AttributeSelectionList.h>
23 #include <ModelAPI_AttributeBoolean.h>
24 #include <ModelAPI_CompositeFeature.h>
25 #include <ModelAPI_ResultBody.h>
26 #include <ModelAPI_Validator.h>
27 #include <ModelAPI_Session.h>
28
29 #include <GeomAlgoAPI_Copy.h>
30 #include <GeomAlgoAPI_Tools.h>
31 #include <GeomAlgoAPI_Partition.h>
32 #include <GeomAlgoAPI_ShapeTools.h>
33
34 #include <GeomAPI_ShapeExplorer.h>
35
36 //=================================================================================================
37 BuildPlugin_Vertex::BuildPlugin_Vertex()
38 {
39 }
40
41 //=================================================================================================
42 void BuildPlugin_Vertex::initAttributes()
43 {
44   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
45
46   data()->addAttribute(INTERSECT_ID(), ModelAPI_AttributeBoolean::typeId());
47   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID());
48 }
49
50 //=================================================================================================
51 bool BuildPlugin_Vertex::buildVertices(GeomShapePtr theShape,
52                                        bool isIntersect,
53                                        int& theResultIndex)
54 {
55   if (!theShape.get()) {
56     setError("Error: Empty shape selected.");
57     return false;
58   }
59
60   if (theShape->shapeType() == GeomAPI_Shape::VERTEX) {
61     // Copy shape.
62     std::shared_ptr<GeomAlgoAPI_Copy> aCopyAlgo(new GeomAlgoAPI_Copy(theShape));
63
64     std::string anError;
65     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCopyAlgo, getKind(), anError)) {
66       setError(anError);
67       return false;
68     }
69
70     // Store result.
71     ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
72     aResultBody->storeModified(theShape, aCopyAlgo->shape());
73     setResult(aResultBody, theResultIndex);
74     ++theResultIndex;
75   } else {
76     // Sketch
77     GeomAPI_DataMapOfShapeShape alreadyProcessed;
78
79     // 1. Explode on Vertices
80     for (GeomAPI_ShapeExplorer anExp (theShape, GeomAPI_Shape::VERTEX);
81          anExp.more(); anExp.next()) {
82       GeomShapePtr aSubShape = anExp.current();
83
84       if (alreadyProcessed.bind(aSubShape, aSubShape)) {
85         // Store result.
86         ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
87         aResultBody->storeModified(theShape, aSubShape);
88         setResult(aResultBody, theResultIndex);
89         ++theResultIndex;
90       }
91     }
92
93     // 2. If need intersection points, perform Partition
94     if (isIntersect) {
95       // Partition
96       ListOfShape anObjList, aTools;
97       anObjList.push_back(theShape);
98       std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo (
99           new GeomAlgoAPI_Partition(anObjList, aTools));
100
101       std::string anError;
102       if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
103         setError(anError);
104         return false;
105       }
106       GeomShapePtr aSplittedSketch = aPartitionAlgo->shape();
107
108       // Explode on Vertices, skip vertices of initial sketch
109       for (GeomAPI_ShapeExplorer anExp (aSplittedSketch, GeomAPI_Shape::VERTEX);
110            anExp.more(); anExp.next()) {
111         GeomShapePtr aSubShape = anExp.current();
112
113         //if (!theShape->isSubShape(aSubShape)) { // skip vertices of initial sketch
114         if (alreadyProcessed.bind(aSubShape, aSubShape)) {
115           // Store result.
116           ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
117           aResultBody->storeGenerated(anObjList, aSubShape, aPartitionAlgo);
118           setResult(aResultBody, theResultIndex);
119           ++theResultIndex;
120         }
121       }
122     }
123   }
124
125   return true;
126 }
127
128 //=================================================================================================
129 bool BuildPlugin_Vertex::buildVertices(FeaturePtr theFeature,
130                                        bool isIntersect,
131                                        int& theResultIndex)
132 {
133   if (theFeature->getKind() != "Sketch") return false;
134
135   // Sub-features
136   CompositeFeaturePtr aComposite =
137     std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
138   if (!aComposite) return false;
139   int nbSubs = aComposite->numberOfSubs();
140   if (nbSubs < 1) return false;
141
142   // The whole sketch shape
143   ResultPtr aContext = theFeature->firstResult();
144   GeomShapePtr theShape = aContext->shape();
145
146   GeomAPI_DataMapOfShapeShape alreadyProcessed;
147
148   // 1. Explode on Vertices
149   for (GeomAPI_ShapeExplorer anExp (theShape, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
150     GeomShapePtr aSubShape = anExp.current();
151
152     if (alreadyProcessed.bind(aSubShape, aSubShape)) {
153       // Store result.
154       ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
155       aResultBody->storeModified(theShape, aSubShape);
156       setResult(aResultBody, theResultIndex);
157       ++theResultIndex;
158     }
159   }
160
161   // 2. If need intersection points, perform Partition
162   if (isIntersect) {
163     // Partition
164     ListOfShape anObjList, aTools;
165     anObjList.push_back(theShape);
166     std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo (
167         new GeomAlgoAPI_Partition(anObjList, aTools));
168
169     std::string anError;
170     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
171       setError(anError);
172       return false;
173     }
174     GeomShapePtr aSplittedSketch = aPartitionAlgo->shape();
175
176     // Explode on Vertices, skip vertices of initial sketch
177     for (GeomAPI_ShapeExplorer anExp (aSplittedSketch, GeomAPI_Shape::VERTEX);
178          anExp.more(); anExp.next()) {
179       GeomShapePtr aSubShape = anExp.current();
180
181       //if (!theShape->isSubShape(aSubShape)) { // skip vertices of initial sketch
182       if (alreadyProcessed.bind(aSubShape, aSubShape)) {
183         // Store result.
184         ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
185         aResultBody->storeGenerated(anObjList, aSubShape, aPartitionAlgo);
186         setResult(aResultBody, theResultIndex);
187         ++theResultIndex;
188       }
189     }
190   }
191
192   // 3. Add construction points (centers of circles, etc.)
193   for (int i = 0; i < nbSubs; i++) {
194     FeaturePtr aSubFeature = aComposite->subFeature(i);
195     const std::list<ResultPtr>& aSubResults = aSubFeature->results();
196     std::list<ResultPtr>::const_iterator anItRes = aSubResults.cbegin();
197     // Iterate on all sub-results
198     for (; anItRes != aSubResults.cend(); anItRes++) {
199       ResultPtr aRes = *anItRes;
200       if (aRes.get()) {
201         // Sub-result i
202         GeomShapePtr aSubResShape = aRes->shape();
203
204         for (GeomAPI_ShapeExplorer anExp (aSubResShape, GeomAPI_Shape::VERTEX);
205              anExp.more(); anExp.next()) {
206           GeomShapePtr aSubShape = anExp.current();
207
208           if (alreadyProcessed.bind(aSubShape, aSubShape)) {
209             // Store result.
210             ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
211             aResultBody->storeModified(theShape, aSubShape);
212             setResult(aResultBody, theResultIndex);
213             ++theResultIndex;
214           }
215         }
216       }
217     }
218   }
219
220   return true;
221 }
222
223 void BuildPlugin_Vertex::execute()
224 {
225   // Get base objects list.
226   AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
227   if (!aSelectionList.get()) {
228     setError("Error: Could not get selection list.");
229     return;
230   }
231   if (aSelectionList->size() == 0) {
232     setError("Error: Empty selection list.");
233     return;
234   }
235
236   // Get "Compute intersections" flag value
237   bool isIntersect = false;
238   if (boolean(INTERSECT_ID()).get() && boolean(INTERSECT_ID())->isInitialized()) {
239     isIntersect = boolean(INTERSECT_ID())->value();
240   }
241
242   // Iterate arguments and build results
243   int aResultIndex = 0;
244   for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
245     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
246     GeomShapePtr aShape = aSelection->value();
247     if (aShape.get()) {
248       // A shape selected
249       if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
250     } else {
251       ResultPtr aContext = aSelection->context();
252       if (aContext.get()) { // Result selected
253         FeaturePtr aFeature = ModelAPI_Feature::feature(aContext);
254         if (aFeature.get()) {
255           if (aFeature->getKind() == "Sketch") {
256             // Special processing for sketch to build center vertices etc.
257             if (!buildVertices(aFeature, isIntersect, aResultIndex)) return;
258           } else {
259             aShape = aContext->shape();
260             if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
261           }
262         }
263       } else {
264         FeaturePtr aFeature = aSelection->contextFeature();
265         if (aFeature.get()) { // Feature selected
266           if (aFeature->getKind() == "Sketch") {
267             // Special processing for sketch to build center vertices etc.
268             if (!buildVertices(aFeature, isIntersect, aResultIndex)) return;
269           } else {
270             const std::list<ResultPtr>& anArgResults = aFeature->results();
271             std::list<ResultPtr>::const_iterator anItRes = anArgResults.cbegin();
272             // Iterate on all its results
273             for (; anItRes != anArgResults.cend(); anItRes++) {
274               ResultPtr aRes = *anItRes;
275               if (aRes.get()) {
276                 // Result i
277                 aShape = aRes->shape();
278                 if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
279               }
280             }
281           }
282         }
283       }
284     }
285   }
286
287   // Remove extra results from previous execution
288   removeResults(aResultIndex);
289 }