1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
20 #include <FeaturesPlugin_CompositeSketch.h>
22 #include <ModelAPI_AttributeSelectionList.h>
23 #include <ModelAPI_AttributeReference.h>
24 #include <ModelAPI_BodyBuilder.h>
25 #include <ModelAPI_ResultConstruction.h>
26 #include <ModelAPI_Session.h>
27 #include <ModelAPI_Validator.h>
29 #include <GeomAlgoAPI_CompoundBuilder.h>
30 #include <GeomAlgoAPI_Prism.h>
31 #include <GeomAlgoAPI_Revolution.h>
32 #include <GeomAlgoAPI_ShapeTools.h>
33 #include <GeomAlgoAPI_SketchBuilder.h>
35 #include <GeomAPI_PlanarEdges.h>
36 #include <GeomAPI_ShapeExplorer.h>
41 static void storeSubShape(ResultBodyPtr theResultBody,
42 const GeomShapePtr theShape,
43 const GeomAPI_Shape::ShapeType theType,
44 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
45 const std::string theName,
49 //=================================================================================================
50 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
52 // Initialize sketch launcher.
53 if(theInitFlags & InitSketchLauncher) {
54 data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId());
55 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID());
58 // Initialize selection list.
59 if(theInitFlags & InitBaseObjectsList) {
60 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
64 //=================================================================================================
65 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::addFeature(std::string theID)
67 FeaturePtr aNew = document()->addFeature(theID, false);
69 data()->reference(SKETCH_ID())->setValue(aNew);
72 // Set as current also after it becomes sub to set correctly enabled for other sketch subs.
73 document()->setCurrentFeature(aNew, false);
77 //=================================================================================================
78 int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const
80 ObjectPtr aObj = data()->reference(SKETCH_ID())->value();
81 return aObj.get() ? 1 : 0;
84 //=================================================================================================
85 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::subFeature(const int theIndex,
89 return std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
92 return std::shared_ptr<ModelAPI_Feature>();
95 //=================================================================================================
96 int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const
100 std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
102 return aFeature->data()->featureId();
109 //=================================================================================================
110 bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const
112 // Check is this feature of result
113 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
114 if(!aFeature.get()) {
118 ObjectPtr aSub = data()->reference(SKETCH_ID())->value();
119 return aSub == theObject;
122 //=================================================================================================
123 void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
125 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
126 if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) {
127 aBaseObjectsSelectionList->clear();
130 reference(SKETCH_ID())->setValue(ObjectPtr());
133 //=================================================================================================
134 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
135 const bool theIsMakeShells)
137 theBaseShapesList.clear();
139 ListOfShape aBaseFacesList;
140 std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
141 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
142 if(!aBaseObjectsSelectionList.get()) {
143 setError("Error: Could not get base objects selection list.");
146 if(aBaseObjectsSelectionList->size() == 0) {
147 setError("Error: Base objects list is empty.");
150 for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
151 AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
152 if(!aBaseObjectSelection.get()) {
153 setError("Error: Selected base object is empty.");
156 GeomShapePtr aBaseShape = aBaseObjectSelection->value();
157 if(aBaseShape.get() && !aBaseShape->isNull()) {
158 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
159 if(aST == GeomAPI_Shape::SOLID || aST == GeomAPI_Shape::COMPSOLID) {
160 setError("Error: Selected shapes has unsupported type.");
163 ResultConstructionPtr aConstruction =
164 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
165 if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) &&
166 aST == GeomAPI_Shape::WIRE) {
167 // It is a wire on the sketch, store it to make face later.
168 aSketchWiresMap[aConstruction].push_back(aBaseShape);
171 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
172 theBaseShapesList.push_back(aBaseShape);
175 // This may be the whole sketch result selected, check and get faces.
176 ResultConstructionPtr aConstruction =
177 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
178 if(!aConstruction.get()) {
179 setError("Error: Selected sketches does not have results.");
182 int aFacesNum = aConstruction->facesNum();
184 // Probably it can be construction.
185 aBaseShape = aConstruction->shape();
186 if(aBaseShape.get() && !aBaseShape->isNull()) {
187 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
188 if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE &&
189 aST != GeomAPI_Shape::WIRE &&
190 aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
191 setError("Error: Selected shapes has unsupported type.");
194 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
195 theBaseShapesList.push_back(aBaseShape);
198 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
199 GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
200 if(!aBaseFace.get() || aBaseFace->isNull()) {
201 setError("Error: One of the faces on selected sketch is null.");
204 aBaseFacesList.push_back(aBaseFace);
210 // Make faces from sketch wires.
211 for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
212 anIt != aSketchWiresMap.cend(); ++anIt) {
213 const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
214 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
215 const ListOfShape& aWiresList = (*anIt).second;
217 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
218 aSketchPlanarEdges->norm(),
221 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
224 // Searching faces with common edges.
225 if(theIsMakeShells && aBaseFacesList.size() > 1) {
227 ListOfShape aFreeFaces;
228 GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
229 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL,
230 aShells, aFreeFaces);
231 theBaseShapesList.insert(theBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
232 theBaseShapesList.insert(theBaseShapesList.end(), aShells.begin(), aShells.end());
234 theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(),
235 aBaseFacesList.end());
239 //=================================================================================================
240 bool FeaturesPlugin_CompositeSketch::isMakeShapeValid(
241 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
243 // Check that algo is done.
244 if(!theMakeShape->isDone()) {
245 setError("Error: " + getKind() + " algorithm failed.");
249 // Check if shape is not null.
250 if(!theMakeShape->shape().get() || theMakeShape->shape()->isNull()) {
251 setError("Error: Resulting shape is null.");
255 // Check that resulting shape is valid.
256 if(!theMakeShape->isValid()) {
257 setError("Error: Resulting shape is not valid.");
264 //=================================================================================================
265 void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape,
266 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
269 // Create result body.
270 ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
272 // Store generated shape.
273 aResultBody->storeGenerated(theBaseShape, theMakeShape->shape());
275 // Store generated edges/faces.
277 storeGenerationHistory(aResultBody, theBaseShape, theMakeShape, aGenTag);
279 setResult(aResultBody, theIndex);
282 //=================================================================================================
283 void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody,
284 const GeomShapePtr theBaseShape,
285 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
288 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
289 GeomAPI_Shape::ShapeType aShapeTypeToExplode = GeomAPI_Shape::SHAPE;
290 std::string aGenName = "Generated_";
292 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
293 switch(aBaseShapeType) {
294 case GeomAPI_Shape::EDGE: {
295 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
298 case GeomAPI_Shape::WIRE: {
299 //std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
300 //GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
301 //ListOfShape aV1History, aV2History;
302 //theMakeShape->generated(aV1, aV1History);
303 //theMakeShape->generated(aV2, aV2History);
304 //if(!aV1History.empty()) {
305 // theResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", theTag++);
307 //if(!aV2History.empty()) {
308 // theResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", theTag++);
310 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
313 case GeomAPI_Shape::FACE:
314 case GeomAPI_Shape::SHELL: {
315 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
318 case GeomAPI_Shape::COMPOUND: {
319 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
323 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
324 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
325 theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape,
326 GeomAPI_Shape::VERTEX,
327 theTag++, aGenName + "Edge",
328 *aMapOfSubShapes.get());
330 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
331 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
332 theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(),
333 theBaseShape, GeomAPI_Shape::EDGE,
334 theTag++, aGenName + "Face",
335 *aMapOfSubShapes.get());
338 std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep =
339 std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
340 if(aMakeSweep.get()) {
341 // Store from shapes.
342 storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes,
343 aMakeSweep->fromShapes(), "From_", theTag);
346 storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes,
347 aMakeSweep->toShapes(), "To_", theTag);
351 //=================================================================================================
352 void FeaturesPlugin_CompositeSketch::storeShapes(ResultBodyPtr theResultBody,
353 const GeomAPI_Shape::ShapeType theBaseShapeType,
354 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
355 const ListOfShape& theShapes,
356 const std::string theName,
359 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
360 std::string aShapeTypeStr = "Face";
361 switch(theBaseShapeType) {
362 case GeomAPI_Shape::VERTEX: {
363 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
364 aShapeTypeStr = "Vertex";
367 case GeomAPI_Shape::EDGE:
368 case GeomAPI_Shape::WIRE: {
369 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
370 aShapeTypeStr = "Edge";
373 case GeomAPI_Shape::FACE:
374 case GeomAPI_Shape::SHELL: {
375 aShapeTypeToExplore = GeomAPI_Shape::FACE;
376 aShapeTypeStr = "Face";
379 case GeomAPI_Shape::COMPOUND: {
380 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
388 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
389 GeomShapePtr aShape = *anIt;
391 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
392 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
393 storeSubShape(theResultBody,
398 aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
401 std::string aName = theName + aShapeTypeStr;
402 storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
403 theMapOfSubShapes, aName, aShapeIndex, theTag);
408 void storeSubShape(ResultBodyPtr theResultBody,
409 const GeomShapePtr theShape,
410 const GeomAPI_Shape::ShapeType theType,
411 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
412 const std::string theName,
416 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
417 GeomShapePtr aSubShape = anExp.current();
418 if(theMapOfSubShapes->isBound(aSubShape)) {
419 aSubShape = theMapOfSubShapes->find(aSubShape);
421 std::ostringstream aStr;
422 aStr << theName << "_" << theShapeIndex++;
423 theResultBody->generated(aSubShape, aStr.str(), theTag++);