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 <GeomAlgoAPI_SketchBuilder.h>
22 #include <GeomAPI_PlanarEdges.h>
23 #include <GeomAPI_ShapeExplorer.h>
28 //=================================================================================================
29 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
31 // Initialize sketch launcher.
32 if(theInitFlags & InitSketchLauncher) {
33 data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId());
34 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID());
37 // Initialize selection list.
38 if(theInitFlags & InitBaseObjectsList) {
39 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
43 //=================================================================================================
44 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::addFeature(std::string theID)
46 FeaturePtr aNew = document()->addFeature(theID, false);
48 data()->reference(SKETCH_ID())->setValue(aNew);
51 // Set as current also after it becomes sub to set correctly enabled for other sketch subs.
52 document()->setCurrentFeature(aNew, false);
56 //=================================================================================================
57 int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const
59 ObjectPtr aObj = data()->reference(SKETCH_ID())->value();
60 return aObj.get() ? 1 : 0;
63 //=================================================================================================
64 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::subFeature(const int theIndex, bool forTree)
67 return std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
70 return std::shared_ptr<ModelAPI_Feature>();
73 //=================================================================================================
74 int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const
78 std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
80 return aFeature->data()->featureId();
87 //=================================================================================================
88 bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const
90 // Check is this feature of result
91 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
96 ObjectPtr aSub = data()->reference(SKETCH_ID())->value();
97 return aSub == theObject;
100 //=================================================================================================
101 void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
103 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
104 if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) {
105 aBaseObjectsSelectionList->clear();
108 reference(SKETCH_ID())->setValue(ObjectPtr());
111 //=================================================================================================
112 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
113 const bool theIsMakeShells)
115 theBaseShapesList.clear();
117 ListOfShape aBaseFacesList;
118 std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
119 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
120 if(!aBaseObjectsSelectionList.get()) {
121 setError("Error: Could not get base objects selection list.");
124 if(aBaseObjectsSelectionList->size() == 0) {
125 setError("Error: Base objects list is empty.");
128 for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
129 AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
130 if(!aBaseObjectSelection.get()) {
131 setError("Error: Selected base object is empty.");
134 GeomShapePtr aBaseShape = aBaseObjectSelection->value();
135 if(aBaseShape.get() && !aBaseShape->isNull()) {
136 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
137 if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE && aST != GeomAPI_Shape::WIRE &&
138 aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
139 setError("Error: Selected shapes has unsupported type.");
142 if(aST == GeomAPI_Shape::WIRE) {
143 ResultConstructionPtr aConstruction =
144 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
145 if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape())) {
146 // It is a wire on the sketch, store it to make face later.
147 aSketchWiresMap[aConstruction].push_back(aBaseShape);
151 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
152 theBaseShapesList.push_back(aBaseShape);
155 // This may be the whole sketch result selected, check and get faces.
156 ResultConstructionPtr aConstruction =
157 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
158 if(!aConstruction.get()) {
159 setError("Error: Selected sketches does not have results.");
162 int aFacesNum = aConstruction->facesNum();
164 // Probably it can be construction.
165 aBaseShape = aConstruction->shape();
166 if(aBaseShape.get() && !aBaseShape->isNull()) {
167 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
168 if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE && aST != GeomAPI_Shape::WIRE &&
169 aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
170 setError("Error: Selected shapes has unsupported type.");
173 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
174 theBaseShapesList.push_back(aBaseShape);
177 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
178 GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
179 if(!aBaseFace.get() || aBaseFace->isNull()) {
180 setError("Error: One of the faces on selected sketch is null.");
183 aBaseFacesList.push_back(aBaseFace);
189 // Make faces from sketch wires.
190 for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
191 anIt != aSketchWiresMap.cend(); ++anIt) {
192 const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
193 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
194 const ListOfShape& aWiresList = (*anIt).second;
196 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
197 aSketchPlanarEdges->norm(),
200 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
203 // Searching faces with common edges.
204 if(theIsMakeShells) {
206 ListOfShape aFreeFaces;
207 GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
208 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces);
209 theBaseShapesList.insert(theBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
210 theBaseShapesList.insert(theBaseShapesList.end(), aShells.begin(), aShells.end());
212 theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
216 //=================================================================================================
217 bool FeaturesPlugin_CompositeSketch::isMakeShapeValid(const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
219 // Check that algo is done.
220 if(!theMakeShape->isDone()) {
221 setError("Error: " + getKind() + " algorithm failed.");
225 // Check if shape is not null.
226 if(!theMakeShape->shape().get() || theMakeShape->shape()->isNull()) {
227 setError("Error: Resulting shape is null.");
231 // Check that resulting shape is valid.
232 if(!theMakeShape->isValid()) {
233 setError("Error: Resulting shape is not valid.");
240 //=================================================================================================
241 void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape,
242 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
243 const int theResultIndex)
245 // Create result body.
246 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
248 // Store generated shape.
249 aResultBody->storeGenerated(theBaseShape, theMakeShape->shape());
251 // Store generated edges/faces.
253 storeGenerationHistory(aResultBody, theBaseShape, theMakeShape, aGenTag);
255 setResult(aResultBody, theResultIndex);
258 //=================================================================================================
259 void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody,
260 const GeomShapePtr theBaseShape,
261 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
264 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
265 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
266 std::string aGenName = "Generated_";
268 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
269 switch(aBaseShapeType) {
270 case GeomAPI_Shape::VERTEX: {
271 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
275 case GeomAPI_Shape::EDGE:
276 case GeomAPI_Shape::WIRE: {
277 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
278 GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
279 ListOfShape aV1History, aV2History;
280 theMakeShape->generated(aV1, aV1History);
281 theMakeShape->generated(aV2, aV2History);
282 if(!aV1History.empty()) {
283 theResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", theTag++);
285 if(!aV2History.empty()) {
286 theResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", theTag++);
289 case GeomAPI_Shape::FACE:
290 case GeomAPI_Shape::SHELL: {
291 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
296 theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, aShapeTypeToExplode,
297 theTag++, aGenName, *aMapOfSubShapes.get());
299 std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep = std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
300 if(aMakeSweep.get()) {
301 // Store from shapes.
302 storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes, aMakeSweep->fromShapes(), "From_", theTag);
305 storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes, aMakeSweep->toShapes(), "To_", theTag);
309 //=================================================================================================
310 void FeaturesPlugin_CompositeSketch::storeShapes(ResultBodyPtr theResultBody,
311 const GeomAPI_Shape::ShapeType theBaseShapeType,
312 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
313 const ListOfShape& theShapes,
314 const std::string theName,
317 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
318 std::string aShapeTypeStr = "Face";
319 switch(theBaseShapeType) {
320 case GeomAPI_Shape::VERTEX: {
321 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
322 aShapeTypeStr = "Vertex";
325 case GeomAPI_Shape::EDGE:
326 case GeomAPI_Shape::WIRE: {
327 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
328 aShapeTypeStr = "Edge";
331 case GeomAPI_Shape::FACE:
332 case GeomAPI_Shape::SHELL: {
333 aShapeTypeToExplore = GeomAPI_Shape::FACE;
334 aShapeTypeStr = "Face";
341 std::string aName = theName + aShapeTypeStr;
342 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
343 GeomShapePtr aShape = *anIt;
344 for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
345 GeomShapePtr aSubShape = anExp.current();
346 if(theMapOfSubShapes->isBound(aSubShape)) {
347 aSubShape = theMapOfSubShapes->find(aSubShape);
349 std::ostringstream aStr;
350 aStr << aName << "_" << aShapeIndex++;
351 theResultBody->generated(aSubShape, aStr.str(), theTag++);