Salome HOME
Copyright update 2020
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_CompositeSketch.cpp
1 // Copyright (C) 2014-2020  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_CompositeSketch.h>
21 #include <FeaturesPlugin_Tools.h>
22
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeReference.h>
25 #include <ModelAPI_BodyBuilder.h>
26 #include <ModelAPI_ResultConstruction.h>
27 #include <ModelAPI_Session.h>
28 #include <ModelAPI_Validator.h>
29
30 #include <GeomAlgoAPI_Revolution.h>
31
32 #include <GeomAPI_ShapeExplorer.h>
33
34
35 static void storeSubShape(const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
36                           ResultBodyPtr theResultBody,
37                           const GeomShapePtr theShape,
38                           const GeomAPI_Shape::ShapeType theType,
39                           const std::string& theName);
40
41 //=================================================================================================
42 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
43 {
44   // Initialize sketch launcher.
45   if(theInitFlags & InitSketchLauncher) {
46     data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId());
47     ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID());
48   }
49
50   // Initialize selection list.
51   if(theInitFlags & InitBaseObjectsList) {
52     data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
53   }
54 }
55
56 //=================================================================================================
57 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::addFeature(std::string theID)
58 {
59   FeaturePtr aNew = document()->addFeature(theID, false);
60   if(aNew) {
61     data()->reference(SKETCH_ID())->setValue(aNew);
62   }
63
64   // Set as current also after it becomes sub to set correctly enabled for other sketch subs.
65   document()->setCurrentFeature(aNew, false);
66   return aNew;
67 }
68
69 //=================================================================================================
70 int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const
71 {
72   ObjectPtr aObj = data()->reference(SKETCH_ID())->value();
73   return aObj.get() ? 1 : 0;
74 }
75
76 //=================================================================================================
77 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::subFeature(const int theIndex,
78                                                                              bool forTree)
79 {
80   FeaturePtr aSubFeature;
81   if(theIndex == 0) {
82     aSubFeature =
83         std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
84   }
85   return aSubFeature;
86 }
87
88 //=================================================================================================
89 int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const
90 {
91   if(theIndex == 0) {
92     FeaturePtr aFeature =
93       std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
94     if(aFeature.get()) {
95       return aFeature->data()->featureId();
96     }
97   }
98
99   return -1;
100 }
101
102 //=================================================================================================
103 bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const
104 {
105   bool isSubFeature = false;
106   // Check is this feature of result
107   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
108   if (aFeature.get()) {
109     ObjectPtr aSub = data()->reference(SKETCH_ID())->value();
110     isSubFeature = aSub == theObject;
111   }
112   return isSubFeature;
113 }
114
115 //=================================================================================================
116 void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
117 {
118   AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
119   if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) {
120     aBaseObjectsSelectionList->clear();
121   }
122
123   reference(SKETCH_ID())->setValue(ObjectPtr());
124 }
125
126 //=================================================================================================
127 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
128                                                    const bool theIsMakeShells)
129 {
130   AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
131   std::string anError;
132   bool isOk = FeaturesPlugin_Tools::getShape(
133       aBaseObjectsSelectionList, theIsMakeShells, theBaseShapesList, anError);
134   if (!isOk)
135     setError(anError);
136 }
137
138 //=================================================================================================
139 void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape,
140                                         const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
141                                         const int theIndex)
142 {
143   // Create result body.
144   ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
145
146   // Store generated shape.
147   aResultBody->storeGenerated(theBaseShape, theMakeShape->shape());
148
149   // Store generated edges/faces.
150   storeGenerationHistory(aResultBody, theBaseShape, theMakeShape);
151
152   setResult(aResultBody, theIndex);
153 }
154
155 //=================================================================================================
156 void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody,
157                                         const GeomShapePtr theBaseShape,
158                                         const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
159 {
160   GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
161   GeomAPI_Shape::ShapeType aShapeTypeToExplode = GeomAPI_Shape::SHAPE;
162
163   switch(aBaseShapeType) {
164     case GeomAPI_Shape::EDGE: {
165             aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
166       break;
167     }
168     case GeomAPI_Shape::WIRE: {
169       aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
170       break;
171     }
172     case GeomAPI_Shape::FACE:
173     case GeomAPI_Shape::SHELL: {
174       aShapeTypeToExplode = GeomAPI_Shape::EDGE;
175       break;
176     }
177     case GeomAPI_Shape::COMPOUND: {
178       aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
179     }
180   }
181
182   int aLateralIndex = 1;
183   int aBaseEdgeIndex = 1;
184   int aVertexIndex = 1;
185   int aBaseVertexIndex = 1;
186
187   if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
188       aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
189     theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX);
190   }
191   if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
192       aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
193     theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE);
194   }
195   std::list<std::shared_ptr<GeomAlgoAPI_MakeSweep> > aSweeps; // all sweeps collected
196   std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep =
197     std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
198   if(aMakeSweep.get()) {
199     aSweeps.push_back(aMakeSweep);
200   } else {
201     std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeList =
202       std::dynamic_pointer_cast<GeomAlgoAPI_MakeShapeList>(theMakeShape);
203     if (aMakeList.get()) {
204       ListOfMakeShape::const_iterator anIter = aMakeList->list().cbegin();
205       for(; anIter != aMakeList->list().cend(); anIter++) {
206         std::shared_ptr<GeomAlgoAPI_MakeSweep> aSweep =
207           std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(*anIter);
208         if (aSweep.get())
209           aSweeps.push_back(aSweep);
210       }
211     }
212   }
213   std::list<std::shared_ptr<GeomAlgoAPI_MakeSweep> >::iterator aSweep = aSweeps.begin();
214   for(; aSweep != aSweeps.end(); aSweep++) {
215     // Store from shapes.
216     storeShapes(theMakeShape, theResultBody, aBaseShapeType, (*aSweep)->fromShapes(), "From_");
217
218     // Store to shapes.
219     storeShapes(theMakeShape, theResultBody, aBaseShapeType, (*aSweep)->toShapes(), "To_");
220   }
221 }
222
223 //=================================================================================================
224 void FeaturesPlugin_CompositeSketch::storeShapes(
225   const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
226   ResultBodyPtr theResultBody,
227   const GeomAPI_Shape::ShapeType theBaseShapeType,
228   const ListOfShape& theShapes,
229   const std::string theName)
230 {
231   GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
232   std::string aShapeTypeStr = "Face";
233   switch(theBaseShapeType) {
234     case GeomAPI_Shape::VERTEX: {
235       aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
236       aShapeTypeStr = "Vertex";
237       break;
238     }
239     case GeomAPI_Shape::EDGE:
240     case GeomAPI_Shape::WIRE: {
241       aShapeTypeToExplore = GeomAPI_Shape::EDGE;
242       aShapeTypeStr = "Edge";
243       break;
244     }
245     case GeomAPI_Shape::FACE:
246     case GeomAPI_Shape::SHELL: {
247       aShapeTypeToExplore = GeomAPI_Shape::FACE;
248       aShapeTypeStr = "Face";
249       break;
250     }
251     case GeomAPI_Shape::COMPOUND: {
252       aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
253       break;
254     }
255   }
256
257   // Store shapes.
258   for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
259     GeomShapePtr aShape = *anIt;
260
261     if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
262       std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
263       storeSubShape(theMakeShape, theResultBody, aShape, aShape->shapeType(), aName);
264     } else {
265       std::string aName = theName + aShapeTypeStr;
266       storeSubShape(theMakeShape, theResultBody, aShape, aShapeTypeToExplore, aName);
267       if (theBaseShapeType == GeomAPI_Shape::WIRE) { // issue 2289: special names also for vertices
268         aName = theName + "Vertex";
269         storeSubShape(theMakeShape, theResultBody, aShape, GeomAPI_Shape::VERTEX, aName);
270       }
271     }
272   }
273 }
274
275 void storeSubShape(
276   const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
277   ResultBodyPtr theResultBody,
278   const GeomShapePtr theShape,
279   const GeomAPI_Shape::ShapeType theType,
280   const std::string& theName)
281 {
282   for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
283     GeomShapePtr aSubShape = anExp.current();
284     if (!theResultBody->generated(aSubShape, theName)) {
285       // store from/to shapes as primitives and then store modification of them by the boolean
286       theResultBody->generated(aSubShape, theName, false);
287       theResultBody->loadModifiedShapes(theMakeShape, aSubShape, theType);
288     }
289   }
290 }