Salome HOME
Task #3079 3.5 Build/Vertex on a whole Sketch
[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); anExp.more(); anExp.next()) {
81       GeomShapePtr aSubShape = anExp.current();
82
83       if (alreadyProcessed.bind(aSubShape, aSubShape)) {
84         // Store result.
85         ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
86         aResultBody->storeModified(theShape, aSubShape);
87         setResult(aResultBody, theResultIndex);
88         ++theResultIndex;
89       }
90     }
91
92     // 2. If need intersection points, perform Partition
93     if (isIntersect) {
94       // Partition
95       ListOfShape anObjList, aTools;
96       anObjList.push_back(theShape);
97       std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo (new GeomAlgoAPI_Partition(anObjList, aTools));
98
99       std::string anError;
100       if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
101         setError(anError);
102         return false;
103       }
104       GeomShapePtr aSplittedSketch = aPartitionAlgo->shape();
105
106       // Explode on Vertices, skip vertices of initial sketch
107       for (GeomAPI_ShapeExplorer anExp (aSplittedSketch, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
108         GeomShapePtr aSubShape = anExp.current();
109
110         //if (!theShape->isSubShape(aSubShape)) { // skip vertices of initial sketch
111         if (alreadyProcessed.bind(aSubShape, aSubShape)) {
112           // Store result.
113           ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
114           aResultBody->storeGenerated(anObjList, aSubShape, aPartitionAlgo);
115           setResult(aResultBody, theResultIndex);
116           ++theResultIndex;
117         }
118       }
119     }
120   }
121
122   return true;
123 }
124
125 //=================================================================================================
126 bool BuildPlugin_Vertex::buildVertices(FeaturePtr theFeature,
127                                        bool isIntersect,
128                                        int& theResultIndex)
129 {
130   if (theFeature->getKind() != "Sketch") return false;
131
132   // Sub-features
133   CompositeFeaturePtr aComposite =
134     std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
135   if (!aComposite) return false;
136   int nbSubs = aComposite->numberOfSubs();
137   if (nbSubs < 1) return false;
138
139   // The whole sketch shape
140   ResultPtr aContext = theFeature->firstResult();
141   GeomShapePtr theShape = aContext->shape();
142
143   GeomAPI_DataMapOfShapeShape alreadyProcessed;
144
145   // 1. Explode on Vertices
146   for (GeomAPI_ShapeExplorer anExp (theShape, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
147     GeomShapePtr aSubShape = anExp.current();
148
149     if (alreadyProcessed.bind(aSubShape, aSubShape)) {
150       // Store result.
151       ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
152       aResultBody->storeModified(theShape, aSubShape);
153       setResult(aResultBody, theResultIndex);
154       ++theResultIndex;
155     }
156   }
157
158   // 2. If need intersection points, perform Partition
159   if (isIntersect) {
160     // Partition
161     ListOfShape anObjList, aTools;
162     anObjList.push_back(theShape);
163     std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo (new GeomAlgoAPI_Partition(anObjList, aTools));
164
165     std::string anError;
166     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
167       setError(anError);
168       return false;
169     }
170     GeomShapePtr aSplittedSketch = aPartitionAlgo->shape();
171
172     // Explode on Vertices, skip vertices of initial sketch
173     for (GeomAPI_ShapeExplorer anExp (aSplittedSketch, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
174       GeomShapePtr aSubShape = anExp.current();
175
176       //if (!theShape->isSubShape(aSubShape)) { // skip vertices of initial sketch
177       if (alreadyProcessed.bind(aSubShape, aSubShape)) {
178         // Store result.
179         ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
180         aResultBody->storeGenerated(anObjList, aSubShape, aPartitionAlgo);
181         setResult(aResultBody, theResultIndex);
182         ++theResultIndex;
183       }
184     }
185   }
186
187   // 3. Add construction points (centers of circles, etc.)
188   for (int i = 0; i < nbSubs; i++) {
189     FeaturePtr aSubFeature = aComposite->subFeature(i);
190     const std::list<ResultPtr>& aSubResults = aSubFeature->results();
191     std::list<ResultPtr>::const_iterator anItRes = aSubResults.cbegin();
192     // Iterate on all sub-results
193     for (; anItRes != aSubResults.cend(); anItRes++) {
194       ResultPtr aRes = *anItRes;
195       if (aRes.get()) {
196         // Sub-result i
197         GeomShapePtr aSubResShape = aRes->shape();
198
199         for (GeomAPI_ShapeExplorer anExp (aSubResShape, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
200           GeomShapePtr aSubShape = anExp.current();
201
202           if (alreadyProcessed.bind(aSubShape, aSubShape)) {
203             // Store result.
204             ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
205             aResultBody->storeModified(theShape, aSubShape);
206             setResult(aResultBody, theResultIndex);
207             ++theResultIndex;
208           }
209         }
210       }
211     }
212   }
213
214   return true;
215 }
216
217 void BuildPlugin_Vertex::execute()
218 {
219   // Get base objects list.
220   AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
221   if (!aSelectionList.get()) {
222     setError("Error: Could not get selection list.");
223     return;
224   }
225   if (aSelectionList->size() == 0) {
226     setError("Error: Empty selection list.");
227     return;
228   }
229
230   // Get "Compute intersections" flag value
231   bool isIntersect = false;
232   if (boolean(INTERSECT_ID()).get() && boolean(INTERSECT_ID())->isInitialized()) {
233     isIntersect = boolean(INTERSECT_ID())->value();
234   }
235
236   // Iterate arguments and build results
237   int aResultIndex = 0;
238   for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
239     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
240     GeomShapePtr aShape = aSelection->value();
241     if (aShape.get()) {
242       // A shape selected
243       if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
244     } else {
245       ResultPtr aContext = aSelection->context();
246       if (aContext.get()) { // Result selected
247         FeaturePtr aFeature = ModelAPI_Feature::feature(aContext);
248         if (aFeature.get()) {
249           if (aFeature->getKind() == "Sketch") {
250             // Special processing for sketch to build center vertices etc.
251             if (!buildVertices(aFeature, isIntersect, aResultIndex)) return;
252           } else {
253             aShape = aContext->shape();
254             if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
255           }
256         }
257       } else {
258         FeaturePtr aFeature = aSelection->contextFeature();
259         if (aFeature.get()) { // Feature selected
260           if (aFeature->getKind() == "Sketch") {
261             // Special processing for sketch to build center vertices etc.
262             if (!buildVertices(aFeature, isIntersect, aResultIndex)) return;
263           } else {
264             const std::list<ResultPtr>& anArgResults = aFeature->results();
265             std::list<ResultPtr>::const_iterator anItRes = anArgResults.cbegin();
266             // Iterate on all its results
267             for (; anItRes != anArgResults.cend(); anItRes++) {
268               ResultPtr aRes = *anItRes;
269               if (aRes.get()) {
270                 // Result i
271                 aShape = aRes->shape();
272                 if (!buildVertices(aShape, isIntersect, aResultIndex)) return;
273               }
274             }
275           }
276         }
277       }
278     }
279   }
280
281   // Remove extra results from previous execution
282   removeResults(aResultIndex);
283 }