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