1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: FeaturesPlugin_CompositeSketch.cpp
4 // Created: 11 September 2015
5 // Author: Dmitry Bobylev
7 #include <FeaturesPlugin_CompositeSketch.h>
9 #include <ModelAPI_AttributeSelectionList.h>
10 #include <ModelAPI_AttributeReference.h>
11 #include <ModelAPI_BodyBuilder.h>
12 #include <ModelAPI_ResultConstruction.h>
13 #include <ModelAPI_Session.h>
14 #include <ModelAPI_Validator.h>
16 #include <GeomAlgoAPI_CompoundBuilder.h>
17 #include <GeomAlgoAPI_Prism.h>
18 #include <GeomAlgoAPI_Revolution.h>
19 #include <GeomAlgoAPI_ShapeTools.h>
20 #include <GeomAPI_ShapeExplorer.h>
24 //=================================================================================================
25 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
27 // Initialize sketch launcher.
28 if(theInitFlags & InitSketchLauncher) {
29 data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId());
30 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID());
33 // Initialize selection list.
34 if(theInitFlags & InitBaseObjectsList) {
35 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
39 //=================================================================================================
40 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::addFeature(std::string theID)
42 FeaturePtr aNew = document()->addFeature(theID, false);
44 data()->reference(SKETCH_ID())->setValue(aNew);
47 // Set as current also after it becomes sub to set correctly enabled for other sketch subs.
48 document()->setCurrentFeature(aNew, false);
52 //=================================================================================================
53 int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const
55 ObjectPtr aObj = data()->reference(SKETCH_ID())->value();
56 return aObj.get() ? 1 : 0;
59 //=================================================================================================
60 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::subFeature(const int theIndex, bool forTree)
63 return std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
66 return std::shared_ptr<ModelAPI_Feature>();
69 //=================================================================================================
70 int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const
74 std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
76 return aFeature->data()->featureId();
83 //=================================================================================================
84 bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const
86 // Check is this feature of result
87 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
92 ObjectPtr aSub = data()->reference(SKETCH_ID())->value();
93 return aSub == theObject;
96 //=================================================================================================
97 void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
99 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
100 if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) {
101 aBaseObjectsSelectionList->clear();
104 reference(SKETCH_ID())->setValue(ObjectPtr());
107 //=================================================================================================
108 void FeaturesPlugin_CompositeSketch::erase()
110 if(data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid
111 FeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_Feature>(reference(SKETCH_ID())->value());
112 if(aSketch.get() && aSketch->data()->isValid()) {
113 document()->removeFeature(aSketch);
117 ModelAPI_CompositeFeature::erase();
120 //=================================================================================================
121 void FeaturesPlugin_CompositeSketch::setSketchObjectToList()
123 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
124 if(!aBaseObjectsSelectionList.get() || aBaseObjectsSelectionList->isInitialized()) {
128 AttributeReferencePtr aSketchLauncherRef = reference(SKETCH_ID());
129 if(!aSketchLauncherRef.get() || !aSketchLauncherRef->isInitialized()) {
133 FeaturePtr aSketchFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aSketchLauncherRef->value());
135 if(!aSketchFeature.get() || aSketchFeature->results().empty()) {
139 ResultPtr aSketchRes = aSketchFeature->results().front();
140 ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSketchRes);
141 if(!aConstruction.get()) {
145 if(aBaseObjectsSelectionList->size() == 0) {
146 aBaseObjectsSelectionList->append(aSketchRes, GeomShapePtr());
150 //=================================================================================================
151 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
152 const bool theIsMakeShells)
154 theBaseShapesList.clear();
156 ListOfShape aBaseFacesList;
157 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
158 if(!aBaseObjectsSelectionList.get()) {
159 setError("Error: Could not get base objects selection list.");
162 if(aBaseObjectsSelectionList->size() == 0) {
163 setError("Error: Base objects list is empty.");
166 for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
167 AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
168 if(!aBaseObjectSelection.get()) {
169 setError("Error: One of the selected base objects is empty.");
172 GeomShapePtr aBaseShape = aBaseObjectSelection->value();
173 if(aBaseShape.get() && !aBaseShape->isNull()) {
174 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
175 if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE && aST != GeomAPI_Shape::WIRE &&
176 aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
177 setError("Error: Selected shapes has unsupported type.");
180 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
181 theBaseShapesList.push_back(aBaseShape);
183 // This may be the whole sketch result selected, check and get faces.
184 ResultConstructionPtr aConstruction =
185 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
186 if(!aConstruction.get()) {
187 setError("Error: One of selected sketches does not have results.");
190 int aFacesNum = aConstruction->facesNum();
192 // Probably it can be construction.
193 aBaseShape = aConstruction->shape();
194 if(aBaseShape.get() && !aBaseShape->isNull()) {
195 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
196 if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE && aST != GeomAPI_Shape::WIRE &&
197 aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
198 setError("Error: Selected shapes has unsupported type.");
201 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
202 theBaseShapesList.push_back(aBaseShape);
205 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
206 GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
207 if(!aBaseFace.get() || aBaseFace->isNull()) {
208 setError("Error: One of the faces on selected sketch is Null.");
211 aBaseFacesList.push_back(aBaseFace);
217 // Searching faces with common edges.
218 if(theIsMakeShells) {
220 ListOfShape aFreeFaces;
221 GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
222 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces);
223 theBaseShapesList.insert(theBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
224 theBaseShapesList.insert(theBaseShapesList.end(), aShells.begin(), aShells.end());
226 theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
230 //=================================================================================================
231 bool FeaturesPlugin_CompositeSketch::isMakeShapeValid(const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
233 // Check that algo is done.
234 if(!theMakeShape->isDone()) {
235 setError("Error: " + getKind() + " algorithm failed.");
239 // Check if shape is not null.
240 if(!theMakeShape->shape().get() || theMakeShape->shape()->isNull()) {
241 setError("Error: Resulting shape is null.");
245 // Check that resulting shape is valid.
246 if(!theMakeShape->isValid()) {
247 setError("Error: Resulting shape is not valid.");
254 //=================================================================================================
255 void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape,
256 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
257 const int theResultIndex)
259 // Create result body.
260 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
262 // Store generated shape.
263 aResultBody->storeGenerated(theBaseShape, theMakeShape->shape());
265 // Store generated edges/faces.
267 storeGenerationHistory(aResultBody, theBaseShape, theMakeShape, aGenTag);
269 setResult(aResultBody, theResultIndex);
272 //=================================================================================================
273 void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody,
274 const GeomShapePtr theBaseShape,
275 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
278 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
279 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
280 std::string aGenName = "Generated_";
282 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
283 switch(aBaseShapeType) {
284 case GeomAPI_Shape::VERTEX: {
285 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
289 case GeomAPI_Shape::EDGE:
290 case GeomAPI_Shape::WIRE: {
291 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
292 GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
293 ListOfShape aV1History, aV2History;
294 theMakeShape->generated(aV1, aV1History);
295 theMakeShape->generated(aV2, aV2History);
296 theResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", theTag++);
297 theResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", theTag++);
299 case GeomAPI_Shape::FACE:
300 case GeomAPI_Shape::SHELL: {
301 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
306 theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, aShapeTypeToExplode,
307 theTag++, aGenName, *aMapOfSubShapes.get());
309 std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep = std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
310 if(aMakeSweep.get()) {
311 // Store from shapes.
312 storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes, aMakeSweep->fromShapes(), "From_", theTag);
315 storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes, aMakeSweep->toShapes(), "To_", theTag);
319 //=================================================================================================
320 void FeaturesPlugin_CompositeSketch::storeShapes(ResultBodyPtr theResultBody,
321 const GeomAPI_Shape::ShapeType theBaseShapeType,
322 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
323 const ListOfShape& theShapes,
324 const std::string theName,
327 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
328 std::string aShapeTypeStr = "Face";
329 switch(theBaseShapeType) {
330 case GeomAPI_Shape::VERTEX: {
331 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
332 aShapeTypeStr = "Vertex";
335 case GeomAPI_Shape::EDGE:
336 case GeomAPI_Shape::WIRE: {
337 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
338 aShapeTypeStr = "Edge";
341 case GeomAPI_Shape::FACE:
342 case GeomAPI_Shape::SHELL: {
343 aShapeTypeToExplore = GeomAPI_Shape::FACE;
344 aShapeTypeStr = "Face";
351 std::string aName = theName + aShapeTypeStr;
352 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
353 GeomShapePtr aShape = *anIt;
354 for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
355 GeomShapePtr aSubShape = anExp.current();
356 if(theMapOfSubShapes->isBound(aSubShape)) {
357 aSubShape = theMapOfSubShapes->find(aSubShape);
359 std::ostringstream aStr;
360 aStr << aName << "_" << aShapeIndex++;
361 theResultBody->generated(aSubShape, aStr.str(), theTag++);